]> err.no Git - scalable-opengroupware.org/blob - UI/WebServerResources/UIxAttendeesEditor.js
git-svn-id: http://svn.opengroupware.org/SOGo/inverse/trunk@1078 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   newRow.setAttribute("class", "");
191   tbody.insertBefore(newRow, newAttendeeRow);
192   //table.tBodies[0].appendChild(newRow);
193   var input = $(newRow.cells[0]).childNodesWithTag("input")[0];
194   input.setAttribute("autocomplete", "off");
195   input.serial = "pouet";
196   Event.observe(input, "blur", checkAttendee.bindAsEventListener(input));
197   Event.observe(input, "keydown", onContactKeydown.bindAsEventListener(input));
198   input.focus();
199   input.focussed = true;
200 }
201
202 function checkAttendee() {
203   this.focussed = false;
204   var th = this.parentNode.parentNode;
205   var tbody = th.parentNode;
206   if (this.value.trim().length == 0)
207     tbody.removeChild(th);
208   else if (!this.hasfreebusy) {
209     if (this.confirmedValue)
210       this.value = this.confirmedValue;
211     displayFreeBusyForNode(this);
212     this.hasfreebusy = true;
213   }
214   resetAttendeesValue();
215 }
216
217 function displayFreeBusyForNode(node) {
218    if (document.contactFreeBusyAjaxRequest)
219       awaitingFreeBusyRequests.push(node);
220    else {
221       var nodes = node.parentNode.parentNode.cells;
222       if (node.uid) {
223          for (var i = 1; i < nodes.length; i++) {
224             nodes[i].removeClassName("noFreeBusy");
225             nodes[i].innerHTML = ('<span class="freeBusyZoneElement"></span>'
226                                   + '<span class="freeBusyZoneElement"></span>'
227                                   + '<span class="freeBusyZoneElement"></span>'
228                                   + '<span class="freeBusyZoneElement"></span>');
229          }
230          if (document.contactFreeBusyAjaxRequest) {
231             document.contactFreeBusyAjaxRequest.aborted = true;
232             document.contactFreeBusyAjaxRequest.abort();
233          }
234          var sd = $('startTime_date').valueAsShortDateString();
235          var ed = $('endTime_date').valueAsShortDateString();
236          var urlstr = ( UserFolderURL + "../" + node.uid + "/freebusy.ifb/ajaxRead?"
237                         + "sday=" + sd + "&eday=" + ed + "&additional=" +
238                         additionalDays );
239          document.contactFreeBusyAjaxRequest
240             = triggerAjaxRequest(urlstr,
241                                  updateFreeBusyData,
242                                  node);
243       } else {
244          for (var i = 1; i < nodes.length; i++) {
245             nodes[i].addClassName("noFreeBusy");
246             nodes[i].innerHTML = '';
247          }
248       }
249    }
250 }
251
252 function setSlot(tds, nbr, status) {
253   var tdnbr = Math.floor(nbr / 4);
254   var spannbr = nbr - (tdnbr * 4);
255   var days = 0;
256   if (tdnbr > 24) {
257     days = Math.floor(tdnbr / 24);
258     tdnbr -= (days * 24);
259   }
260   if (tdnbr > 7 && tdnbr < 19) {
261     var i = (days * 11 + tdnbr - 7);
262     var td = tds[i];
263     var spans = $(td).childNodesWithTag("span");
264     if (status == '2')
265       spans[spannbr].addClassName("maybe-busy");
266     else
267       spans[spannbr].addClassName("busy");
268   }
269 }
270
271 function updateFreeBusyData(http) {
272   if (http.readyState == 4) {
273     if (http.status == 200) {
274       var node = http.callbackData;
275       var slots = http.responseText.split(",");
276       var tds = node.parentNode.parentNode.cells;
277       for (var i = 0; i < slots.length; i++) {
278         if (slots[i] != '0')
279           setSlot(tds, i, slots[i]);
280       }
281     }
282     document.contactFreeBusyAjaxRequest = null;
283     if (awaitingFreeBusyRequests.length > 0)
284       displayFreeBusyForNode(awaitingFreeBusyRequests.shift());
285   }
286 }
287
288 function resetAttendeesValue() {
289   var table = $("freeBusy");
290   var inputs = table.getElementsByTagName("input");
291   for (var i = 0; i < inputs.length - 2; i++) {
292     var currentInput = inputs[i];
293     var uid = currentInput.getAttribute("uid");
294     if (uid) {
295       currentInput.uid = uid;
296       currentInput.setAttribute("uid", null);
297     }
298     currentInput.setAttribute("autocomplete", "off");
299     Event.observe(currentInput, "keydown", onContactKeydown.bindAsEventListener(currentInput), false);
300     Event.observe(currentInput, "blur", checkAttendee.bindAsEventListener(currentInput), false);
301   }
302   inputs[inputs.length - 2].setAttribute("autocomplete", "off");
303   Event.observe(inputs[inputs.length - 2], "click", newAttendee, false);
304 }
305
306 function resetAllFreeBusys() {
307   var table = $("freeBusy");
308   var inputs = table.getElementsByTagName("input");
309
310   for (var i = 0; i < inputs.length - 2; i++) {
311     var currentInput = inputs[i];
312     currentInput.hasfreebusy = false;
313     displayFreeBusyForNode(inputs[i]);
314   }
315 }
316
317 function initializeWindowButtons() {
318    var okButton = $("okButton");
319    var cancelButton = $("cancelButton");
320
321    Event.observe(okButton, "click", onEditorOkClick, false);
322    Event.observe(cancelButton, "click", onEditorCancelClick, false);
323
324    var buttons = $("freeBusyViewButtons").childNodesWithTag("a");
325    for (var i = 0; i < buttons.length; i++)
326      Event.observe(buttons[i], "click", listRowMouseDownHandler, false);
327    buttons = $("freeBusyZoomButtons").childNodesWithTag("a");
328    for (var i = 0; i < buttons.length; i++)
329      Event.observe(buttons[i], "click", listRowMouseDownHandler, false);
330    buttons = $("freeBusyButtons").childNodesWithTag("a");
331    for (var i = 0; i < buttons.length; i++)
332      Event.observe(buttons[i], "click", listRowMouseDownHandler, false);
333 }
334
335 function onEditorOkClick(event) {
336    event.preventDefault();
337
338    attendeesNames = new Array();
339    attendeesEmails = new Array();
340
341    var table = $("freeBusy");
342    var inputs = table.getElementsByTagName("input");
343    for (var i = 0; i < inputs.length - 2; i++) {
344      var name = extractEmailName(inputs[i].value);
345      if (!(name && name.length > 0))
346        name = inputs[i].uid;
347      var email = extractEmailAddress(inputs[i].value);
348      var pos = attendeesEmails.indexOf(email);
349      if (pos == -1)
350        pos = attendeesEmails.length;
351      attendeesNames[pos] = name;
352      attendeesEmails[pos] = email;
353    }
354
355    parent$("attendeesNames").value = attendeesNames.join(",");
356    parent$("attendeesEmails").value = attendeesEmails.join(",");
357    window.opener.refreshAttendees();
358
359    updateParentDateFields("startTime", "startTime");
360    updateParentDateFields("endTime", "endTime");
361
362    window.close();
363 }
364
365 function onEditorCancelClick(event) {
366    event.preventDefault();
367    window.close();
368 }
369
370 function synchronizeWithParent(srcWidgetName, dstWidgetName) {
371    var srcDate = parent$(srcWidgetName + "_date");
372    var dstDate = $(dstWidgetName + "_date");
373    dstDate.value = srcDate.value;
374
375    var srcHour = parent$(srcWidgetName + "_time_hour");
376    var dstHour = $(dstWidgetName + "_time_hour");
377    dstHour.value = srcHour.value;
378
379    var srcMinute = parent$(srcWidgetName + "_time_minute");
380    var dstMinute = $(dstWidgetName + "_time_minute");
381    dstMinute.value = srcMinute.value;
382 }
383
384 function updateParentDateFields(srcWidgetName, dstWidgetName) {
385    var srcDate = $(srcWidgetName + "_date");
386    var dstDate = parent$(dstWidgetName + "_date");
387    dstDate.value = srcDate.value;
388
389    var srcHour = $(srcWidgetName + "_time_hour");
390    var dstHour = parent$(dstWidgetName + "_time_hour");
391    dstHour.value = srcHour.value;
392
393    var srcMinute = $(srcWidgetName + "_time_minute");
394    var dstMinute = parent$(dstWidgetName + "_time_minute");
395    dstMinute.value = srcMinute.value;
396 }
397
398 function initializeTimeWidgets() {
399    synchronizeWithParent("startTime", "startTime");
400    synchronizeWithParent("endTime", "endTime");
401
402    Event.observe($("startTime_date"), "change", onTimeDateWidgetChange, false);
403    Event.observe($("startTime_time_hour"), "change", onTimeWidgetChange, false);
404    Event.observe($("startTime_time_minute"), "change", onTimeWidgetChange, false);
405
406    Event.observe($("endTime_date"), "change", onTimeDateWidgetChange, false);
407    Event.observe($("endTime_time_hour"), "change", onTimeWidgetChange, false);
408    Event.observe($("endTime_time_minute"), "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);