1 /*********************************************************************************
2 * SugarCRM Community Edition is a customer relationship management program developed by
3 * SugarCRM, Inc. Copyright (C) 2004-2012 SugarCRM Inc.
5 * This program is free software; you can redistribute it and/or modify it under
6 * the terms of the GNU Affero General Public License version 3 as published by the
7 * Free Software Foundation with the addition of the following permission added
8 * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
9 * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
10 * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
17 * You should have received a copy of the GNU Affero General Public License along with
18 * this program; if not, see http://www.gnu.org/licenses or write to the Free
19 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22 * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
23 * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
25 * The interactive user interfaces in modified source and object code versions
26 * of this program must display Appropriate Legal Notices, as required under
27 * Section 5 of the GNU Affero General Public License version 3.
29 * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
30 * these Appropriate Legal Notices must retain the display of the "Powered by
31 * SugarCRM" logo. If the display of the logo is not reasonably feasible for
32 * technical reasons, the Appropriate Legal Notices must display the words
33 * "Powered by SugarCRM".
34 ********************************************************************************/
38 //////////////////////////////////////////////////
39 // class: SugarWidgetListView
40 // widget to display a list view
42 //////////////////////////////////////////////////
44 SugarClass.inherit("SugarWidgetListView","SugarClass");
46 function SugarWidgetListView() {
50 SugarWidgetListView.prototype.init = function() {
54 SugarWidgetListView.prototype.load = function(parentNode) {
55 this.parentNode = parentNode;
59 SugarWidgetListView.prototype.display = function() {
61 if(typeof GLOBAL_REGISTRY['result_list'] == 'undefined') {
62 this.display_loading();
66 var div = document.getElementById('list_div_win');
67 div.style.display = 'block';
68 //div.style.height='125px';
69 var html = '<table width="100%" cellpadding="0" cellspacing="0" border="0" class="list view">';
71 html += '<th width="2%" nowrap="nowrap"> </th>';
72 html += '<th width="20%" nowrap="nowrap">'+GLOBAL_REGISTRY['meeting_strings']['LBL_NAME']+'</th>';
73 html += '<th width="20%" nowrap="nowrap">'+GLOBAL_REGISTRY['meeting_strings']['LBL_EMAIL']+'</th>';
74 html += '<th width="20%" nowrap="nowrap">'+GLOBAL_REGISTRY['meeting_strings']['LBL_PHONE']+'</th>';
75 html += '<th width="18%" nowrap="nowrap"> </th>';
77 //var html = '<table width="100%" cellpadding="0" cellspacing="0">';
78 for(var i=0;i<GLOBAL_REGISTRY['result_list'].length;i++) {
79 var bean = GLOBAL_REGISTRY['result_list'][i];
81 var className='evenListRowS1';
83 if(typeof(GLOBAL_REGISTRY.focus.users_arr_hash[ bean.fields.id]) != 'undefined') {
87 className='oddListRowS1';
89 className='evenListRowS1';
91 if(typeof (bean.fields.first_name) == 'undefined') {
92 bean.fields.first_name = '';
94 if(typeof (bean.fields.email1) == 'undefined' || bean.fields.email1 == "") {
95 bean.fields.email1 = ' ';
97 if(typeof (bean.fields.phone_work) == 'undefined' || bean.fields.phone_work == "") {
98 bean.fields.phone_work = ' ';
101 html += '<tr class="'+className+'">';
102 html += '<td><img src="'+GLOBAL_REGISTRY.config['site_url']+'/index.php?entryPoint=getImage&themeName='+SUGAR.themes.theme_name+'&imageName='+bean.module+'s.gif"/></td>';
103 html += '<td>'+bean.fields.full_name+'</td>';
104 html += '<td>'+bean.fields.email1+'</td>';
105 html += '<td>'+bean.fields.phone_work+'</td>';
106 html += '<td align="right">';
107 // hidden = 'hidden';
110 // hidden = 'visible';
112 html += '<input type="button" id="invitees_add_'+(i+1)+'" class="button" onclick="this.disabled=true;SugarWidgetSchedulerAttendees.form_add_attendee('+i+');" value="'+GLOBAL_REGISTRY['meeting_strings']['LBL_ADD_BUTTON']+'"/ style="visibility: '+hidden+'"/>';
118 //this.parentNode.innerHTML = html;
120 div.innerHTML = html;
123 SugarWidgetListView.prototype.display_loading = function() {
127 //////////////////////////////////////////////////
128 // class: SugarWidgetSchedulerSearch
129 // widget to display the meeting scheduler search box
131 //////////////////////////////////////////////////
133 SugarClass.inherit("SugarWidgetSchedulerSearch","SugarClass");
135 function SugarWidgetSchedulerSearch() {
139 SugarWidgetSchedulerSearch.prototype.init = function() {
140 this.form_id = 'scheduler_search';
141 GLOBAL_REGISTRY['widget_element_map'] = new Object();
142 GLOBAL_REGISTRY['widget_element_map'][this.form_id] = this;
143 GLOBAL_REGISTRY.scheduler_search_obj = this;
146 SugarWidgetSchedulerSearch.prototype.load = function(parentNode) {
147 this.parentNode = parentNode;
151 SugarWidgetSchedulerSearch.submit = function(form) {
153 SugarWidgetSchedulerSearch.hideCreateForm();
155 //construct query obj:
156 var conditions = new Array();
158 if(form.search_first_name.value != '') {
159 conditions[conditions.length] = {"name":"first_name","op":"starts_with","value":form.search_first_name.value}
161 if(form.search_last_name.value != '') {
162 conditions[conditions.length] = {"name":"last_name","op":"starts_with","value":form.search_last_name.value}
164 if(form.search_email.value != '') {
165 conditions[conditions.length] = {"name":"email1","op":"starts_with","value":form.search_email.value}
168 var query = {"modules":["Users","Contacts"
170 ],"group":"and","field_list":['id','full_name','email1','phone_work'],"conditions":conditions};
171 global_request_registry[req_count] = [this,'display'];
172 req_id = global_rpcClient.call_method('query',query);
173 global_request_registry[req_id] = [ GLOBAL_REGISTRY['widget_element_map'][form.id],'refresh_list'];
176 SugarWidgetSchedulerSearch.prototype.refresh_list = function(rslt) {
178 GLOBAL_REGISTRY['result_list'] = rslt['list'];
180 if (rslt['list'].length > 0) {
181 this.list_view.display();
182 document.getElementById('empty-search-message').style.display = 'none';
184 document.getElementById('list_div_win').style.display = 'none';
185 document.getElementById('empty-search-message').style.display = '';
190 SugarWidgetSchedulerSearch.prototype.display = function() {
191 var html ='<div class="schedulerInvitees"><h3>'+GLOBAL_REGISTRY['meeting_strings']['LBL_ADD_INVITEE']+'</h5><table border="0" cellpadding="0" cellspacing="0" width="100%" class="edit view">';
193 html += '<form name="schedulerwidget" id="'+this.form_id+'" onsubmit="SugarWidgetSchedulerSearch.submit(this);return false;">';
195 html += '<table width="100%" cellpadding="0" cellspacing="0" width="100%" >'
197 //html += '<form id="'+this.form_id+'"><table width="100%"><tbody><tr>';
198 html += '<td scope="col" nowrap><label for="search_first_name">'+GLOBAL_REGISTRY['meeting_strings']['LBL_FIRST_NAME']+':</label> <input name="search_first_name" id="search_first_name" value="" type="text" size="10"></td>';
199 html += '<td scope="col" nowrap><label for="search_last_name">'+GLOBAL_REGISTRY['meeting_strings']['LBL_LAST_NAME']+':</label> <input name="search_last_name" id="search_last_name" value="" type="text" size="10"></td>';
200 html += '<td scope="col" nowrap><label for="search_email">'+GLOBAL_REGISTRY['meeting_strings']['LBL_EMAIL']+':</label> <input name="search_email" id="search_email" type="text" value="" size="15"></td>';
201 //html += '<td valign="center"><input type="submit" onclick="SugarWidgetSchedulerSearch.submit(this.form);" value="Search" ></td></tr></tbody></table></form>';
202 html += '<td valign="center"><input id="invitees_search" type="submit" class="button" value="'+GLOBAL_REGISTRY['meeting_strings']['LBL_SEARCH_BUTTON']+'" ></td></tr>';
205 html += '</td></tr></table></div>';
207 // append the list_view as the third row of the outside table
208 this.parentNode.innerHTML += html;
211 var div = document.createElement('div');
212 div.setAttribute('id','list_div_win');
213 div.style.overflow = 'auto';
214 div.style.width = '100%';
215 div.style.height= '100%';
216 div.style.display = 'none';
217 this.parentNode.appendChild(div);
221 html += '<div id="create-invitees" style="margin-bottom: 10px;">';
222 html += '<div id="empty-search-message" style="display: none;">' + GLOBAL_REGISTRY['meeting_strings']['LBL_EMPTY_SEARCH_RESULT'] + '</div>';
223 html += '<h3 id="create-invitees-title">' + GLOBAL_REGISTRY['meeting_strings']['LBL_CREATE_INVITEE'] + '</h3>';
224 html += '<div id="create-invitees-buttons">';
225 html += '<button type="button" id="create_invitee_as_contact" onclick="SugarWidgetSchedulerSearch.showCreateForm(\'Contacts\');">' + GLOBAL_REGISTRY['meeting_strings']['LBL_CREATE_CONTACT'] + '</button> ';
226 html += '<button type="button" id="create_invitee_as_lead" onclick="SugarWidgetSchedulerSearch.showCreateForm(\'Leads\');">' + GLOBAL_REGISTRY['meeting_strings']['LBL_CREATE_LEAD'] + '</button> ';
229 html += '<div id="create-invitee-edit" style="display: none;">';
230 html += '<form name="createInviteeForm" id="createInviteeForm" onsubmit="SugarWidgetSchedulerSearch.createInvitee(this); return false;">';
231 html += '<input type="hidden" name="inviteeModule" value="Contacts">';
232 html += '<table class="edit view" cellpadding="0" cellspacing="0" style="width: 330px; margin-top: 2px;">'
234 html += '<td valign="top" width="33%">' + GLOBAL_REGISTRY['meeting_strings']['LBL_FIRST_NAME'] + ': </td><td valign="top"><input name="first_name" type="text" size="19"></td>';
237 html += '<td valign="top" width="33%">' + GLOBAL_REGISTRY['meeting_strings']['LBL_LAST_NAME'] + ': <span class="required">*</span></td><td valign="top"><input name="last_name" type="text" size="19"></td>';
240 html += '<td valign="top" width="33%">' + GLOBAL_REGISTRY['meeting_strings']['LBL_EMAIL'] + ': </td><td valign="top"><input name="email1" type="text" size="19"></td>';
243 html += '<button type="button" id="create-invitee-btn" onclick="SugarWidgetSchedulerSearch.createInvitee(this.form);">' + GLOBAL_REGISTRY['meeting_strings']['LBL_CREATE_AND_ADD'] + '</button> ';
244 html += '<button type="button" id="cancel-create-invitee-btn" onclick="SugarWidgetSchedulerSearch.hideCreateForm();">' + GLOBAL_REGISTRY['meeting_strings']['LBL_CANCEL_CREATE_INVITEE'] + '</button> ';
248 this.parentNode.innerHTML += html;
250 addToValidate('createInviteeForm', 'last_name', 'last_name', true, GLOBAL_REGISTRY['meeting_strings']['LBL_LAST_NAME']);
252 this.list_view = new SugarWidgetListView();
253 this.list_view.load(div);
256 SugarWidgetSchedulerSearch.showCreateForm = function(module){
257 document.getElementById('create-invitee-edit').style.display = '';
258 document.getElementById('create-invitees-buttons').style.display = 'none';
259 document.getElementById('list_div_win').style.display = 'none';
260 document.forms['createInviteeForm'].elements['inviteeModule'].value = module;
262 document.getElementById('empty-search-message').style.display = 'none';
264 if (typeof document.createInviteeForm.first_name != 'undefined' && typeof document.schedulerwidget.search_first_name != 'undefined')
265 document.createInviteeForm.first_name.value = document.schedulerwidget.search_first_name.value;
266 if (typeof document.createInviteeForm.last_name != 'undefined' && typeof document.schedulerwidget.search_last_name != 'undefined')
267 document.createInviteeForm.last_name.value = document.schedulerwidget.search_last_name.value;
268 if (typeof document.createInviteeForm.email1 != 'undefined' && typeof document.schedulerwidget.search_email != 'undefined')
269 document.createInviteeForm.email1.value = document.schedulerwidget.search_email.value;
273 SugarWidgetSchedulerSearch.hideCreateForm = function(module){
274 document.getElementById('create-invitee-edit').style.display = 'none';
275 document.getElementById('create-invitees-buttons').style.display = '';
277 document.forms['createInviteeForm'].reset();
280 SugarWidgetSchedulerSearch.resetSearchForm = function() {
281 if(GLOBAL_REGISTRY.scheduler_search_obj && document.forms[GLOBAL_REGISTRY.scheduler_search_obj.form_id]) {
282 //if search form is initiated, it clears the input fields.
283 document.forms[GLOBAL_REGISTRY.scheduler_search_obj.form_id].reset();
287 SugarWidgetSchedulerSearch.createInvitee = function(form){
288 if(!(check_form('createInviteeForm'))){
292 document.getElementById('create-invitee-btn').setAttribute('disabled', 'disabled');
293 document.getElementById('cancel-create-invitee-btn').setAttribute('disabled', 'disabled');
295 ajaxStatus.showStatus(SUGAR.language.get('app_strings', 'LBL_SAVING'));
298 success: function (response) {
300 var rObj = eval("("+response.responseText+")");
302 ajaxStatus.hideStatus();
304 if (typeof rObj.noAccess != 'undefined') {
305 var alertMsg = GLOBAL_REGISTRY['meeting_strings']['LBL_NO_ACCESS'];
306 alertMsg = alertMsg.replace("\$module", rObj.module);
307 SugarWidgetSchedulerSearch.hideCreateForm();
312 GLOBAL_REGISTRY.focus.users_arr[GLOBAL_REGISTRY.focus.users_arr.length] = rObj;
313 GLOBAL_REGISTRY.scheduler_attendees_obj.display();
315 SugarWidgetSchedulerSearch.hideCreateForm();
316 //Bug#51357: Reset the search input fields after invitee is added.
317 SugarWidgetSchedulerSearch.resetSearchForm();
319 document.getElementById('create-invitee-btn').removeAttribute('disabled');
320 document.getElementById('cancel-create-invitee-btn').removeAttribute('disabled');
324 var fieldList = ['id', 'full_name', 'email1', 'phone_work'];
327 for (i in fieldList) {
328 t.push("fieldList[]=" + encodeURIComponent(fieldList[i]));
330 var postData = t.join("&");
332 var url = "index.php?module=Calendar&action=CreateInvitee&sugar_body_only=true";
333 YAHOO.util.Connect.setForm(document.forms['createInviteeForm']);
334 YAHOO.util.Connect.asyncRequest('POST', url, callback, postData);
338 //////////////////////////////////////////////////
339 // class: SugarWidgetScheduler
340 // widget to display the meeting scheduler
342 //////////////////////////////////////////////////
344 SugarClass.inherit("SugarWidgetScheduler","SugarClass");
346 function SugarWidgetScheduler() {
350 SugarWidgetScheduler.prototype.init = function() {
351 //var row = new SugarWidgetScheduleAttendees();
355 SugarWidgetScheduler.prototype.load = function(parentNode) {
356 this.parentNode = parentNode;
360 SugarWidgetScheduler.fill_invitees = function(form) {
361 for(var i=0;i<GLOBAL_REGISTRY.focus.users_arr.length;i++) {
362 if(GLOBAL_REGISTRY.focus.users_arr[i].module == 'User') {
363 form.user_invitees.value += GLOBAL_REGISTRY.focus.users_arr[i].fields.id + ",";
364 } else if(GLOBAL_REGISTRY.focus.users_arr[i].module == 'Contact') {
365 form.contact_invitees.value += GLOBAL_REGISTRY.focus.users_arr[i].fields.id + ",";
366 } else if(GLOBAL_REGISTRY.focus.users_arr[i].module == 'Lead') {
367 form.lead_invitees.value += GLOBAL_REGISTRY.focus.users_arr[i].fields.id + ",";
372 SugarWidgetScheduler.update_time = function() {
375 if(typeof document.EditView != 'undefined')
376 form_name = "EditView";
377 else if(typeof document.CalendarEditView != 'undefined')
378 form_name = "CalendarEditView";
382 //check for field value, we can't do anything if it doesnt exist.
383 if(typeof document.forms[form_name].date_start == 'undefined')
386 var date_start = document.forms[form_name].date_start.value;
387 if(date_start.length < 16) {
390 var hour_start = parseInt(date_start.substring(11,13), 10);
391 var minute_start = parseInt(date_start.substring(14,16), 10);
392 var has_meridiem = /am|pm/i.test(date_start);
394 var meridiem = trim(date_start.substring(16));
397 GLOBAL_REGISTRY.focus.fields.date_start = date_start;
400 GLOBAL_REGISTRY.focus.fields.time_start = hour_start + time_separator + minute_start + meridiem;
402 GLOBAL_REGISTRY.focus.fields.time_start = hour_start + time_separator + minute_start;
405 GLOBAL_REGISTRY.focus.fields.duration_hours = document.forms[form_name].duration_hours.value;
406 GLOBAL_REGISTRY.focus.fields.duration_minutes = document.forms[form_name].duration_minutes.value;
407 GLOBAL_REGISTRY.focus.fields.datetime_start = SugarDateTime.mysql2jsDateTime(GLOBAL_REGISTRY.focus.fields.date_start,GLOBAL_REGISTRY.focus.fields.time_start);
409 GLOBAL_REGISTRY.scheduler_attendees_obj.init();
410 GLOBAL_REGISTRY.scheduler_attendees_obj.display();
413 SugarWidgetScheduler.prototype.display = function() {
414 this.parentNode.innerHTML = '';
416 var attendees = new SugarWidgetSchedulerAttendees();
417 attendees.load(this.parentNode);
419 var search = new SugarWidgetSchedulerSearch();
420 search.load(this.parentNode);
424 //////////////////////////////////////////////////
425 // class: SugarWidgetSchedulerAttendees
426 // widget to display the meeting attendees and availability
428 //////////////////////////////////////////////////
430 SugarClass.inherit("SugarWidgetSchedulerAttendees","SugarClass");
432 function SugarWidgetSchedulerAttendees() {
436 SugarWidgetSchedulerAttendees.prototype.init = function() {
438 // A list of modules which allow the parent to be in the invitees
439 SugarWidgetSchedulerAttendees.allowedTypes = ['Contact', 'Lead'];
441 $(document).ready(function()
443 // Hide the link label
444 $('#add_parent_invitee_label').css('visibility', 'hidden');
446 // Set visibility on load
447 SugarWidgetSchedulerAttendees.setAddParentLinkVisibility();
449 // Add listener for parent_type, so we can hide/unhide the link
450 $('#parent_type').change(function()
452 SugarWidgetSchedulerAttendees.setAddParentLinkVisibility();
457 if(typeof document.EditView != 'undefined')
458 form_name = "EditView";
459 else if(typeof document.CalendarEditView != 'undefined')
460 form_name = "CalendarEditView";
464 // this.datetime = new SugarDateTime();
465 GLOBAL_REGISTRY.scheduler_attendees_obj = this;
466 var date_start = document.forms[form_name].date_start.value;
467 var hour_start = parseInt(date_start.substring(11,13), 10);
468 var minute_start = parseInt(date_start.substring(14,16), 10);
469 var has_meridiem = /am|pm/i.test(date_start);
471 var meridiem = trim(date_start.substring(16));
475 GLOBAL_REGISTRY.focus.fields.time_start = hour_start + time_separator + minute_start + meridiem;
477 GLOBAL_REGISTRY.focus.fields.time_start = hour_start+time_separator+minute_start;
478 //GLOBAL_REGISTRY.focus.fields.time_start = document.forms[form_name].time_hour_start.value+time_separator+minute_start;
481 GLOBAL_REGISTRY.focus.fields.date_start = document.forms[form_name].date_start.value;
482 GLOBAL_REGISTRY.focus.fields.duration_hours = document.forms[form_name].duration_hours.value;
483 GLOBAL_REGISTRY.focus.fields.duration_minutes = document.forms[form_name].duration_minutes.value;
484 GLOBAL_REGISTRY.focus.fields.datetime_start = SugarDateTime.mysql2jsDateTime(GLOBAL_REGISTRY.focus.fields.date_start,GLOBAL_REGISTRY.focus.fields.time_start);
486 this.timeslots = new Array();
489 this.start_hours_before = 4;
491 var minute_interval = 15;
492 var dtstart = GLOBAL_REGISTRY.focus.fields.datetime_start;
494 // initialize first date in timeslots
495 var curdate = new Date(dtstart.getFullYear(),dtstart.getMonth(),dtstart.getDate(),dtstart.getHours()-this.start_hours_before,0);
497 if(typeof(GLOBAL_REGISTRY.focus.fields.duration_minutes) == 'undefined') {
498 GLOBAL_REGISTRY.focus.fields.duration_minutes = 0;
500 GLOBAL_REGISTRY.focus.fields.datetime_end = new Date(dtstart.getFullYear(),dtstart.getMonth(),dtstart.getDate(),dtstart.getHours()+parseInt(GLOBAL_REGISTRY.focus.fields.duration_hours),dtstart.getMinutes()+parseInt(GLOBAL_REGISTRY.focus.fields.duration_minutes),0);
502 var has_start = false;
505 for(i=0;i < this.hours*this.segments; i++) {
506 var hash = SugarDateTime.getUTCHash(curdate);
507 var obj = {"hash":hash,"date_obj":curdate};
508 if(has_start == false && GLOBAL_REGISTRY.focus.fields.datetime_start.getTime() <= curdate.getTime()) {
512 if(has_end == false && GLOBAL_REGISTRY.focus.fields.datetime_end.getTime() <= curdate.getTime()) {
516 this.timeslots.push(obj);
518 curdate = new Date(curdate.getFullYear(),curdate.getMonth(),curdate.getDate(),curdate.getHours(),curdate.getMinutes()+minute_interval);
520 //Bug#51357: Reset the search input fields after attandee popup is initiated.
521 SugarWidgetSchedulerSearch.resetSearchForm();
524 SugarWidgetSchedulerAttendees.prototype.load = function (parentNode) {
525 this.parentNode = parentNode;
529 SugarWidgetSchedulerAttendees.prototype.display = function() {
532 if(typeof document.EditView != 'undefined')
533 form_name = "EditView";
534 else if(typeof document.CalendarEditView != 'undefined')
535 form_name = "CalendarEditView";
539 var dtstart = GLOBAL_REGISTRY.focus.fields.datetime_start;
540 var top_date = SugarDateTime.getFormattedDate(dtstart);
541 var html = '<h3>'+GLOBAL_REGISTRY['meeting_strings']['LBL_SCHEDULING_FORM_TITLE']+'</h3><table id ="schedulerTable">';
542 html += '<tr class="schedulerTopRow">';
543 html += '<th colspan="'+((this.hours*this.segments)+2)+'"><h4>'+ top_date +'</h4></th>';
545 html += '<tr class="schedulerTimeRow">';
546 html += '<td> </td>';
548 for(var i=0;i < (this.timeslots.length/this.segments); i++) {
549 var hours = this.timeslots[i*this.segments].date_obj.getHours();
552 if(time_reg_format.indexOf('A') >= 0 || time_reg_format.indexOf('a') >= 0) {
566 if(time_reg_format.indexOf('a') >= 0) {
567 am_pm = am_pm.toLowerCase();
569 if(hours != 0 && hours != 12 && i != 0) {
575 var form_hours = hours+time_separator+"00";
576 html += '<th scope="col" colspan="'+this.segments+'">'+form_hours+am_pm+'</th>';
579 html += '<td> </td>';
582 if ( this.parentNode.childNodes.length < 1 )
583 this.parentNode.innerHTML += '<div class="schedulerDiv">' + html + '</div>';
585 this.parentNode.childNodes[0].innerHTML = html;
587 var thetable = "schedulerTable";
589 if(typeof (GLOBAL_REGISTRY) == 'undefined') {
593 //set the current user (as event-coordinator) so that they can be added to invitee list
594 //only IF the first removed flag has not been set AND this is a new record
595 if((typeof (GLOBAL_REGISTRY.focus.users_arr) == 'undefined' || GLOBAL_REGISTRY.focus.users_arr.length == 0)
596 && document.forms[form_name].record.value =='' && typeof(GLOBAL_REGISTRY.FIRST_REMOVE)=='undefined') {
597 GLOBAL_REGISTRY.focus.users_arr = [ GLOBAL_REGISTRY.current_user ];
600 if(typeof GLOBAL_REGISTRY.focus.users_arr_hash == 'undefined') {
601 GLOBAL_REGISTRY.focus.users_arr_hash = new Object();
604 // append attendee rows
605 for(var i=0;i < GLOBAL_REGISTRY.focus.users_arr.length;i++) {
606 var row = new SugarWidgetScheduleRow(this.timeslots);
607 row.focus_bean = GLOBAL_REGISTRY.focus.users_arr[i];
608 GLOBAL_REGISTRY.focus.users_arr_hash[ GLOBAL_REGISTRY.focus.users_arr[i]['fields']['id']] = GLOBAL_REGISTRY.focus.users_arr[i];
613 SugarWidgetSchedulerAttendees.form_add_attendee = function (list_row) {
614 if(typeof (GLOBAL_REGISTRY.result_list[list_row]) != 'undefined' && typeof(GLOBAL_REGISTRY.focus.users_arr_hash[ GLOBAL_REGISTRY.result_list[list_row].fields.id]) == 'undefined') {
615 GLOBAL_REGISTRY.focus.users_arr[ GLOBAL_REGISTRY.focus.users_arr.length ] = GLOBAL_REGISTRY.result_list[list_row];
617 GLOBAL_REGISTRY.scheduler_attendees_obj.display();
620 // Function sets the visibility of the Add Parent Link
621 SugarWidgetSchedulerAttendees.setAddParentLinkVisibility = function()
623 parent_type = $('#parent_type option:selected').text();
624 if ($.inArray(parent_type, SugarWidgetSchedulerAttendees.allowedTypes) > -1)
626 $('#add_parent_invitee').parent().css('display', '');
630 $('#add_parent_invitee').parent().css('display', 'none');
634 // Function used to add the parent to the invitees
635 SugarWidgetSchedulerAttendees.formAddParent = function()
637 parent_id = $("#parent_id").val();
638 parent_name = $("#parent_name").val();
639 parent_type = $("#parent_type option:selected").text();
641 // If it's an allowed parent type and the parent is selected, add it to the invitees
642 if (parent_id.length > 0 && $.inArray(parent_type, SugarWidgetSchedulerAttendees.allowedTypes) > -1)
646 {id:parent_id, full_name:parent_name},
650 for(var i = 0; i < GLOBAL_REGISTRY.focus.users_arr.length; i++)
652 if (GLOBAL_REGISTRY.focus.users_arr[i]['fields']['id'] == invitee['fields']['id'])
661 GLOBAL_REGISTRY.focus.users_arr[GLOBAL_REGISTRY.focus.users_arr.length] = invitee;
662 GLOBAL_REGISTRY.scheduler_attendees_obj.display();
667 //////////////////////////////////////////////////
668 // class: SugarWidgetScheduleRow
669 // widget to display each row in the scheduler
671 //////////////////////////////////////////////////
672 SugarClass.inherit("SugarWidgetScheduleRow","SugarClass");
674 function SugarWidgetScheduleRow(timeslots) {
675 this.init(timeslots);
678 SugarWidgetScheduleRow.prototype.init = function(timeslots) {
679 this.timeslots = timeslots;
682 SugarWidgetScheduleRow.prototype.load = function (thetableid) {
683 this.thetableid = thetableid;
686 vcalClient = new SugarVCalClient();
687 if(typeof (GLOBAL_REGISTRY['freebusy_adjusted']) == 'undefined' || typeof (GLOBAL_REGISTRY['freebusy_adjusted'][this.focus_bean.fields.id]) == 'undefined') {
688 global_request_registry[req_count] = [this,'display'];
689 vcalClient.load(this.focus_bean.fields.id,req_count);
696 SugarWidgetScheduleRow.prototype.display = function() {
697 SUGAR.util.doWhen("document.getElementById('" + this.thetableid + "') != null", function(){
699 this.thetable = document.getElementById(this.thetableid);
701 if(typeof (this.element) != 'undefined') {
702 if (this.element.parentNode != null)
703 this.thetable.deleteRow(this.element.rowIndex);
705 tr = document.createElement('tr');
706 this.thetable.appendChild(tr);
708 tr = this.thetable.insertRow(this.thetable.rows.length);
710 tr.className = "schedulerAttendeeRow";
712 td = document.createElement('td');
714 //insertCell(tr.cells.length);
718 var img = '<img align="absmiddle" src="index.php?entryPoint=getImage&themeName='
719 + SUGAR.themes.theme_name+'&imageName='+this.focus_bean.module+'s.gif"/> ';
722 td.innerHTML = td.innerHTML;
724 if (this.focus_bean.fields.full_name)
725 td.innerHTML += ' ' + this.focus_bean.fields.full_name;
727 td.innerHTML += ' ' + this.focus_bean.fields.name;
729 // add freebusy tds here:
730 this.add_freebusy_nodes(tr);
733 var td = document.createElement('td');
735 //var td = tr.insertCell(tr.cells.length);
736 td.className = 'schedulerAttendeeDeleteCell';
738 //CCL - Remove check to disallow removal of assigned user or current user
739 //if ( GLOBAL_REGISTRY.focus.fields.assigned_user_id != this.focus_bean.fields.id && GLOBAL_REGISTRY.current_user.fields.id != this.focus_bean.fields.id) {
740 td.innerHTML = '<a title="'+ GLOBAL_REGISTRY['meeting_strings']['LBL_REMOVE']
741 + '" class="listViewTdToolsS1" style="text-decoration:none;" '
742 + 'href="javascript:SugarWidgetScheduleRow.deleteRow(\''+this.focus_bean.fields.id+'\');"> '
743 + '<img src="index.php?entryPoint=getImage&themeName='+SUGAR.themes.theme_name+'&imageName=delete_inline.gif" '
744 + 'align="absmiddle" alt="'+ GLOBAL_REGISTRY['meeting_strings']['LBL_REMOVE'] +'" border="0"> '
745 + GLOBAL_REGISTRY['meeting_strings']['LBL_REMOVE'] +'</a>';
748 this.element_index = this.thetable.rows.length - 1;
752 SugarWidgetScheduleRow.deleteRow = function(bean_id) {
753 // can't delete organizer
755 if(GLOBAL_REGISTRY.focus.users_arr.length == 1 || GLOBAL_REGISTRY.focus.fields.assigned_user_id == bean_id) {
759 for(var i=0;i<GLOBAL_REGISTRY.focus.users_arr.length;i++) {
760 if(GLOBAL_REGISTRY.focus.users_arr[i]['fields']['id']==bean_id) {
761 delete GLOBAL_REGISTRY.focus.users_arr_hash[GLOBAL_REGISTRY.focus.users_arr[i]['fields']['id']];
762 GLOBAL_REGISTRY.focus.users_arr.splice(i,1);
763 //set first remove flag to true for processing in display() function
764 GLOBAL_REGISTRY.FIRST_REMOVE = true;
765 GLOBAL_REGISTRY.container.root_widget.display();
771 function DL_GetElementLeft(eElement) {
773 * ifargument is invalid
774 * (not specified, is null or is 0)
775 * and function is a method
776 * identify the element as the method owner
778 if(!eElement && this) {
783 * initialize var to store calculations
784 * identify first offset parent element
785 * move up through element hierarchy
786 * appending left offset of each parent
787 * until no more offset parents exist
789 var nLeftPos = eElement.offsetLeft;
790 var eParElement = eElement.offsetParent;
791 while (eParElement != null) {
792 nLeftPos += eParElement.offsetLeft;
793 eParElement = eParElement.offsetParent;
795 return nLeftPos; // return the number calculated
799 function DL_GetElementTop(eElement) {
800 if(!eElement && this) {
804 var nTopPos = eElement.offsetTop;
805 var eParElement = eElement.offsetParent;
806 while (eParElement != null) {
807 nTopPos += eParElement.offsetTop;
808 eParElement = eParElement.offsetParent;
814 //////////////////////////////////////////
815 // adds the <td>s for freebusy display within a row
816 SugarWidgetScheduleRow.prototype.add_freebusy_nodes = function(tr,attendee) {
820 var is_loaded = false;
822 if(typeof GLOBAL_REGISTRY['freebusy_adjusted'] != 'undefined' && typeof GLOBAL_REGISTRY['freebusy_adjusted'][this.focus_bean.fields.id] != 'undefined') {
826 for(var i=0;i < this.timeslots.length; i++) {
827 var td = document.createElement('td');
829 //var td = tr.insertCell(tr.cells.length);
830 td.innerHTML = ' ';
831 if(typeof(this.timeslots[i]['is_start']) != 'undefined') {
832 td.className = 'schedulerSlotCellStartTime';
834 if(typeof(this.timeslots[i]['is_end']) != 'undefined') {
835 td.className = 'schedulerSlotCellEndTime';
839 // iftheres a freebusy stack in this slice
840 if( typeof(GLOBAL_REGISTRY['freebusy_adjusted'][this.focus_bean.fields.id][this.timeslots[i].hash]) != 'undefined') {
841 td.style.backgroundColor="#4D5EAA";
843 if( GLOBAL_REGISTRY['freebusy_adjusted'][this.focus_bean.fields.id][this.timeslots[i].hash] > 1) {
844 td.style.backgroundColor="#AA4D4D";