]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - jssource/src_files/modules/Meetings/jsclass_scheduler.js
Release 6.5.16
[Github/sugarcrm.git] / jssource / src_files / modules / Meetings / jsclass_scheduler.js
1 /*********************************************************************************
2  * SugarCRM Community Edition is a customer relationship management program developed by
3  * SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
4  * 
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.
11  * 
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
15  * details.
16  * 
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
20  * 02110-1301 USA.
21  * 
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.
24  * 
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.
28  * 
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  ********************************************************************************/
35
36
37
38 //////////////////////////////////////////////////
39 // class: SugarWidgetListView
40 // widget to display a list view
41 //
42 //////////////////////////////////////////////////
43
44 SugarClass.inherit("SugarWidgetListView","SugarClass");
45
46 function SugarWidgetListView() {
47         this.init();
48 }
49
50 SugarWidgetListView.prototype.init = function() {
51
52 }
53
54 SugarWidgetListView.prototype.load = function(parentNode) {
55         this.parentNode = parentNode;
56         this.display();
57 }
58
59 SugarWidgetListView.prototype.display = function() {
60
61         if(typeof GLOBAL_REGISTRY['result_list'] == 'undefined') {
62                 this.display_loading();
63                 return;
64         }
65
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">';
70         html += '<tr>';
71         html += '<th width="2%" nowrap="nowrap">&nbsp;</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">&nbsp;</th>';
76         html += '</tr>';
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];
80                 var disabled = false;
81                 var className='evenListRowS1';
82
83                 if(typeof(GLOBAL_REGISTRY.focus.users_arr_hash[ bean.fields.id]) != 'undefined') {
84                         disabled = true;
85                 }
86                 if((i%2) == 0) {
87                         className='oddListRowS1';
88                 } else {
89                         className='evenListRowS1';
90                 }
91                 if(typeof (bean.fields.first_name) == 'undefined') {
92                         bean.fields.first_name = '';
93                 }
94                 if(typeof (bean.fields.email1) == 'undefined' || bean.fields.email1 == "") {
95                         bean.fields.email1 = '&nbsp;';
96                 }
97                 if(typeof (bean.fields.phone_work) == 'undefined' || bean.fields.phone_work == "") {
98                         bean.fields.phone_work = '&nbsp;';
99                 }
100
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';
108                 hidden = 'visible';
109                 if(!disabled) {
110                         //      hidden = 'visible';
111                 }
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+'"/>';
113                 html += '</td>';
114
115                 html += '</tr>';
116         }
117         html += '</table>';
118         //this.parentNode.innerHTML = html;
119
120         div.innerHTML = html;
121 }
122
123 SugarWidgetListView.prototype.display_loading = function() {
124
125 }
126
127 //////////////////////////////////////////////////
128 // class: SugarWidgetSchedulerSearch
129 // widget to display the meeting scheduler search box
130 //
131 //////////////////////////////////////////////////
132
133 SugarClass.inherit("SugarWidgetSchedulerSearch","SugarClass");
134
135 function SugarWidgetSchedulerSearch() {
136         this.init();
137 }
138
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;
144 }
145
146 SugarWidgetSchedulerSearch.prototype.load = function(parentNode) {
147         this.parentNode = parentNode;
148         this.display();
149 }
150
151 SugarWidgetSchedulerSearch.submit = function(form) {
152
153         SugarWidgetSchedulerSearch.hideCreateForm();
154
155         //construct query obj:
156         var conditions  = new Array();
157
158         if(form.search_first_name.value != '') {
159                 conditions[conditions.length] = {"name":"first_name","op":"starts_with","value":form.search_first_name.value}
160         }
161         if(form.search_last_name.value != '') {
162                 conditions[conditions.length] = {"name":"last_name","op":"starts_with","value":form.search_last_name.value}
163         }
164         if(form.search_email.value != '') {
165                 conditions[conditions.length] = {"name":"email1","op":"starts_with","value":form.search_email.value}
166         }
167
168         var query = {"modules":["Users","Contacts"
169         ,"Leads"
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'];
174 }
175
176 SugarWidgetSchedulerSearch.prototype.refresh_list = function(rslt) {
177
178         GLOBAL_REGISTRY['result_list'] = rslt['list'];
179
180         if (rslt['list'].length > 0) {
181                 this.list_view.display();
182                 document.getElementById('empty-search-message').style.display = 'none';
183         }else{
184                 document.getElementById('list_div_win').style.display = 'none';
185                 document.getElementById('empty-search-message').style.display = '';
186         }
187
188 }
189
190 SugarWidgetSchedulerSearch.prototype.display = function() {
191
192         // append the list_view as the third row of the outside table
193         var html = document.createElement("div");
194         html.setAttribute('class','schedulerInvitees');
195
196         var h3 = document.createElement("h3");
197         h3.innerHTML = GLOBAL_REGISTRY['meeting_strings']['LBL_ADD_INVITEE'];
198         html.appendChild(h3);
199
200         var table1 = document.createElement("table");
201         table1.setAttribute('class','edit view');
202         table1.setAttribute('border','0');
203         table1.setAttribute('cellpadding','0');
204         table1.setAttribute('cellspacing','0');
205         table1.setAttribute('width','100%');
206         var row1 = table1.insertRow(0);
207         var cell1 = row1.insertCell(0);
208
209         var form = document.createElement("form");
210         form.setAttribute('name','schedulerwidget');
211         form.setAttribute('id',this.form_id);
212         form.setAttribute('onsubmit','SugarWidgetSchedulerSearch.submit(this);return false;');
213
214         var table2 = document.createElement("table");
215         table2.setAttribute('border','0');
216         table2.setAttribute('cellpadding','0');
217         table2.setAttribute('cellspacing','0');
218         table2.setAttribute('width','100%');
219
220         var row2 = table2.insertRow(0);
221         var cell21 = row2.insertCell(0);
222         cell21.setAttribute('scope','col');
223         cell21.setAttribute('nowrap','nowrap');
224
225         var label1 = document.createElement("label");
226         label1.setAttribute('for','search_first_name');
227         label1.innerHTML = GLOBAL_REGISTRY['meeting_strings']['LBL_FIRST_NAME']+':&nbsp;&nbsp;';
228         cell21.appendChild(label1);
229
230         var input1 = document.createElement("input");
231         input1.setAttribute('name','search_first_name');
232         input1.setAttribute('id','search_first_name');
233         input1.setAttribute('value','');
234         input1.setAttribute('type','text');
235         input1.setAttribute('size','10');
236         cell21.appendChild(input1);
237
238         var cell22 = row2.insertCell(1);
239         cell22.setAttribute('scope','col');
240         cell22.setAttribute('nowrap','nowrap');
241
242         var label2 = document.createElement("label");
243         label2.setAttribute('for','search_last_name');
244         label2.innerHTML = GLOBAL_REGISTRY['meeting_strings']['LBL_LAST_NAME']+':&nbsp;&nbsp;';
245         cell22.appendChild(label2);
246
247         var input2 = document.createElement("input");
248         input2.setAttribute('name','search_last_name');
249         input2.setAttribute('id','search_last_name');
250         input2.setAttribute('value','');
251         input2.setAttribute('type','text');
252         input2.setAttribute('size','10');
253         cell22.appendChild(input2);
254
255         var cell23 = row2.insertCell(2);
256         cell23.setAttribute('scope','col');
257         cell23.setAttribute('nowrap','nowrap');
258
259         var label3 = document.createElement("label");
260         label3.setAttribute('for','search_email');
261         label3.innerHTML = GLOBAL_REGISTRY['meeting_strings']['LBL_EMAIL']+':&nbsp;&nbsp;';
262         cell23.appendChild(label3);
263
264         var input3 = document.createElement("input");
265         input3.setAttribute('name','search_email');
266         input3.setAttribute('id','search_email');
267         input3.setAttribute('value','');
268         input3.setAttribute('type','text');
269         input3.setAttribute('size','10');
270         cell23.appendChild(input3);
271
272         var cell24 = row2.insertCell(3);
273         cell24.setAttribute('valign','center');
274
275         var input3 = document.createElement("input");
276         input3.setAttribute('class','button');
277         input3.setAttribute('id','invitees_search');
278         input3.setAttribute('value',GLOBAL_REGISTRY['meeting_strings']['LBL_SEARCH_BUTTON']);
279         input3.setAttribute('type','submit');
280         cell24.appendChild(input3);
281
282         form.appendChild(table2);
283         cell1.appendChild(form);
284         html.appendChild(table1);
285
286         this.parentNode.appendChild(html);
287
288         var div = document.createElement('div');
289         div.setAttribute('id','list_div_win');
290         div.style.overflow = 'auto';
291         div.style.width = '100%';
292         div.style.height= '100%';
293         div.style.display = 'none';
294         this.parentNode.appendChild(div);
295
296         var create_invitees = document.createElement("div");
297         create_invitees.setAttribute('id','create-invitees');
298         create_invitees.setAttribute('style','margin-bottom: 10px;');
299
300         var empty_search_message = document.createElement("div");
301         empty_search_message.setAttribute('id','empty-search-message');
302         empty_search_message.setAttribute('style','display: none;');
303         empty_search_message.innerHTML = GLOBAL_REGISTRY['meeting_strings']['LBL_EMPTY_SEARCH_RESULT'];
304         create_invitees.appendChild(empty_search_message);
305
306         var h3 = document.createElement("h3");
307         h3.setAttribute('id', 'create-invitees-title');
308         h3.innerHTML = GLOBAL_REGISTRY['meeting_strings']['LBL_CREATE_INVITEE'];
309         create_invitees.appendChild(h3);
310
311         var create_invitees_buttons = document.createElement("div");
312         create_invitees_buttons.setAttribute('id','create-invitees-buttons');
313
314         var button1 = document.createElement("button");
315         button1.setAttribute('id', 'create_invitee_as_contact');
316         button1.setAttribute('type', 'button');
317         button1.setAttribute('onclick', 'SugarWidgetSchedulerSearch.showCreateForm(\'Contacts\');');
318         button1.innerHTML = GLOBAL_REGISTRY['meeting_strings']['LBL_CREATE_CONTACT'];
319         create_invitees_buttons.appendChild(button1);
320
321         var button2 = document.createElement("button");
322         button2.setAttribute('id', 'create_invitee_as_lead');
323         button2.setAttribute('type', 'button');
324         button2.setAttribute('onclick', 'SugarWidgetSchedulerSearch.showCreateForm(\'Leads\');');
325         button2.innerHTML = GLOBAL_REGISTRY['meeting_strings']['LBL_CREATE_LEAD'];
326         create_invitees_buttons.appendChild(button2);
327         create_invitees.appendChild(create_invitees_buttons);
328
329         var create_invitee_edit = document.createElement("div");
330         create_invitee_edit.setAttribute('id','create-invitee-edit');
331         create_invitee_edit.setAttribute('style','display: none;');
332
333         var form1 = document.createElement("form");
334         form1.setAttribute('name','createInviteeForm');
335         form1.setAttribute('id','createInviteeForm');
336         form1.setAttribute('onsubmit','SugarWidgetSchedulerSearch.createInvitee(this); return false;');
337
338         var input4 = document.createElement("input");
339         input4.setAttribute('name','inviteeModule');
340         input4.setAttribute('value','Contacts');
341         input4.setAttribute('type','hidden');
342         form1.appendChild(input4);
343
344         var table3 = document.createElement("table");
345         table3.setAttribute('class','edit view');
346         table3.setAttribute('cellpadding','0');
347         table3.setAttribute('cellspacing','0');
348         table3.setAttribute('style','width: 330px; margin-top: 2px;');
349
350         var row3 = table3.insertRow(0);
351         var cell31 = row3.insertCell(0);
352         cell31.setAttribute('valign','top');
353         cell31.setAttribute('width','33%');
354         cell31.innerHTML = GLOBAL_REGISTRY['meeting_strings']['LBL_FIRST_NAME']+':';
355
356         var cell32 = row3.insertCell(1);
357         cell32.setAttribute('valign','top');
358
359         var input5 = document.createElement("input");
360         input5.setAttribute('name','first_name');
361         input5.setAttribute('size','19');
362         input5.setAttribute('type','text');
363         cell32.appendChild(input5);
364
365         var row4 = table3.insertRow(1);
366         var cell41 = row4.insertCell(0);
367         cell41.setAttribute('valign','top');
368         cell41.setAttribute('width','33%');
369         cell41.innerHTML = GLOBAL_REGISTRY['meeting_strings']['LBL_LAST_NAME']+':';
370
371         var cell42 = row4.insertCell(1);
372         cell42.setAttribute('valign','top');
373
374         var input6 = document.createElement("input");
375         input6.setAttribute('name','last_name');
376         input6.setAttribute('size','19');
377         input6.setAttribute('type','text');
378         cell42.appendChild(input6);
379
380         var row5 = table3.insertRow(2);
381         var cell51 = row5.insertCell(0);
382         cell51.setAttribute('valign','top');
383         cell51.setAttribute('width','33%');
384         cell51.innerHTML = GLOBAL_REGISTRY['meeting_strings']['LBL_EMAIL']+':';
385
386         var cell52 = row5.insertCell(1);
387         cell52.setAttribute('valign','top');
388
389         var input7 = document.createElement("input");
390         input7.setAttribute('name','email1');
391         input7.setAttribute('size','19');
392         input7.setAttribute('type','text');
393         cell52.appendChild(input7);
394
395         form1.appendChild(table3);
396
397         var button3 = document.createElement("button");
398         button3.setAttribute('id', 'create-invitee-btn');
399         button3.setAttribute('type', 'button');
400         button3.setAttribute('onclick', 'SugarWidgetSchedulerSearch.createInvitee(this.form);');
401         button3.innerHTML = GLOBAL_REGISTRY['meeting_strings']['LBL_CREATE_AND_ADD'];
402         form1.appendChild(button3);
403
404         var button4 = document.createElement("button");
405         button4.setAttribute('id', 'cancel-create-invitee-btn');
406         button4.setAttribute('type', 'button');
407         button4.setAttribute('onclick', 'SugarWidgetSchedulerSearch.hideCreateForm();');
408         button4.innerHTML = GLOBAL_REGISTRY['meeting_strings']['LBL_CANCEL_CREATE_INVITEE'];
409         form1.appendChild(button4);
410
411         create_invitee_edit.appendChild(form1);
412         create_invitees.appendChild(create_invitee_edit);
413         this.parentNode.appendChild(create_invitees);
414
415         addToValidate('createInviteeForm', 'last_name', 'last_name', true, GLOBAL_REGISTRY['meeting_strings']['LBL_LAST_NAME']);
416
417     this.list_view = new SugarWidgetListView();
418         this.list_view.load(div);
419 }
420
421 SugarWidgetSchedulerSearch.showCreateForm = function(module){
422         document.getElementById('create-invitee-edit').style.display = '';
423         document.getElementById('create-invitees-buttons').style.display = 'none';
424         document.getElementById('list_div_win').style.display = 'none';
425         document.forms['createInviteeForm'].elements['inviteeModule'].value = module;
426
427         document.getElementById('empty-search-message').style.display = 'none';
428
429         if (typeof document.createInviteeForm.first_name != 'undefined' && typeof document.schedulerwidget.search_first_name != 'undefined')
430                 document.createInviteeForm.first_name.value = document.schedulerwidget.search_first_name.value;
431         if (typeof document.createInviteeForm.last_name != 'undefined' && typeof document.schedulerwidget.search_last_name != 'undefined')
432                 document.createInviteeForm.last_name.value = document.schedulerwidget.search_last_name.value;
433         if (typeof document.createInviteeForm.email1 != 'undefined' && typeof document.schedulerwidget.search_email != 'undefined')
434                 document.createInviteeForm.email1.value = document.schedulerwidget.search_email.value;
435
436 }
437
438 SugarWidgetSchedulerSearch.hideCreateForm = function(module){
439         document.getElementById('create-invitee-edit').style.display = 'none';
440         document.getElementById('create-invitees-buttons').style.display = '';
441
442         document.forms['createInviteeForm'].reset();
443 }
444
445 SugarWidgetSchedulerSearch.resetSearchForm = function() {
446     if(GLOBAL_REGISTRY.scheduler_search_obj && document.forms[GLOBAL_REGISTRY.scheduler_search_obj.form_id]) {
447         //if search form is initiated, it clears the input fields.
448         document.forms[GLOBAL_REGISTRY.scheduler_search_obj.form_id].reset();
449     }
450 }
451
452 SugarWidgetSchedulerSearch.createInvitee = function(form){
453         if(!(check_form('createInviteeForm'))){
454                 return false;
455         }
456
457         document.getElementById('create-invitee-btn').setAttribute('disabled', 'disabled');
458         document.getElementById('cancel-create-invitee-btn').setAttribute('disabled', 'disabled');
459
460         ajaxStatus.showStatus(SUGAR.language.get('app_strings', 'LBL_SAVING'));
461
462         var callback = {
463                 success: function (response) {
464
465                         var rObj = eval("("+response.responseText+")");
466
467                         ajaxStatus.hideStatus();
468
469                         if (typeof rObj.noAccess != 'undefined') {
470                                 var alertMsg = GLOBAL_REGISTRY['meeting_strings']['LBL_NO_ACCESS'];
471                                 alertMsg = alertMsg.replace("\$module", rObj.module);
472                                 SugarWidgetSchedulerSearch.hideCreateForm();
473                                 alert(alertMsg);
474                                 return false;
475                         }
476
477                         GLOBAL_REGISTRY.focus.users_arr[GLOBAL_REGISTRY.focus.users_arr.length] = rObj;
478                         GLOBAL_REGISTRY.scheduler_attendees_obj.display();
479
480                         SugarWidgetSchedulerSearch.hideCreateForm();
481             //Bug#51357: Reset the search input fields after invitee is added.
482             SugarWidgetSchedulerSearch.resetSearchForm();
483
484                         document.getElementById('create-invitee-btn').removeAttribute('disabled');
485                         document.getElementById('cancel-create-invitee-btn').removeAttribute('disabled');
486                 }
487         };
488
489         var fieldList = ['id', 'full_name', 'email1', 'phone_work'];
490
491         var t = [];
492         for (i in fieldList) {
493                 t.push("fieldList[]=" + encodeURIComponent(fieldList[i]));
494         }
495         var postData = t.join("&");
496
497         var url = "index.php?module=Calendar&action=CreateInvitee&sugar_body_only=true";
498         YAHOO.util.Connect.setForm(document.forms['createInviteeForm']);
499         YAHOO.util.Connect.asyncRequest('POST', url, callback, postData);
500
501 }
502
503 //////////////////////////////////////////////////
504 // class: SugarWidgetScheduler
505 // widget to display the meeting scheduler
506 //
507 //////////////////////////////////////////////////
508
509 SugarClass.inherit("SugarWidgetScheduler","SugarClass");
510
511 function SugarWidgetScheduler() {
512         this.init();
513 }
514
515 SugarWidgetScheduler.prototype.init = function() {
516         //var row = new SugarWidgetScheduleAttendees();
517         //row.load(this);
518 }
519
520 SugarWidgetScheduler.prototype.load = function(parentNode) {
521         this.parentNode = parentNode;
522         this.display();
523 }
524
525 SugarWidgetScheduler.fill_invitees = function(form) {
526         for(var i=0;i<GLOBAL_REGISTRY.focus.users_arr.length;i++) {
527                 if(GLOBAL_REGISTRY.focus.users_arr[i].module == 'User') {
528                         form.user_invitees.value += GLOBAL_REGISTRY.focus.users_arr[i].fields.id + ",";
529                 } else if(GLOBAL_REGISTRY.focus.users_arr[i].module == 'Contact') {
530                         form.contact_invitees.value += GLOBAL_REGISTRY.focus.users_arr[i].fields.id + ",";
531                 } else if(GLOBAL_REGISTRY.focus.users_arr[i].module == 'Lead') {
532                         form.lead_invitees.value += GLOBAL_REGISTRY.focus.users_arr[i].fields.id + ",";
533                 }
534         }
535 }
536
537 SugarWidgetScheduler.update_time = function() {
538
539         var form_name;
540         if(typeof document.EditView != 'undefined')
541                 form_name = "EditView";
542         else if(typeof document.CalendarEditView != 'undefined')
543                 form_name = "CalendarEditView";
544         else
545                 return;
546
547    //check for field value, we can't do anything if it doesnt exist.
548     if(typeof document.forms[form_name].date_start == 'undefined')
549                 return;
550
551         var date_start = document.forms[form_name].date_start.value;
552         if(date_start.length < 16) {
553                 return;
554         }
555         var hour_start = parseInt(date_start.substring(11,13), 10);
556         var minute_start = parseInt(date_start.substring(14,16), 10);
557         var has_meridiem = /am|pm/i.test(date_start);
558         if(has_meridiem) {
559         var meridiem = trim(date_start.substring(16));
560         }
561
562         GLOBAL_REGISTRY.focus.fields.date_start = date_start;
563
564         if(has_meridiem) {
565                 GLOBAL_REGISTRY.focus.fields.time_start = hour_start + time_separator + minute_start + meridiem;
566         } else {
567                 GLOBAL_REGISTRY.focus.fields.time_start = hour_start + time_separator + minute_start;
568         }
569
570         GLOBAL_REGISTRY.focus.fields.duration_hours = document.forms[form_name].duration_hours.value;
571         GLOBAL_REGISTRY.focus.fields.duration_minutes = document.forms[form_name].duration_minutes.value;
572         GLOBAL_REGISTRY.focus.fields.datetime_start = SugarDateTime.mysql2jsDateTime(GLOBAL_REGISTRY.focus.fields.date_start,GLOBAL_REGISTRY.focus.fields.time_start);
573
574         GLOBAL_REGISTRY.scheduler_attendees_obj.init();
575         GLOBAL_REGISTRY.scheduler_attendees_obj.display();
576 }
577
578 SugarWidgetScheduler.prototype.display = function() {
579     this.parentNode.innerHTML = '';
580
581         var attendees = new SugarWidgetSchedulerAttendees();
582         attendees.load(this.parentNode);
583
584         var search = new SugarWidgetSchedulerSearch();
585         search.load(this.parentNode);
586 }
587
588
589 //////////////////////////////////////////////////
590 // class: SugarWidgetSchedulerAttendees
591 // widget to display the meeting attendees and availability
592 //
593 //////////////////////////////////////////////////
594
595 SugarClass.inherit("SugarWidgetSchedulerAttendees","SugarClass");
596
597 function SugarWidgetSchedulerAttendees() {
598         this.init();
599 }
600
601 SugarWidgetSchedulerAttendees.prototype.init = function() {
602
603         var form_name;
604         if(typeof document.EditView != 'undefined')
605                 form_name = "EditView";
606         else if(typeof document.CalendarEditView != 'undefined')
607                 form_name = "CalendarEditView";
608         else
609                 return;
610
611         // this.datetime = new SugarDateTime();
612         GLOBAL_REGISTRY.scheduler_attendees_obj = this;
613         var date_start = document.forms[form_name].date_start.value;
614         var hour_start = parseInt(date_start.substring(11,13), 10);
615         var minute_start = parseInt(date_start.substring(14,16), 10);
616         var has_meridiem = /am|pm/i.test(date_start);
617         if(has_meridiem) {
618         var meridiem = trim(date_start.substring(16));
619         }
620
621         if(has_meridiem) {
622                 GLOBAL_REGISTRY.focus.fields.time_start = hour_start + time_separator + minute_start + meridiem;
623         } else {
624                 GLOBAL_REGISTRY.focus.fields.time_start = hour_start+time_separator+minute_start;
625                 //GLOBAL_REGISTRY.focus.fields.time_start = document.forms[form_name].time_hour_start.value+time_separator+minute_start;
626         }
627
628         GLOBAL_REGISTRY.focus.fields.date_start = document.forms[form_name].date_start.value;
629         GLOBAL_REGISTRY.focus.fields.duration_hours = document.forms[form_name].duration_hours.value;
630         GLOBAL_REGISTRY.focus.fields.duration_minutes = document.forms[form_name].duration_minutes.value;
631         GLOBAL_REGISTRY.focus.fields.datetime_start = SugarDateTime.mysql2jsDateTime(GLOBAL_REGISTRY.focus.fields.date_start,GLOBAL_REGISTRY.focus.fields.time_start);
632
633         this.timeslots = new Array();
634         this.hours = 9;
635         this.segments = 4;
636         this.start_hours_before = 4;
637
638         var minute_interval = 15;
639         var dtstart = GLOBAL_REGISTRY.focus.fields.datetime_start;
640
641         // initialize first date in timeslots
642         var curdate = new Date(dtstart.getFullYear(),dtstart.getMonth(),dtstart.getDate(),dtstart.getHours()-this.start_hours_before,0);
643
644         if(typeof(GLOBAL_REGISTRY.focus.fields.duration_minutes) == 'undefined') {
645                 GLOBAL_REGISTRY.focus.fields.duration_minutes = 0;
646         }
647         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);
648
649         var has_start = false;
650         var has_end = false;
651
652         for(i=0;i < this.hours*this.segments; i++) {
653                 var hash = SugarDateTime.getUTCHash(curdate);
654                 var obj = {"hash":hash,"date_obj":curdate};
655                 if(has_start == false && GLOBAL_REGISTRY.focus.fields.datetime_start.getTime() <= curdate.getTime()) {
656                         obj.is_start = true;
657                         has_start = true;
658                 }
659                 if(has_end == false && GLOBAL_REGISTRY.focus.fields.datetime_end.getTime() <= curdate.getTime()) {
660                         obj.is_end = true;
661                         has_end = true;
662                 }
663                 this.timeslots.push(obj);
664
665                 curdate = new Date(curdate.getFullYear(),curdate.getMonth(),curdate.getDate(),curdate.getHours(),curdate.getMinutes()+minute_interval);
666         }
667     //Bug#51357: Reset the search input fields after attandee popup is initiated.
668     SugarWidgetSchedulerSearch.resetSearchForm();
669 }
670
671 SugarWidgetSchedulerAttendees.prototype.load = function (parentNode) {
672         this.parentNode = parentNode;
673         this.display();
674 }
675
676 SugarWidgetSchedulerAttendees.prototype.display = function() {
677
678         var form_name;
679         if(typeof document.EditView != 'undefined')
680                 form_name = "EditView";
681         else if(typeof document.CalendarEditView != 'undefined')
682                 form_name = "CalendarEditView";
683         else
684                 return;
685
686         var dtstart = GLOBAL_REGISTRY.focus.fields.datetime_start;
687         var top_date = SugarDateTime.getFormattedDate(dtstart);
688         var html = '<h3>'+GLOBAL_REGISTRY['meeting_strings']['LBL_SCHEDULING_FORM_TITLE']+'</h3><table id ="schedulerTable">';
689         html += '<tr class="schedulerTopRow">';
690         html += '<th colspan="'+((this.hours*this.segments)+2)+'"><h4>'+ top_date +'</h4></th>';
691         html += '</tr>';
692         html += '<tr class="schedulerTimeRow">';
693         html += '<td>&nbsp;</td>';
694
695         for(var i=0;i < (this.timeslots.length/this.segments); i++) {
696                 var hours = this.timeslots[i*this.segments].date_obj.getHours();
697                 var am_pm = '';
698
699                 if(time_reg_format.indexOf('A') >= 0 || time_reg_format.indexOf('a') >= 0) {
700                         am_pm = "AM";
701
702                         if(hours > 12) {
703                                 am_pm = "PM";
704                                 hours -= 12;
705                         }
706                         if(hours == 12) {
707                                 am_pm = "PM";
708                         }
709                         if(hours == 0) {
710                                 hours = 12;
711                                 am_pm = "AM";
712                         }
713                         if(time_reg_format.indexOf('a') >= 0) {
714                                 am_pm = am_pm.toLowerCase();
715                         }
716                         if(hours != 0 && hours != 12 && i != 0) {
717                                 am_pm = "";
718                         }
719
720                 }
721
722                 var form_hours = hours+time_separator+"00";
723                 html += '<th scope="col" colspan="'+this.segments+'">'+form_hours+am_pm+'</th>';
724         }
725
726         html += '<td>&nbsp;</td>';
727         html += '</tr>';
728         html += '</table>';
729     if ( this.parentNode.childNodes.length < 1 )
730         this.parentNode.innerHTML += '<div class="schedulerDiv">' + html + '</div>';
731     else
732         this.parentNode.childNodes[0].innerHTML = html;
733
734         var thetable = "schedulerTable";
735
736         if(typeof (GLOBAL_REGISTRY) == 'undefined') {
737                 return;
738         }
739
740         //set the current user (as event-coordinator) so that they can be added to invitee list
741         //only IF the first removed flag has not been set AND this is a new record
742         if((typeof (GLOBAL_REGISTRY.focus.users_arr) == 'undefined' || GLOBAL_REGISTRY.focus.users_arr.length == 0)
743       && document.forms[form_name].record.value =='' && typeof(GLOBAL_REGISTRY.FIRST_REMOVE)=='undefined') {
744                 GLOBAL_REGISTRY.focus.users_arr = [ GLOBAL_REGISTRY.current_user ];
745         }
746
747         if(typeof GLOBAL_REGISTRY.focus.users_arr_hash == 'undefined') {
748                 GLOBAL_REGISTRY.focus.users_arr_hash = new Object();
749         }
750
751         // append attendee rows
752         for(var i=0;i < GLOBAL_REGISTRY.focus.users_arr.length;i++) {
753                 var row = new SugarWidgetScheduleRow(this.timeslots);
754                 row.focus_bean = GLOBAL_REGISTRY.focus.users_arr[i];
755                 GLOBAL_REGISTRY.focus.users_arr_hash[ GLOBAL_REGISTRY.focus.users_arr[i]['fields']['id']] =     GLOBAL_REGISTRY.focus.users_arr[i];
756                 row.load(thetable);
757         }
758 }
759
760 SugarWidgetSchedulerAttendees.form_add_attendee = function (list_row) {
761         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') {
762                 GLOBAL_REGISTRY.focus.users_arr[ GLOBAL_REGISTRY.focus.users_arr.length ] = GLOBAL_REGISTRY.result_list[list_row];
763         }
764         GLOBAL_REGISTRY.scheduler_attendees_obj.display();
765 }
766
767
768 //////////////////////////////////////////////////
769 // class: SugarWidgetScheduleRow
770 // widget to display each row in the scheduler
771 //
772 //////////////////////////////////////////////////
773 SugarClass.inherit("SugarWidgetScheduleRow","SugarClass");
774
775 function SugarWidgetScheduleRow(timeslots) {
776         this.init(timeslots);
777 }
778
779 SugarWidgetScheduleRow.prototype.init = function(timeslots) {
780         this.timeslots = timeslots;
781 }
782
783 SugarWidgetScheduleRow.prototype.load = function (thetableid) {
784         this.thetableid = thetableid;
785         var self = this;
786
787         vcalClient = new SugarVCalClient();
788         if(typeof (GLOBAL_REGISTRY['freebusy_adjusted']) == 'undefined' ||      typeof (GLOBAL_REGISTRY['freebusy_adjusted'][this.focus_bean.fields.id]) == 'undefined') {
789                 global_request_registry[req_count] = [this,'display'];
790                 vcalClient.load(this.focus_bean.fields.id,req_count);
791                 req_count++;
792         } else {
793                 this.display();
794         }
795 }
796
797 SugarWidgetScheduleRow.prototype.display = function() {
798         SUGAR.util.doWhen("document.getElementById('" + this.thetableid + "') != null", function(){
799         var tr;
800         this.thetable = document.getElementById(this.thetableid);
801
802         if(typeof (this.element) != 'undefined') {
803             if (this.element.parentNode != null)
804                 this.thetable.deleteRow(this.element.rowIndex);
805
806             tr = document.createElement('tr');
807             this.thetable.appendChild(tr);
808         } else {
809             tr = this.thetable.insertRow(this.thetable.rows.length);
810         }
811         tr.className = "schedulerAttendeeRow";
812
813         td = document.createElement('td');
814         tr.appendChild(td);
815         //insertCell(tr.cells.length);
816
817         // icon + full name
818         td.scope = 'row';
819         var img = '<img align="absmiddle" src="index.php?entryPoint=getImage&themeName='
820                 + SUGAR.themes.theme_name+'&imageName='+this.focus_bean.module+'s.gif"/>&nbsp;';
821         td.innerHTML = img;
822
823         td.innerHTML = td.innerHTML;
824
825         if (this.focus_bean.fields.full_name)
826             td.innerHTML += ' ' + this.focus_bean.fields.full_name;
827         else
828             td.innerHTML += ' ' + this.focus_bean.fields.name;
829
830         // add freebusy tds here:
831         this.add_freebusy_nodes(tr);
832
833         // delete button
834         var td = document.createElement('td');
835         tr.appendChild(td);
836         //var td = tr.insertCell(tr.cells.length);
837         td.className = 'schedulerAttendeeDeleteCell';
838         td.noWrap = true;
839         //CCL - Remove check to disallow removal of assigned user or current user
840         //if ( GLOBAL_REGISTRY.focus.fields.assigned_user_id != this.focus_bean.fields.id && GLOBAL_REGISTRY.current_user.fields.id != this.focus_bean.fields.id) {
841        td.innerHTML = '<a title="'+ GLOBAL_REGISTRY['meeting_strings']['LBL_REMOVE']
842                     + '" class="listViewTdToolsS1" style="text-decoration:none;" '
843                     + 'href="javascript:SugarWidgetScheduleRow.deleteRow(\''+this.focus_bean.fields.id+'\');">&nbsp;'
844                     + '<img src="index.php?entryPoint=getImage&themeName='+SUGAR.themes.theme_name+'&imageName=delete_inline.gif" '
845                     + 'align="absmiddle" alt="'+ GLOBAL_REGISTRY['meeting_strings']['LBL_REMOVE'] +'" border="0"> '
846                     + GLOBAL_REGISTRY['meeting_strings']['LBL_REMOVE'] +'</a>';
847         //}
848         this.element = tr;
849         this.element_index = this.thetable.rows.length - 1;
850     }, null, this);
851 }
852
853 SugarWidgetScheduleRow.deleteRow = function(bean_id) {
854         // can't delete organizer
855         /*
856         if(GLOBAL_REGISTRY.focus.users_arr.length == 1 || GLOBAL_REGISTRY.focus.fields.assigned_user_id == bean_id) {
857                 return;
858         }
859     */
860         for(var i=0;i<GLOBAL_REGISTRY.focus.users_arr.length;i++) {
861                 if(GLOBAL_REGISTRY.focus.users_arr[i]['fields']['id']==bean_id) {
862                         delete GLOBAL_REGISTRY.focus.users_arr_hash[GLOBAL_REGISTRY.focus.users_arr[i]['fields']['id']];
863                         GLOBAL_REGISTRY.focus.users_arr.splice(i,1);
864                 //set first remove flag to true for processing in display() function
865                         GLOBAL_REGISTRY.FIRST_REMOVE = true;
866                         GLOBAL_REGISTRY.container.root_widget.display();
867                 }
868         }
869 }
870
871
872 function DL_GetElementLeft(eElement) {
873         /*
874          * ifargument is invalid
875          * (not specified, is null or is 0)
876          * and function is a method
877          * identify the element as the method owner
878          */
879         if(!eElement && this) {
880                 eElement = this;
881         }
882
883         /*
884          * initialize var to store calculations
885          * identify first offset parent element
886          * move up through element hierarchy
887          * appending left offset of each parent
888          * until no more offset parents exist
889          */
890         var nLeftPos = eElement.offsetLeft;
891         var eParElement = eElement.offsetParent;
892         while (eParElement != null) {
893                 nLeftPos += eParElement.offsetLeft;
894                 eParElement = eParElement.offsetParent;
895         }
896         return nLeftPos; // return the number calculated
897 }
898
899
900 function DL_GetElementTop(eElement) {
901         if(!eElement && this) {
902                 eElement = this;
903         }
904
905         var nTopPos = eElement.offsetTop;
906         var eParElement = eElement.offsetParent;
907         while (eParElement != null) {
908                 nTopPos += eParElement.offsetTop;
909                 eParElement = eParElement.offsetParent;
910         }
911         return nTopPos;
912 }
913
914
915 //////////////////////////////////////////
916 // adds the <td>s for freebusy display within a row
917 SugarWidgetScheduleRow.prototype.add_freebusy_nodes = function(tr,attendee) {
918         var hours = 9;
919         var segments = 4;
920         var html = '';
921         var is_loaded = false;
922
923         if(typeof GLOBAL_REGISTRY['freebusy_adjusted'] != 'undefined' && typeof GLOBAL_REGISTRY['freebusy_adjusted'][this.focus_bean.fields.id] != 'undefined') {
924                 is_loaded = true;
925         }
926
927         for(var i=0;i < this.timeslots.length; i++) {
928                 var td = document.createElement('td');
929                 tr.appendChild(td);
930                 //var td = tr.insertCell(tr.cells.length);
931         td.innerHTML = '&nbsp;';
932                 if(typeof(this.timeslots[i]['is_start']) != 'undefined') {
933                         td.className = 'schedulerSlotCellStartTime';
934                 }
935                 if(typeof(this.timeslots[i]['is_end']) != 'undefined') {
936                         td.className = 'schedulerSlotCellEndTime';
937                 }
938
939                 if(is_loaded) {
940                         // iftheres a freebusy stack in this slice
941                         if(     typeof(GLOBAL_REGISTRY['freebusy_adjusted'][this.focus_bean.fields.id][this.timeslots[i].hash]) != 'undefined') {
942                                 td.style.backgroundColor="#4D5EAA";
943
944                                 if(     GLOBAL_REGISTRY['freebusy_adjusted'][this.focus_bean.fields.id][this.timeslots[i].hash] > 1) {
945                                         td.style.backgroundColor="#AA4D4D";
946                                 }
947                         }
948                 }
949         }
950 }