]> err.no Git - scalable-opengroupware.org/blob - UI/WebServerResources/UIxAttendeesEditor.js
git-svn-id: http://svn.opengroupware.org/SOGo/inverse/trunk@1209 d1b88da0-ebda-0310...
[scalable-opengroupware.org] / UI / WebServerResources / UIxAttendeesEditor.js
1 var resultsDiv;
2 var searchField;
3 var running = false;
4 var address;
5 var delay = 500;
6 var requestField;
7 var awaitingFreeBusyRequests = new Array();
8 var additionalDays = 2;
9
10 var dayStartHour = 8;
11 var dayEndHour = 18;
12
13 var attendeesNames;
14 var attendeesEmails;
15
16 function onContactKeydown(event) {
17   if (event.ctrlKey || event.metaKey) {
18     this.focussed = true;
19     return;
20   }
21   if (event.keyCode == 9) { // Tab
22     preventDefault(event);
23     if (this.confirmedValue)
24       this.value = this.confirmedValue;
25     var row = this.parentNode.parentNode.nextSibling;
26     while (row && row.tagName != 'TR')
27       row = row.nextSibling;
28     this.blur();
29     var input = $(row.cells[0]).childNodesWithTag("input")[0];
30     if (input.readOnly)
31       newAttendee(null);
32     else {
33       input.focussed = true;
34       input.activate();
35     }
36   }
37   else if (!running) {
38     if (event.keyCode == 0
39         || event.keyCode == 8 // Backspace
40         || event.keyCode == 32  // Space
41         || event.keyCode > 47) {
42       running = true;
43       requestField = this;
44       requestField.setAttribute("modified", "1");
45       setTimeout("triggerRequest()", delay);
46     }
47     else if (this.confirmedValue) {
48       if (event.keyCode == 13) { // Enter
49         $(this).setCaretTo(this.value.length);
50       }
51     }
52   }
53 }
54
55 function triggerRequest() {
56   if (document.contactLookupAjaxRequest) {
57     document.contactLookupAjaxRequest.aborted = yes;
58     document.contactLookupAjaxRequest.abort();
59   }
60   var urlstr = ( UserFolderURL + "Contacts/contactSearch?search="
61                  + escape(requestField.value) );
62   //log (urlstr);
63   document.contactLookupAjaxRequest = triggerAjaxRequest(urlstr,
64                                                          updateResults,
65                                                          requestField);
66 }
67
68 function updateResults(http) {
69   if (http.readyState == 4) {
70     if (http.status == 200) {
71       var searchField = http.callbackData;
72       var start = searchField.value.length;
73       var text = http.responseText.split(":");
74       if (text[0].length > 0)
75         searchField.uid = text[0];
76       else
77         searchField.uid = null;
78       searchField.hasfreebusy = false;
79       var completeEmail = text[1] + " <" + text[2] + ">";
80       if (text[1].substring(0, searchField.value.length).toUpperCase()
81           == searchField.value.toUpperCase())
82         searchField.value = completeEmail;
83       else {
84         searchField.value += ' >> ' + completeEmail;
85       }
86       searchField.confirmedValue = completeEmail;
87       if (searchField.focussed) {
88         var end = searchField.value.length;
89         $(searchField).selectText(start, end);
90       }
91       else
92         searchField.value = text[1];
93     }
94     running = false;
95     document.contactLookupAjaxRequest = null;
96   }
97 }
98
99 function UIDLookupCallback(http) {
100   if (http.readyState == 4) {
101     if (http.status == 200) {
102       var searchField = http.callbackData;
103       var start = searchField.value.length;
104       var text = http.responseText.split(":");
105       if (text[0].length > 0) {
106          searchField.uid = text[0];
107          displayFreeBusyForNode(searchField);
108       }
109       else
110          searchField.uid = null
111     }
112   }
113 }
114
115 function resetFreeBusyZone() {
116   var table = $("freeBusy");
117   var row = table.tHead.rows[2];
118   for (var i = 1; i < row.cells.length; i++) {
119     var nodes = $(row.cells[i]).childNodesWithTag("span");
120     for (var j = 0; j < nodes.length; j++)
121       nodes[j].removeClassName("busy");
122   }
123 }
124
125 function redisplayFreeBusyZone() {
126   var table = $("freeBusy");
127   var row = table.tHead.rows[2];
128   var stDay = $("startTime_date").valueAsDate();
129   var etDay = $("endTime_date").valueAsDate();
130
131   var days = stDay.daysUpTo(etDay);
132   var addDays = days.length - 1;
133   var stHour = parseInt($("startTime_time_hour").value);
134   var stMinute = parseInt($("startTime_time_minute").value) / 15;
135   var etHour = parseInt($("endTime_time_hour").value);
136   var etMinute = parseInt($("endTime_time_minute").value) / 15;
137   if (stHour < 8) {
138     stHour = 8;
139     stMinute = 0;
140   }
141   if (stHour > 19) {
142     stHour = 19
143     stMinute = 0;
144   }
145   if (etHour < 8) {
146     etHour = 8;
147     etMinute = 0;
148   }
149   if (etHour > 19) {
150     etHour = 19;
151     etMinute = 0;
152   }
153   if (stHour > etHour) {
154     var swap = etHour;
155     etHour = stHour;
156     stHour = swap;
157     swap = etMinute;
158     etMinute = stMinute;
159     stMinute = etMinute;
160   } else {
161     if (stMinute > etMinute) {
162       var swap = etMinute;
163       etMinute = stMinute;
164       stMinute = swap;
165     }
166   }
167
168   var deltaCells = (etHour - stHour) + (11 * addDays);
169   var deltaSpans = (deltaCells * 4 ) + (etMinute - stMinute);
170   var currentCellNbr = stHour - 7;
171   var currentCell = row.cells[currentCellNbr];
172   var currentSpanNbr = stMinute;
173   var spans = $(currentCell).childNodesWithTag("span");
174   resetFreeBusyZone();
175   while (deltaSpans > 0) {
176     var currentSpan = spans[currentSpanNbr];
177     currentSpan.addClassName("busy");
178     currentSpanNbr++;
179     if (currentSpanNbr > 3) {
180       currentSpanNbr = 0;
181       currentCellNbr++;
182       currentCell = row.cells[currentCellNbr];
183       spans = $(currentCell).childNodesWithTag("span");
184     }
185     deltaSpans--;
186   }
187 }
188
189 function newAttendee(event) {
190    var table = $("freeBusy");
191    var tbody = table.tBodies[0];
192    var model = tbody.rows[tbody.rows.length - 1];
193    var newAttendeeRow = tbody.rows[tbody.rows.length - 2];
194    var newRow = model.cloneNode(true);
195    tbody.insertBefore(newRow, newAttendeeRow);
196   
197    $(newRow).className = "";
198   
199    var input = $(newRow.cells[0]).childNodesWithTag("input")[0];
200    input.setAttribute("autocomplete", "off");
201    Event.observe(input, "blur", checkAttendee.bindAsEventListener(input));
202    Event.observe(input, "keydown", onContactKeydown.bindAsEventListener(input));
203
204    input.focussed = true;
205    input.activate();
206 }
207
208 function checkAttendee() {
209   this.focussed = false;
210   var th = this.parentNode.parentNode;
211   var tbody = th.parentNode;
212   if (tbody && this.value.trim().length == 0)
213     tbody.removeChild(th);
214   else if (!this.hasfreebusy) {
215     if (this.confirmedValue)
216       this.value = this.confirmedValue;
217     displayFreeBusyForNode(this);
218     this.hasfreebusy = true;
219   }
220   resetAttendeesValue();
221 }
222
223 function displayFreeBusyForNode(node) {
224    if (document.contactFreeBusyAjaxRequest)
225       awaitingFreeBusyRequests.push(node);
226    else {
227       var nodes = node.parentNode.parentNode.cells;
228       if (node.uid) {
229          for (var i = 1; i < nodes.length; i++) {
230             $(nodes[i]).removeClassName("noFreeBusy");
231             nodes[i].innerHTML = ('<span class="freeBusyZoneElement"></span>'
232                                   + '<span class="freeBusyZoneElement"></span>'
233                                   + '<span class="freeBusyZoneElement"></span>'
234                                   + '<span class="freeBusyZoneElement"></span>');
235          }
236          if (document.contactFreeBusyAjaxRequest) {
237             document.contactFreeBusyAjaxRequest.aborted = true;
238             document.contactFreeBusyAjaxRequest.abort();
239          }
240          var sd = $('startTime_date').valueAsShortDateString();
241          var ed = $('endTime_date').valueAsShortDateString();
242          var urlstr = ( UserFolderURL + "../" + node.uid + "/freebusy.ifb/ajaxRead?"
243                         + "sday=" + sd + "&eday=" + ed + "&additional=" +
244                         additionalDays );
245          document.contactFreeBusyAjaxRequest
246             = triggerAjaxRequest(urlstr,
247                                  updateFreeBusyData,
248                                  node);
249       } else {
250          for (var i = 1; i < nodes.length; i++) {
251             $(nodes[i]).addClassName("noFreeBusy");
252             nodes[i].innerHTML = '';
253          }
254       }
255    }
256 }
257
258 function setSlot(tds, nbr, status) {
259   var tdnbr = Math.floor(nbr / 4);
260   var spannbr = nbr - (tdnbr * 4);
261   var days = 0;
262   if (tdnbr > 24) {
263     days = Math.floor(tdnbr / 24);
264     tdnbr -= (days * 24);
265   }
266   if (tdnbr > 7 && tdnbr < 19) {
267     var i = (days * 11 + tdnbr - 7);
268     var td = tds[i];
269     var spans = $(td).childNodesWithTag("span");
270     if (status == '2')
271       $(spans[spannbr]).addClassName("maybe-busy");
272     else
273       $(spans[spannbr]).addClassName("busy");
274   }
275 }
276
277 function updateFreeBusyData(http) {
278   if (http.readyState == 4) {
279     if (http.status == 200) {
280       var node = http.callbackData;
281       var slots = http.responseText.split(",");
282       var tds = node.parentNode.parentNode.cells;
283       for (var i = 0; i < slots.length; i++) {
284         if (slots[i] != '0')
285           setSlot(tds, i, slots[i]);
286       }
287     }
288     document.contactFreeBusyAjaxRequest = null;
289     if (awaitingFreeBusyRequests.length > 0)
290       displayFreeBusyForNode(awaitingFreeBusyRequests.shift());
291   }
292 }
293
294 function resetAttendeesValue() {
295   var table = $("freeBusy");
296   var inputs = table.getElementsByTagName("input");
297   for (var i = 0; i < inputs.length - 2; i++) {
298     var currentInput = inputs[i];
299     var uid = currentInput.getAttribute("uid");
300     if (uid) {
301       currentInput.uid = uid;
302       currentInput.setAttribute("uid", null);
303     }
304     currentInput.setAttribute("autocomplete", "off");
305     //Event.observe(currentInput, "keydown", onContactKeydown.bindAsEventListener(currentInput));
306     //Event.observe(currentInput, "blur", checkAttendee.bindAsEventListener(currentInput));
307   }
308   inputs[inputs.length - 2].setAttribute("autocomplete", "off");
309   Event.observe(inputs[inputs.length - 2], "click", newAttendee);
310 }
311
312 function resetAllFreeBusys() {
313   var table = $("freeBusy");
314   var inputs = table.getElementsByTagName("input");
315
316   for (var i = 0; i < inputs.length - 2; i++) {
317     var currentInput = inputs[i];
318     currentInput.hasfreebusy = false;
319     displayFreeBusyForNode(inputs[i]);
320   }
321 }
322
323 function initializeWindowButtons() {
324    var okButton = $("okButton");
325    var cancelButton = $("cancelButton");
326
327    Event.observe(okButton, "click", onEditorOkClick, false);
328    Event.observe(cancelButton, "click", onEditorCancelClick, false);
329
330    var buttons = $("freeBusyViewButtons").childNodesWithTag("a");
331    for (var i = 0; i < buttons.length; i++)
332      Event.observe(buttons[i], "click", listRowMouseDownHandler, false);
333    buttons = $("freeBusyZoomButtons").childNodesWithTag("a");
334    for (var i = 0; i < buttons.length; i++)
335      Event.observe(buttons[i], "click", listRowMouseDownHandler, false);
336    buttons = $("freeBusyButtons").childNodesWithTag("a");
337    for (var i = 0; i < buttons.length; i++)
338      Event.observe(buttons[i], "click", listRowMouseDownHandler, false);
339 }
340
341 function onEditorOkClick(event) {
342    preventDefault(event);
343
344    attendeesNames = new Array();
345    attendeesEmails = new Array();
346
347    var table = $("freeBusy");
348    var inputs = table.getElementsByTagName("input");
349    for (var i = 0; i < inputs.length - 2; i++) {
350      var name = extractEmailName(inputs[i].value);
351      if (!(name && name.length > 0))
352        name = inputs[i].uid;
353      var email = extractEmailAddress(inputs[i].value);
354      var pos = attendeesEmails.indexOf(email);
355      if (pos == -1)
356        pos = attendeesEmails.length;
357      attendeesNames[pos] = name;
358      attendeesEmails[pos] = email;
359    }
360
361    parent$("attendeesNames").value = attendeesNames.join(",");
362    parent$("attendeesEmails").value = attendeesEmails.join(",");
363    window.opener.refreshAttendees();
364
365    updateParentDateFields("startTime", "startTime");
366    updateParentDateFields("endTime", "endTime");
367
368    window.close();
369 }
370
371 function onEditorCancelClick(event) {
372    preventDefault(event);
373    window.close();
374 }
375
376 function synchronizeWithParent(srcWidgetName, dstWidgetName) {
377    var srcDate = parent$(srcWidgetName + "_date");
378    var dstDate = $(dstWidgetName + "_date");
379    dstDate.value = srcDate.value;
380
381    var srcHour = parent$(srcWidgetName + "_time_hour");
382    var dstHour = $(dstWidgetName + "_time_hour");
383    dstHour.value = srcHour.value;
384
385    var srcMinute = parent$(srcWidgetName + "_time_minute");
386    var dstMinute = $(dstWidgetName + "_time_minute");
387    dstMinute.value = srcMinute.value;
388 }
389
390 function updateParentDateFields(srcWidgetName, dstWidgetName) {
391    var srcDate = $(srcWidgetName + "_date");
392    var dstDate = parent$(dstWidgetName + "_date");
393    dstDate.value = srcDate.value;
394
395    var srcHour = $(srcWidgetName + "_time_hour");
396    var dstHour = parent$(dstWidgetName + "_time_hour");
397    dstHour.value = srcHour.value;
398
399    var srcMinute = $(srcWidgetName + "_time_minute");
400    var dstMinute = parent$(dstWidgetName + "_time_minute");
401    dstMinute.value = srcMinute.value;
402 }
403
404 function initializeTimeWidgets() {
405    synchronizeWithParent("startTime", "startTime");
406    synchronizeWithParent("endTime", "endTime");
407
408    Event.observe($("startTime_date"), "change", onTimeDateWidgetChange, false);
409    Event.observe($("startTime_time_hour"), "change", onTimeWidgetChange, false);
410    Event.observe($("startTime_time_minute"), "change", onTimeWidgetChange, false);
411
412    Event.observe($("endTime_date"), "change", onTimeDateWidgetChange, false);
413    Event.observe($("endTime_time_hour"), "change", onTimeWidgetChange, false);
414    Event.observe($("endTime_time_minute"), "change", onTimeWidgetChange, false);
415 }
416
417 function onTimeWidgetChange() {
418    redisplayFreeBusyZone();
419 }
420
421 function onTimeDateWidgetChange(event) {
422   var table = $("freeBusy");
423
424   var rows = table.tHead.rows;
425   for (var i = 0; i < rows.length; i++) {
426      for (var j = rows[i].cells.length - 1; j > 0; j--) {
427         rows[i].deleteCell(j);
428      }
429   }
430
431   rows = table.tBodies[0].rows;
432   for (var i = 0; i < rows.length; i++) {
433      for (var j = rows[i].cells.length - 1; j > 0; j--) {
434         rows[i].deleteCell(j);
435      }
436   }
437
438   prepareTableHeaders();
439   prepareTableRows();
440   redisplayFreeBusyZone();
441   resetAttendeesValue();
442   resetAllFreeBusys();
443 }
444
445 function prepareTableHeaders() {
446    var startTimeDate = $("startTime_date");
447    var startDate = startTimeDate.valueAsDate();
448
449    var endTimeDate = $("endTime_date");
450    var endDate = endTimeDate.valueAsDate();
451    endDate.setTime(endDate.getTime() + (additionalDays * 86400000));
452
453    var rows = $("freeBusy").tHead.rows;
454    var days = startDate.daysUpTo(endDate);
455    for (var i = 0; i < days.length; i++) {
456       var header1 = document.createElement("th");
457       header1.colSpan = (dayEndHour - dayStartHour) + 1;
458       header1.appendChild(document.createTextNode(days[i].toLocaleDateString()));
459       rows[0].appendChild(header1);
460       for (var hour = dayStartHour; hour < (dayEndHour + 1); hour++) {
461          var header2 = document.createElement("th");
462          var text = hour + ":00";
463          if (hour < 10)
464             text = "0" + text;
465          header2.appendChild(document.createTextNode(text));
466          rows[1].appendChild(header2);
467
468          var header3 = document.createElement("th");
469          for (var span = 0; span < 4; span++) {
470             var spanElement = document.createElement("span");
471             $(spanElement).addClassName("freeBusyZoneElement");
472             header3.appendChild(spanElement);
473          }
474          rows[2].appendChild(header3);
475       }
476    }
477 }
478
479 function prepareTableRows() {
480    var startTimeDate = $("startTime_date");
481    var startDate = startTimeDate.valueAsDate();
482
483    var endTimeDate = $("endTime_date");
484    var endDate = endTimeDate.valueAsDate();
485    endDate.setTime(endDate.getTime() + (additionalDays * 86400000));
486
487    var rows = $("freeBusy").tBodies[0].rows;
488    var days = startDate.daysUpTo(endDate);
489    for (var i = 0; i < days.length; i++)
490       for (var rowNbr = 0; rowNbr < rows.length; rowNbr++)
491          for (var hour = dayStartHour; hour < (dayEndHour + 1); hour++)
492             rows[rowNbr].appendChild(document.createElement("td"));
493 }
494
495 function prepareAttendees() {
496    var value = parent$("attendeesNames").value;
497    if (value.length > 0) {
498       attendeesNames = parent$("attendeesNames").value.split(",");
499       attendeesEmails = parent$("attendeesEmails").value.split(",");
500
501       var body = $("freeBusy").tBodies[0];
502       for (var i = 0; i < attendeesNames.length; i++) {
503          var tr = body.insertRow(i);
504          var td = document.createElement("td");
505          $(td).addClassName("attendees");
506          var input = document.createElement("input");
507          var value = "";
508          if (attendeesNames[i].length > 0)
509             value += attendeesNames[i] + " ";
510          value += "<" + attendeesEmails[i] + ">";
511          input.value = value;
512          $(input).addClassName("textField");
513          input.setAttribute("modified", "0");
514          tr.appendChild(td);
515          td.appendChild(input);
516          displayFreeBusyForNode(input);
517       }
518    }
519    else {
520       attendeesNames = new Array();
521       attendeesEmails = new Array();
522    }
523 }
524
525 function initializeFreebusys() {
526    var inputs = $("freeBusy").getElementsByTagName("input");
527    var baseUrl = UserFolderURL + "Contacts/contactSearch?search=";
528    for (var i = 0; i < attendeesEmails.length; i++)
529       triggerAjaxRequest(baseUrl + attendeesEmails[i],
530                          UIDLookupCallback, inputs[i]);
531 }
532
533 function onFreeBusyLoadHandler() {
534    initializeWindowButtons();
535    initializeTimeWidgets();
536    prepareAttendees();
537    prepareTableHeaders();
538    prepareTableRows();
539    redisplayFreeBusyZone();
540    resetAttendeesValue();
541    initializeFreebusys();
542 }
543
544 addEvent(window, 'load', onFreeBusyLoadHandler);