]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - jssource/src_files/modules/Meetings/jsclass_scheduler.js
Release 6.5.6
[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-2012 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         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">';
192         html +='<tr><td>';
193         html += '<form name="schedulerwidget" id="'+this.form_id+'" onsubmit="SugarWidgetSchedulerSearch.submit(this);return false;">';
194
195         html += '<table width="100%" cellpadding="0" cellspacing="0" width="100%" >'
196         html += '<tr>';
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>&nbsp;&nbsp;<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>&nbsp;&nbsp;<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>&nbsp;&nbsp;<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>';
203         html += '</table>';
204         html += '</form>';
205         html += '</td></tr></table></div>';
206
207         // append the list_view as the third row of the outside table
208         this.parentNode.innerHTML += html;
209
210
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);
218
219
220         html = '';
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> ';
227         html += '</div>';
228
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;">'
233         html += '<tr>';
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>';
235         html += '</tr>';
236         html += '<tr>';
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>';
238         html += '</tr>';
239         html += '<tr>';
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>';
241         html += '</tr>';
242         html += '</table>';
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> ';
245         html += '</form>';
246         html += '</div>';
247         html += '</div>';
248         this.parentNode.innerHTML += html;
249
250         addToValidate('createInviteeForm', 'last_name', 'last_name', true, GLOBAL_REGISTRY['meeting_strings']['LBL_LAST_NAME']);
251
252     this.list_view = new SugarWidgetListView();
253         this.list_view.load(div);
254 }
255
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;
261
262         document.getElementById('empty-search-message').style.display = 'none';
263
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;
270
271 }
272
273 SugarWidgetSchedulerSearch.hideCreateForm = function(module){
274         document.getElementById('create-invitee-edit').style.display = 'none';
275         document.getElementById('create-invitees-buttons').style.display = '';
276
277         document.forms['createInviteeForm'].reset();
278 }
279
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();
284     }
285 }
286
287 SugarWidgetSchedulerSearch.createInvitee = function(form){
288         if(!(check_form('createInviteeForm'))){
289                 return false;
290         }
291
292         document.getElementById('create-invitee-btn').setAttribute('disabled', 'disabled');
293         document.getElementById('cancel-create-invitee-btn').setAttribute('disabled', 'disabled');
294
295         ajaxStatus.showStatus(SUGAR.language.get('app_strings', 'LBL_SAVING'));
296
297         var callback = {
298                 success: function (response) {
299
300                         var rObj = eval("("+response.responseText+")");
301
302                         ajaxStatus.hideStatus();
303
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();
308                                 alert(alertMsg);
309                                 return false;
310                         }
311
312                         GLOBAL_REGISTRY.focus.users_arr[GLOBAL_REGISTRY.focus.users_arr.length] = rObj;
313                         GLOBAL_REGISTRY.scheduler_attendees_obj.display();
314
315                         SugarWidgetSchedulerSearch.hideCreateForm();
316             //Bug#51357: Reset the search input fields after invitee is added.
317             SugarWidgetSchedulerSearch.resetSearchForm();
318
319                         document.getElementById('create-invitee-btn').removeAttribute('disabled');
320                         document.getElementById('cancel-create-invitee-btn').removeAttribute('disabled');
321                 }
322         };
323
324         var fieldList = ['id', 'full_name', 'email1', 'phone_work'];
325
326         var t = [];
327         for (i in fieldList) {
328                 t.push("fieldList[]=" + encodeURIComponent(fieldList[i]));
329         }
330         var postData = t.join("&");
331
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);
335
336 }
337
338 //////////////////////////////////////////////////
339 // class: SugarWidgetScheduler
340 // widget to display the meeting scheduler
341 //
342 //////////////////////////////////////////////////
343
344 SugarClass.inherit("SugarWidgetScheduler","SugarClass");
345
346 function SugarWidgetScheduler() {
347         this.init();
348 }
349
350 SugarWidgetScheduler.prototype.init = function() {
351         //var row = new SugarWidgetScheduleAttendees();
352         //row.load(this);
353 }
354
355 SugarWidgetScheduler.prototype.load = function(parentNode) {
356         this.parentNode = parentNode;
357         this.display();
358 }
359
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 + ",";
368                 }
369         }
370 }
371
372 SugarWidgetScheduler.update_time = function() {
373
374         var form_name;
375         if(typeof document.EditView != 'undefined')
376                 form_name = "EditView";
377         else if(typeof document.CalendarEditView != 'undefined')
378                 form_name = "CalendarEditView";
379         else
380                 return;
381
382    //check for field value, we can't do anything if it doesnt exist.
383     if(typeof document.forms[form_name].date_start == 'undefined')
384                 return;
385
386         var date_start = document.forms[form_name].date_start.value;
387         if(date_start.length < 16) {
388                 return;
389         }
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);
393         if(has_meridiem) {
394         var meridiem = trim(date_start.substring(16));
395         }
396
397         GLOBAL_REGISTRY.focus.fields.date_start = date_start;
398
399         if(has_meridiem) {
400                 GLOBAL_REGISTRY.focus.fields.time_start = hour_start + time_separator + minute_start + meridiem;
401         } else {
402                 GLOBAL_REGISTRY.focus.fields.time_start = hour_start + time_separator + minute_start;
403         }
404
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);
408
409         GLOBAL_REGISTRY.scheduler_attendees_obj.init();
410         GLOBAL_REGISTRY.scheduler_attendees_obj.display();
411 }
412
413 SugarWidgetScheduler.prototype.display = function() {
414     this.parentNode.innerHTML = '';
415
416         var attendees = new SugarWidgetSchedulerAttendees();
417         attendees.load(this.parentNode);
418
419         var search = new SugarWidgetSchedulerSearch();
420         search.load(this.parentNode);
421 }
422
423
424 //////////////////////////////////////////////////
425 // class: SugarWidgetSchedulerAttendees
426 // widget to display the meeting attendees and availability
427 //
428 //////////////////////////////////////////////////
429
430 SugarClass.inherit("SugarWidgetSchedulerAttendees","SugarClass");
431
432 function SugarWidgetSchedulerAttendees() {
433         this.init();
434 }
435
436 SugarWidgetSchedulerAttendees.prototype.init = function() {
437
438         // A list of modules which allow the parent to be in the invitees
439         SugarWidgetSchedulerAttendees.allowedTypes = ['Contact', 'Lead'];
440         
441         $(document).ready(function()
442         {
443                 // Hide the link label
444                 $('#add_parent_invitee_label').css('visibility', 'hidden');
445                 
446                 // Set visibility on load
447                 SugarWidgetSchedulerAttendees.setAddParentLinkVisibility();
448                 
449                 // Add listener for parent_type, so we can hide/unhide the link
450                 $('#parent_type').change(function()
451                 {
452                         SugarWidgetSchedulerAttendees.setAddParentLinkVisibility();
453                 });
454         });
455         
456         var form_name;
457         if(typeof document.EditView != 'undefined')
458                 form_name = "EditView";
459         else if(typeof document.CalendarEditView != 'undefined')
460                 form_name = "CalendarEditView";
461         else
462                 return;
463
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);
470         if(has_meridiem) {
471         var meridiem = trim(date_start.substring(16));
472         }
473
474         if(has_meridiem) {
475                 GLOBAL_REGISTRY.focus.fields.time_start = hour_start + time_separator + minute_start + meridiem;
476         } else {
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;
479         }
480
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);
485
486         this.timeslots = new Array();
487         this.hours = 9;
488         this.segments = 4;
489         this.start_hours_before = 4;
490
491         var minute_interval = 15;
492         var dtstart = GLOBAL_REGISTRY.focus.fields.datetime_start;
493
494         // initialize first date in timeslots
495         var curdate = new Date(dtstart.getFullYear(),dtstart.getMonth(),dtstart.getDate(),dtstart.getHours()-this.start_hours_before,0);
496
497         if(typeof(GLOBAL_REGISTRY.focus.fields.duration_minutes) == 'undefined') {
498                 GLOBAL_REGISTRY.focus.fields.duration_minutes = 0;
499         }
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);
501
502         var has_start = false;
503         var has_end = false;
504
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()) {
509                         obj.is_start = true;
510                         has_start = true;
511                 }
512                 if(has_end == false && GLOBAL_REGISTRY.focus.fields.datetime_end.getTime() <= curdate.getTime()) {
513                         obj.is_end = true;
514                         has_end = true;
515                 }
516                 this.timeslots.push(obj);
517
518                 curdate = new Date(curdate.getFullYear(),curdate.getMonth(),curdate.getDate(),curdate.getHours(),curdate.getMinutes()+minute_interval);
519         }
520     //Bug#51357: Reset the search input fields after attandee popup is initiated.
521     SugarWidgetSchedulerSearch.resetSearchForm();
522 }
523
524 SugarWidgetSchedulerAttendees.prototype.load = function (parentNode) {
525         this.parentNode = parentNode;
526         this.display();
527 }
528
529 SugarWidgetSchedulerAttendees.prototype.display = function() {
530
531         var form_name;
532         if(typeof document.EditView != 'undefined')
533                 form_name = "EditView";
534         else if(typeof document.CalendarEditView != 'undefined')
535                 form_name = "CalendarEditView";
536         else
537                 return;
538
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>';
544         html += '</tr>';
545         html += '<tr class="schedulerTimeRow">';
546         html += '<td>&nbsp;</td>';
547
548         for(var i=0;i < (this.timeslots.length/this.segments); i++) {
549                 var hours = this.timeslots[i*this.segments].date_obj.getHours();
550                 var am_pm = '';
551
552                 if(time_reg_format.indexOf('A') >= 0 || time_reg_format.indexOf('a') >= 0) {
553                         am_pm = "AM";
554
555                         if(hours > 12) {
556                                 am_pm = "PM";
557                                 hours -= 12;
558                         }
559                         if(hours == 12) {
560                                 am_pm = "PM";
561                         }
562                         if(hours == 0) {
563                                 hours = 12;
564                                 am_pm = "AM";
565                         }
566                         if(time_reg_format.indexOf('a') >= 0) {
567                                 am_pm = am_pm.toLowerCase();
568                         }
569                         if(hours != 0 && hours != 12 && i != 0) {
570                                 am_pm = "";
571                         }
572
573                 }
574
575                 var form_hours = hours+time_separator+"00";
576                 html += '<th scope="col" colspan="'+this.segments+'">'+form_hours+am_pm+'</th>';
577         }
578
579         html += '<td>&nbsp;</td>';
580         html += '</tr>';
581         html += '</table>';
582     if ( this.parentNode.childNodes.length < 1 )
583         this.parentNode.innerHTML += '<div class="schedulerDiv">' + html + '</div>';
584     else
585         this.parentNode.childNodes[0].innerHTML = html;
586
587         var thetable = "schedulerTable";
588
589         if(typeof (GLOBAL_REGISTRY) == 'undefined') {
590                 return;
591         }
592
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 ];
598         }
599
600         if(typeof GLOBAL_REGISTRY.focus.users_arr_hash == 'undefined') {
601                 GLOBAL_REGISTRY.focus.users_arr_hash = new Object();
602         }
603
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];
609                 row.load(thetable);
610         }
611 }
612
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];
616         }
617         GLOBAL_REGISTRY.scheduler_attendees_obj.display();
618 }
619
620 // Function sets the visibility of the Add Parent Link
621 SugarWidgetSchedulerAttendees.setAddParentLinkVisibility = function()
622 {
623         parent_type = $('#parent_type option:selected').text();
624         if ($.inArray(parent_type, SugarWidgetSchedulerAttendees.allowedTypes) > -1)
625         {
626                 $('#add_parent_invitee').parent().css('display', '');
627         }
628         else
629         {
630                 $('#add_parent_invitee').parent().css('display', 'none');
631         }
632 }
633
634 // Function used to add the parent to the invitees
635 SugarWidgetSchedulerAttendees.formAddParent = function()
636 {       
637         parent_id = $("#parent_id").val();
638         parent_name = $("#parent_name").val();
639         parent_type = $("#parent_type option:selected").text();
640
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)
643         {
644                 invitee = {
645                                 fields:
646                                         {id:parent_id, full_name:parent_name},
647                                 module:parent_type};
648                 
649                 contains = false;
650                 for(var i = 0; i < GLOBAL_REGISTRY.focus.users_arr.length; i++)
651                 {
652                         if (GLOBAL_REGISTRY.focus.users_arr[i]['fields']['id'] == invitee['fields']['id'])
653                         {
654                                 contains = true;
655                                 break;
656                         }
657                 }
658                 
659                 if (!contains)
660                 {
661                         GLOBAL_REGISTRY.focus.users_arr[GLOBAL_REGISTRY.focus.users_arr.length] = invitee;
662                         GLOBAL_REGISTRY.scheduler_attendees_obj.display();      
663                 }
664         }
665 }
666
667 //////////////////////////////////////////////////
668 // class: SugarWidgetScheduleRow
669 // widget to display each row in the scheduler
670 //
671 //////////////////////////////////////////////////
672 SugarClass.inherit("SugarWidgetScheduleRow","SugarClass");
673
674 function SugarWidgetScheduleRow(timeslots) {
675         this.init(timeslots);
676 }
677
678 SugarWidgetScheduleRow.prototype.init = function(timeslots) {
679         this.timeslots = timeslots;
680 }
681
682 SugarWidgetScheduleRow.prototype.load = function (thetableid) {
683         this.thetableid = thetableid;
684         var self = this;
685
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);
690                 req_count++;
691         } else {
692                 this.display();
693         }
694 }
695
696 SugarWidgetScheduleRow.prototype.display = function() {
697         SUGAR.util.doWhen("document.getElementById('" + this.thetableid + "') != null", function(){
698         var tr;
699         this.thetable = document.getElementById(this.thetableid);
700
701         if(typeof (this.element) != 'undefined') {
702             if (this.element.parentNode != null)
703                 this.thetable.deleteRow(this.element.rowIndex);
704
705             tr = document.createElement('tr');
706             this.thetable.appendChild(tr);
707         } else {
708             tr = this.thetable.insertRow(this.thetable.rows.length);
709         }
710         tr.className = "schedulerAttendeeRow";
711
712         td = document.createElement('td');
713         tr.appendChild(td);
714         //insertCell(tr.cells.length);
715
716         // icon + full name
717         td.scope = 'row';
718         var img = '<img align="absmiddle" src="index.php?entryPoint=getImage&themeName='
719                 + SUGAR.themes.theme_name+'&imageName='+this.focus_bean.module+'s.gif"/>&nbsp;';
720         td.innerHTML = img;
721
722         td.innerHTML = td.innerHTML;
723
724         if (this.focus_bean.fields.full_name)
725             td.innerHTML += ' ' + this.focus_bean.fields.full_name;
726         else
727             td.innerHTML += ' ' + this.focus_bean.fields.name;
728
729         // add freebusy tds here:
730         this.add_freebusy_nodes(tr);
731
732         // delete button
733         var td = document.createElement('td');
734         tr.appendChild(td);
735         //var td = tr.insertCell(tr.cells.length);
736         td.className = 'schedulerAttendeeDeleteCell';
737         td.noWrap = true;
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+'\');">&nbsp;'
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>';
746         //}
747         this.element = tr;
748         this.element_index = this.thetable.rows.length - 1;
749     }, null, this);
750 }
751
752 SugarWidgetScheduleRow.deleteRow = function(bean_id) {
753         // can't delete organizer
754         /*
755         if(GLOBAL_REGISTRY.focus.users_arr.length == 1 || GLOBAL_REGISTRY.focus.fields.assigned_user_id == bean_id) {
756                 return;
757         }
758     */
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();
766                 }
767         }
768 }
769
770
771 function DL_GetElementLeft(eElement) {
772         /*
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
777          */
778         if(!eElement && this) {
779                 eElement = this;
780         }
781
782         /*
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
788          */
789         var nLeftPos = eElement.offsetLeft;
790         var eParElement = eElement.offsetParent;
791         while (eParElement != null) {
792                 nLeftPos += eParElement.offsetLeft;
793                 eParElement = eParElement.offsetParent;
794         }
795         return nLeftPos; // return the number calculated
796 }
797
798
799 function DL_GetElementTop(eElement) {
800         if(!eElement && this) {
801                 eElement = this;
802         }
803
804         var nTopPos = eElement.offsetTop;
805         var eParElement = eElement.offsetParent;
806         while (eParElement != null) {
807                 nTopPos += eParElement.offsetTop;
808                 eParElement = eParElement.offsetParent;
809         }
810         return nTopPos;
811 }
812
813
814 //////////////////////////////////////////
815 // adds the <td>s for freebusy display within a row
816 SugarWidgetScheduleRow.prototype.add_freebusy_nodes = function(tr,attendee) {
817         var hours = 9;
818         var segments = 4;
819         var html = '';
820         var is_loaded = false;
821
822         if(typeof GLOBAL_REGISTRY['freebusy_adjusted'] != 'undefined' && typeof GLOBAL_REGISTRY['freebusy_adjusted'][this.focus_bean.fields.id] != 'undefined') {
823                 is_loaded = true;
824         }
825
826         for(var i=0;i < this.timeslots.length; i++) {
827                 var td = document.createElement('td');
828                 tr.appendChild(td);
829                 //var td = tr.insertCell(tr.cells.length);
830         td.innerHTML = '&nbsp;';
831                 if(typeof(this.timeslots[i]['is_start']) != 'undefined') {
832                         td.className = 'schedulerSlotCellStartTime';
833                 }
834                 if(typeof(this.timeslots[i]['is_end']) != 'undefined') {
835                         td.className = 'schedulerSlotCellEndTime';
836                 }
837
838                 if(is_loaded) {
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";
842
843                                 if(     GLOBAL_REGISTRY['freebusy_adjusted'][this.focus_bean.fields.id][this.timeslots[i].hash] > 1) {
844                                         td.style.backgroundColor="#AA4D4D";
845                                 }
846                         }
847                 }
848         }
849 }