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