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