7 var awaitingFreeBusyRequests = new Array();
8 var additionalDays = 2;
16 function onContactKeydown(event) {
17 if (event.ctrlKey || event.metaKey) {
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;
29 var input = $(row.cells[0]).childNodesWithTag("input")[0];
33 input.focussed = true;
38 if (event.keyCode == 0
39 || event.keyCode == 8 // Backspace
40 || event.keyCode == 32 // Space
41 || event.keyCode > 47) {
44 requestField.setAttribute("modified", "1");
45 setTimeout("triggerRequest()", delay);
47 else if (this.confirmedValue) {
48 if (event.keyCode == 13) { // Enter
49 $(this).setCaretTo(this.value.length);
55 function triggerRequest() {
56 if (document.contactLookupAjaxRequest) {
57 document.contactLookupAjaxRequest.aborted = yes;
58 document.contactLookupAjaxRequest.abort();
60 var urlstr = ( UserFolderURL + "Contacts/contactSearch?search="
61 + escape(requestField.value) );
63 document.contactLookupAjaxRequest = triggerAjaxRequest(urlstr,
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];
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;
84 searchField.value += ' >> ' + completeEmail;
86 searchField.confirmedValue = completeEmail;
87 if (searchField.focussed) {
88 var end = searchField.value.length;
89 $(searchField).selectText(start, end);
92 searchField.value = text[1];
95 document.contactLookupAjaxRequest = null;
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);
110 searchField.uid = null
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");
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();
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;
153 if (stHour > etHour) {
161 if (stMinute > etMinute) {
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");
175 while (deltaSpans > 0) {
176 var currentSpan = spans[currentSpanNbr];
177 currentSpan.addClassName("busy");
179 if (currentSpanNbr > 3) {
182 currentCell = row.cells[currentCellNbr];
183 spans = $(currentCell).childNodesWithTag("span");
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);
197 $(newRow).className = "";
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));
204 input.focussed = true;
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;
220 resetAttendeesValue();
223 function displayFreeBusyForNode(node) {
224 if (document.contactFreeBusyAjaxRequest)
225 awaitingFreeBusyRequests.push(node);
227 var nodes = node.parentNode.parentNode.cells;
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>');
236 if (document.contactFreeBusyAjaxRequest) {
237 document.contactFreeBusyAjaxRequest.aborted = true;
238 document.contactFreeBusyAjaxRequest.abort();
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=" +
245 document.contactFreeBusyAjaxRequest
246 = triggerAjaxRequest(urlstr,
250 for (var i = 1; i < nodes.length; i++) {
251 $(nodes[i]).addClassName("noFreeBusy");
252 nodes[i].innerHTML = '';
258 function setSlot(tds, nbr, status) {
259 var tdnbr = Math.floor(nbr / 4);
260 var spannbr = nbr - (tdnbr * 4);
263 days = Math.floor(tdnbr / 24);
264 tdnbr -= (days * 24);
266 if (tdnbr > 7 && tdnbr < 19) {
267 var i = (days * 11 + tdnbr - 7);
269 var spans = $(td).childNodesWithTag("span");
271 $(spans[spannbr]).addClassName("maybe-busy");
273 $(spans[spannbr]).addClassName("busy");
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++) {
285 setSlot(tds, i, slots[i]);
288 document.contactFreeBusyAjaxRequest = null;
289 if (awaitingFreeBusyRequests.length > 0)
290 displayFreeBusyForNode(awaitingFreeBusyRequests.shift());
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");
301 currentInput.uid = uid;
302 currentInput.setAttribute("uid", null);
304 currentInput.setAttribute("autocomplete", "off");
305 //Event.observe(currentInput, "keydown", onContactKeydown.bindAsEventListener(currentInput));
306 //Event.observe(currentInput, "blur", checkAttendee.bindAsEventListener(currentInput));
308 inputs[inputs.length - 2].setAttribute("autocomplete", "off");
309 Event.observe(inputs[inputs.length - 2], "click", newAttendee);
312 function resetAllFreeBusys() {
313 var table = $("freeBusy");
314 var inputs = table.getElementsByTagName("input");
316 for (var i = 0; i < inputs.length - 2; i++) {
317 var currentInput = inputs[i];
318 currentInput.hasfreebusy = false;
319 displayFreeBusyForNode(inputs[i]);
323 function initializeWindowButtons() {
324 var okButton = $("okButton");
325 var cancelButton = $("cancelButton");
327 Event.observe(okButton, "click", onEditorOkClick, false);
328 Event.observe(cancelButton, "click", onEditorCancelClick, false);
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);
341 function onEditorOkClick(event) {
342 preventDefault(event);
344 attendeesNames = new Array();
345 attendeesEmails = new Array();
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);
356 pos = attendeesEmails.length;
357 attendeesNames[pos] = name;
358 attendeesEmails[pos] = email;
361 parent$("attendeesNames").value = attendeesNames.join(",");
362 parent$("attendeesEmails").value = attendeesEmails.join(",");
363 window.opener.refreshAttendees();
365 updateParentDateFields("startTime", "startTime");
366 updateParentDateFields("endTime", "endTime");
371 function onEditorCancelClick(event) {
372 preventDefault(event);
376 function synchronizeWithParent(srcWidgetName, dstWidgetName) {
377 var srcDate = parent$(srcWidgetName + "_date");
378 var dstDate = $(dstWidgetName + "_date");
379 dstDate.value = srcDate.value;
381 var srcHour = parent$(srcWidgetName + "_time_hour");
382 var dstHour = $(dstWidgetName + "_time_hour");
383 dstHour.value = srcHour.value;
385 var srcMinute = parent$(srcWidgetName + "_time_minute");
386 var dstMinute = $(dstWidgetName + "_time_minute");
387 dstMinute.value = srcMinute.value;
390 function updateParentDateFields(srcWidgetName, dstWidgetName) {
391 var srcDate = $(srcWidgetName + "_date");
392 var dstDate = parent$(dstWidgetName + "_date");
393 dstDate.value = srcDate.value;
395 var srcHour = $(srcWidgetName + "_time_hour");
396 var dstHour = parent$(dstWidgetName + "_time_hour");
397 dstHour.value = srcHour.value;
399 var srcMinute = $(srcWidgetName + "_time_minute");
400 var dstMinute = parent$(dstWidgetName + "_time_minute");
401 dstMinute.value = srcMinute.value;
404 function initializeTimeWidgets() {
405 synchronizeWithParent("startTime", "startTime");
406 synchronizeWithParent("endTime", "endTime");
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);
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);
417 function onTimeWidgetChange() {
418 redisplayFreeBusyZone();
421 function onTimeDateWidgetChange(event) {
422 var table = $("freeBusy");
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);
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);
438 prepareTableHeaders();
440 redisplayFreeBusyZone();
441 resetAttendeesValue();
445 function prepareTableHeaders() {
446 var startTimeDate = $("startTime_date");
447 var startDate = startTimeDate.valueAsDate();
449 var endTimeDate = $("endTime_date");
450 var endDate = endTimeDate.valueAsDate();
451 endDate.setTime(endDate.getTime() + (additionalDays * 86400000));
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";
465 header2.appendChild(document.createTextNode(text));
466 rows[1].appendChild(header2);
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);
474 rows[2].appendChild(header3);
479 function prepareTableRows() {
480 var startTimeDate = $("startTime_date");
481 var startDate = startTimeDate.valueAsDate();
483 var endTimeDate = $("endTime_date");
484 var endDate = endTimeDate.valueAsDate();
485 endDate.setTime(endDate.getTime() + (additionalDays * 86400000));
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"));
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(",");
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");
508 if (attendeesNames[i].length > 0)
509 value += attendeesNames[i] + " ";
510 value += "<" + attendeesEmails[i] + ">";
512 $(input).addClassName("textField");
513 input.setAttribute("modified", "0");
515 td.appendChild(input);
516 displayFreeBusyForNode(input);
520 attendeesNames = new Array();
521 attendeesEmails = new Array();
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]);
533 function onFreeBusyLoadHandler() {
534 initializeWindowButtons();
535 initializeTimeWidgets();
537 prepareTableHeaders();
539 redisplayFreeBusyZone();
540 resetAttendeesValue();
541 initializeFreebusys();
544 addEvent(window, 'load', onFreeBusyLoadHandler);