* iteratorstruct private again
[citadel.git] / webcit / static / wclib.js
1 //
2 // $Id$
3 //
4 // JavaScript function library for WebCit.
5 //
6 //
7
8
9 var browserType;
10 var room_is_trash = 0;
11
12 var currentlyExpandedFloor = null;
13 var roomlist = null;
14
15 var _switchToRoomList = "switch to room list";
16 var _switchToMenu = "switch to menu";
17
18 var currentDropTarget = null;
19
20 var supportsAddEventListener = (!!document.addEventListener);
21 var today = new Date();
22
23 var wc_log = "";
24 var is_ie6 = false;
25 if (document.all) {browserType = "ie"}
26 if (window.navigator.userAgent.toLowerCase().match("gecko")) {
27         browserType= "gecko";
28 }
29 var ns6=document.getElementById&&!document.all;
30 Event.observe(window, 'load', ToggleTaskDateOrNoDateActivate);
31 Event.observe(window, 'load', taskViewActivate);
32 Event.observe(window, 'load', fixbanner);
33 Event.observe(window, 'load', resizeViewport);
34 Event.observe(window, 'resize', resizeViewport);
35 //document.observe("dom:loaded", setupPrefEngine);
36 document.observe("dom:loaded", setupIconBar);
37 document.observe('dom:loaded', function() { if (!!document.getElementById("ib_chat_launch")) { $('ib_chat_launch').observe('click', launchChat); } });
38 function CtdlRandomString()  {
39         return((Math.random()+'').substr(3));
40 }
41
42 function emptyElement(element) {
43   childNodes = element.childNodes;
44   for(var i=0; i<childNodes.length; i++) {
45     try {
46     element.removeChild(childNodes[i]);
47     } catch (e) {
48       WCLog(e+"|"+e.description);
49     }
50   }
51 }
52 /** Implements superior internet explorer 'extract all child text from element' feature'. Falls back on buggy, patent violating standardized method */
53 function getTextContent(element) {
54   if (element.textContent == undefined) {
55     return element.innerText;
56   }
57   return element.textContent;
58 }
59 /** Same reasons as above */
60 function setTextContent(element, textContent) {
61   if(element.textContent == undefined) {
62     element.innerText = textContent;
63   } else {
64   element.textContent = textContent;
65   }
66 }
67
68 // We love string tokenizers.
69 function extract_token(source_string, token_num, delimiter) {
70         var i = 0;
71         var extracted_string = source_string;
72
73         if (token_num > 0) {
74                 for (i=0; i<token_num; ++i) {
75                         var j = extracted_string.indexOf(delimiter);
76                         if (j >= 0) {
77                                 extracted_string = extracted_string.substr(j+1);
78                         }
79                 }
80         }
81
82         j = extracted_string.indexOf(delimiter);
83         if (j >= 0) {
84                 extracted_string = extracted_string.substr(0, j);
85         }
86
87         return extracted_string;
88 }
89
90 function CtdlSpawnContextMenu(event, source) {
91   // remove any existing menus
92   disintergrateContextMenus(null);
93   var x = event.clientX-10; // cut a few pixels out so our mouseout works right
94   var y = event.clientY-10;
95   var contextDIV = document.createElement("div");
96   contextDIV.setAttribute("id", "ctdlContextMenu");
97   document.body.appendChild(contextDIV);
98   var sourceChildren = source.childNodes;
99   for(var j=0; j<sourceChildren.length; j++) {
100     contextDIV.appendChild(sourceChildren[j].cloneNode(true));
101   }
102   var leftRule = "left: "+x+"px;";
103   contextDIV.setAttribute("style", leftRule);
104   contextDIV.setAttribute("actual", leftRule);
105   contextDIV.style.top = y+"px";
106   contextDIV.style.display = "block";
107   $(contextDIV).observe('mouseout',disintergrateContextMenus);
108 }
109 function disintergrateContextMenus(event) {
110   var contextMenu = document.getElementById("ctdlContextMenu");
111   if (contextMenu) {
112     contextMenu.parentNode.removeChild(contextMenu);
113   }
114   Event.stopObserving(document,'click',disintergrateContextMenus);
115 }
116 // This code handles the popups for important-messages.
117 function hide_imsg_popup() {
118         if (browserType == "gecko") {
119                 document.poppedLayer = eval('document.getElementById(\'important_message\')');
120         }
121         else if (browserType == "ie") {
122                 document.poppedLayer = eval('document.all[\'important_message\']');
123         }
124         else {
125                 document.poppedLayer = eval('document.layers[\'`important_message\']');
126         }
127
128         document.poppedLayer.style.visibility = "hidden";
129 }
130
131
132 // This function activates the ajax-powered recipient autocompleters on the message entry screen.
133 function activate_entmsg_autocompleters() {
134         new Ajax.Autocompleter('cc_id', 'cc_name_choices', 'cc_autocomplete', {} );
135         new Ajax.Autocompleter('bcc_id', 'bcc_name_choices', 'bcc_autocomplete', {} );
136         new Ajax.Autocompleter('recp_id', 'recp_name_choices', 'recp_autocomplete', {} );
137 }
138
139 function setupIconBar() {
140   if (!document.getElementById("switch")) {
141       return;
142     }
143   _switchToRoomList = getTextContent(document.getElementById("rmlist_template"));
144   _switchToMenu = getTextContent(document.getElementById("mnlist_template"));
145   var switchSpan = document.getElementById("switch").firstChild;
146   if (switchSpan != null) {
147     setTextContent(switchSpan, _switchToRoomList);
148     $(switchSpan).observe('click', changeIconBarEvent);
149     var currentView = ctdlLocalPrefs.readPref("iconbar_view");
150     if (currentView != null) {
151       switchSpan.ctdlSwitchIconBarTo = currentView;
152       changeIconBar(switchSpan);
153     } else {
154       switchSpan.ctdlSwitchIconBarTo = "rooms";
155     }
156   }
157   var online_users = document.getElementById("online_users");
158   if (online_users.offsetParent != null && online_users.offsetTop > 0) {
159     new Ajax.PeriodicalUpdater('online_users', 'do_template?template=wholist_section', {method: 'get', frequency: 30});
160   }
161 }
162 function changeIconBarEvent(event) {
163   changeIconBar(event.target);
164 }
165 function changeIconBar(target) {
166   var switchTo = target.ctdlSwitchIconBarTo;
167   WCLog("Changing to: " + switchTo);
168   ctdlLocalPrefs.setPref("iconbar_view", target.ctdlSwitchIconBarTo);  
169   if (switchTo == "rooms") {
170     switch_to_room_list();
171     setTextContent(target, _switchToMenu);
172     target.ctdlSwitchIconBarTo = "menu";
173   } else {
174     switch_to_menu_buttons();
175     setTextContent(target, _switchToRoomList);
176     target.ctdlSwitchIconBarTo = "rooms";
177   }
178 }
179 function switch_to_room_list() {
180   var roomlist = document.getElementById("roomlist");
181   var summary = document.getElementById("iconbar_menu");
182   if (!rooms || !floors || !roomlist) {
183     FillRooms(IconBarRoomList);
184   }
185   roomlist.className = roomlist.className.replace("hidden","");
186   summary.className += " hidden";
187 }
188
189 function switch_to_menu_buttons() {
190   if (roomlist != null) {
191     roomlist.className += "hidden";
192   }
193   var iconbar = document.getElementById("iconbar_menu");
194   iconbar.className = iconbar.className.replace("hidden","");
195   var roomlist = document.getElementById("roomlist");
196   roomlist.className += " hidden";
197 }
198 function IconBarRoomList() {
199   var currentExpanded = ctdlLocalPrefs.readPref("rooms_expanded");
200   currentDropTargets = new Array();
201   var iconbar = document.getElementById("iconbar");
202   roomlist = document.getElementById("roomlist");
203   var ul = document.createElement("ul");
204   roomlist.appendChild(ul);
205   // Add mailbox, because they are special
206   var mailboxLI = document.createElement("li");
207   ul.appendChild(mailboxLI);
208   var mailboxSPAN = document.createElement("span");
209   var _mailbox = getTextContent(document.getElementById("mbox_template"));
210   mailboxSPAN.appendChild(document.createTextNode(_mailbox));
211   $(mailboxSPAN).observe('click', expandFloorEvent);
212   mailboxLI.appendChild(mailboxSPAN);
213   mailboxLI.setAttribute("class", "floor");
214   var mailboxUL = document.createElement("ul");
215   mailboxLI.appendChild(mailboxUL);
216   var mailboxRooms = GetMailboxRooms();
217   for(var i=0; i<mailboxRooms.length; i++) {
218     var room = mailboxRooms[i];
219     currentDropTargets.push(addRoomToList(mailboxUL, room));
220   }
221   if (currentExpanded != null && currentExpanded == _mailbox ) {
222     expandFloor(mailboxSPAN);
223   }
224   for(var a=0; a<floors.length; a++) {
225     var floor = floors[a];
226     var floornum = floor[0];
227     var name = floor[1];
228     var floorLI = document.createElement("li");
229     ul.appendChild(floorLI);
230     var floorSPAN = document.createElement("span");
231     floorSPAN.appendChild(document.createTextNode(name));
232     $(floorSPAN).observe('click', expandFloorEvent);
233     floorLI.appendChild(floorSPAN);
234     floorLI.setAttribute("class", "floor");
235     var floorUL = document.createElement("ul");
236     floorLI.appendChild(floorUL);
237     var roomsForFloor = GetRoomsByFloorNum(floornum);
238     for(var b=0; b<roomsForFloor.length; b++) {
239       var room = roomsForFloor[b];
240       currentDropTargets.push(addRoomToList(floorUL, room));
241     }
242     if (currentExpanded != null && currentExpanded == name) {
243       expandFloor(floorSPAN);
244     }
245   }
246 }
247
248 function addRoomToList(floorUL,room) {
249   var roomName = room[RN_ROOM_NAME];
250   var flag = room[RN_ROOM_FLAG];
251   var curView = room[RN_CUR_VIEW];
252   var view = room[RN_DEF_VIEW];
253   var isMailBox = ((flag & QR_MAILBOX) == QR_MAILBOX);
254   var hasNewMsgs = ((curView & UA_HASNEWMSGS) == UA_HASNEWMSGS);
255   var roomLI = document.createElement("li");
256   var roomA = document.createElement("a");
257   roomA.setAttribute("href","dotgoto?room="+roomName);
258   roomA.appendChild(document.createTextNode(roomName));
259   roomLI.appendChild(roomA);
260   floorUL.appendChild(roomLI);
261   var className = "room ";
262   if (view == VIEW_MAILBOX) {
263     className += "room-private"
264   } else if (view == VIEW_ADDRESSBOOK) {
265     className += "room-addr";
266   } else if (view == VIEW_CALENDAR || view == VIEW_CALBRIEF) {
267     className += "room-cal";
268   } else if (view == VIEW_TASKS) {
269     className += "room-tasks";
270   } else if (view == VIEW_NOTES) {
271     className += "room-notes";
272   } else {
273     className += "room-chat";
274   }
275   if (hasNewMsgs) {
276     className += " room-newmsgs";
277   }
278   roomLI.setAttribute("class", className);
279   roomA.dropTarget = true;
280   roomA.dropHandler = roomListDropHandler;
281   return roomLI;
282 }
283
284 function roomListDropHandler(target, dropped) {
285   if (dropped.ctdlMsgId) {
286     var room = getTextContent(target);
287     var msgIds = "";
288     for(msgId in currentlyMarkedRows) { //defined in summaryview.js
289       msgIds += ","+msgId;
290     }
291     var mvCommand = "g_cmd=MOVE " + msgIds + "|"+room+"|0";
292     new Ajax.Request('ajax_servcmd', {
293       method: 'post',
294           parameters: mvCommand,
295           onComplete: deleteAllMarkedRows()});
296     } 
297 }
298 function expandFloorEvent(event) {
299   expandFloor(event.target);
300 }
301 function expandFloor(target) {
302   if (target.nodeName.toLowerCase() != "span") {
303     return; // ignore clicks on child UL
304   }
305   ctdlLocalPrefs.setPref("rooms_expanded", target.firstChild.nodeValue);
306   var parentUL = target.parentNode;
307   if (currentlyExpandedFloor != null) {
308     currentlyExpandedFloor.className = currentlyExpandedFloor.className.replace("floor-expanded","");
309   }
310   parentUL.className = parentUL.className + " floor-expanded";
311   currentlyExpandedFloor = parentUL;
312 }
313
314 // These functions handle moving sticky notes around the screen by dragging them
315
316 var uid_of_note_being_dragged = 0;
317 var saved_cursor_style = 'default';
318 var note_was_dragged = 0;
319
320 function NotesDragMouseUp(evt) {
321         document.onmouseup = null;
322         document.onmousemove = null;
323         if (document.layers) {
324                 document.releaseEvents(Event.MOUSEUP | Event.MOUSEMOVE);
325         }
326
327         d = $('note-' + uid_of_note_being_dragged);
328         d.style.cursor = saved_cursor_style;
329
330         // If any motion actually occurred, submit an ajax http call to record it to the server
331         if (note_was_dragged > 0) {
332                 p = 'note_uid=' + uid_of_note_being_dragged
333                         + '&left=' + d.style.left
334                         + '&top=' + d.style.top
335                         + '&r=' + CtdlRandomString();
336                 new Ajax.Request(
337                         'ajax_update_note',
338                         {
339                                 method: 'post',
340                                 parameters: p
341                         }
342                 );
343         }
344
345         uid_of_note_being_dragged = '';
346         return true;
347 }
348
349 function NotesDragMouseMove(evt) {
350         x = (ns6 ? evt.clientX : event.clientX);
351         x_increment = x - saved_x;
352         y = (ns6 ? evt.clientY : event.clientY);
353         y_increment = y - saved_y;
354
355         // Move the div
356         d = $('note-' + uid_of_note_being_dragged);
357
358         divTop = parseInt(d.style.top);
359         divLeft = parseInt(d.style.left);
360
361         d.style.top = (divTop + y_increment) + 'px';
362         d.style.left = (divLeft + x_increment) + 'px';
363
364         saved_x = x;
365         saved_y = y;
366         note_was_dragged = 1;
367         return true;
368 }
369
370
371 function NotesDragMouseDown(evt, uid) {
372         saved_x = (ns6 ? evt.clientX : event.clientX);
373         saved_y = (ns6 ? evt.clientY : event.clientY);
374         document.onmouseup = NotesDragMouseUp;
375         document.onmousemove = NotesDragMouseMove;
376         if (document.layers) {
377                 document.captureEvents(Event.MOUSEUP | Event.MOUSEMOVE);
378         }
379         uid_of_note_being_dragged = uid;
380         d = $('note-' + uid_of_note_being_dragged);
381         saved_cursor_style = d.style.cursor;
382         d.style.cursor = 'move';
383         return false;           // disable the default action
384 }
385
386
387 // Called when the user clicks on the palette icon of a sticky note to change its color.
388 // It toggles the color selector visible or invisible.
389
390 function NotesClickPalette(evt, uid) {
391         uid_of_note_being_colored = uid;
392         d = $('palette-' + uid_of_note_being_colored);
393
394         if (d.style.display) {
395                 if (d.style.display == 'none') {
396                         d.style.display = 'block';
397                 }
398                 else {
399                         d.style.display = 'none';
400                 }
401         }
402         else {
403                 d.style.display = 'block';
404         }
405
406         return true;
407 }
408
409
410 // Called when the user clicks on one of the colors in an open color selector.
411 // Sets the desired color and then closes the color selector.
412
413 function NotesClickColor(evt, uid, red, green, blue, notecolor, titlecolor) {
414         uid_of_note_being_colored = uid;
415         palette_button = $('palette-' + uid_of_note_being_colored);
416         note_div = $('note-' + uid_of_note_being_colored);
417         titlebar_div = $('titlebar-' + uid_of_note_being_colored);
418
419         // alert('FIXME red=' + red + ' green=' + green + ' blue=' + blue);
420
421         note_div.style.backgroundColor = notecolor;
422         titlebar_div.style.backgroundColor = titlecolor;
423         palette_button.style.display = 'none';
424
425         // submit an ajax http call to record it to the server
426         p = 'note_uid=' + uid_of_note_being_colored
427                 + '&red=' + red
428                 + '&green=' + green
429                 + '&blue=' + blue
430                 + '&r=' + CtdlRandomString();
431         new Ajax.Request(
432                 'ajax_update_note',
433                 {
434                         method: 'post',
435                         parameters: p
436                 }
437         );
438 }
439
440
441
442
443 // These functions handle resizing sticky notes by dragging the resize handle
444
445 var uid_of_note_being_resized = 0;
446 var saved_cursor_style = 'default';
447 var note_was_resized = 0;
448
449 function NotesResizeMouseUp(evt) {
450         document.onmouseup = null;
451         document.onmousemove = null;
452         if (document.layers) {
453                 document.releaseEvents(Event.MOUSEUP | Event.MOUSEMOVE);
454         }
455
456         d = $('note-' + uid_of_note_being_resized);
457         d.style.cursor = saved_cursor_style;
458
459         // If any motion actually occurred, submit an ajax http call to record it to the server
460         if (note_was_resized > 0) {
461                 p = 'note_uid=' + uid_of_note_being_resized
462                         + '&width=' + d.style.width
463                         + '&height=' + d.style.height
464                         + '&r=' + CtdlRandomString();
465                 new Ajax.Request(
466                         'ajax_update_note',
467                         {
468                                 method: 'post',
469                                 parameters: p
470                         }
471                 );
472         }
473
474         uid_of_note_being_resized = '';
475         return false;           // disable the default action
476 }
477
478 function NotesResizeMouseMove(evt) {
479         x = (ns6 ? evt.clientX : event.clientX);
480         x_increment = x - saved_x;
481         y = (ns6 ? evt.clientY : event.clientY);
482         y_increment = y - saved_y;
483
484         // Move the div
485         d = $('note-' + uid_of_note_being_resized);
486
487         divTop = parseInt(d.style.height);
488         divLeft = parseInt(d.style.width);
489
490         d.style.height = (divTop + y_increment) + 'px';
491         d.style.width = (divLeft + x_increment) + 'px';
492
493         saved_x = x;
494         saved_y = y;
495         note_was_resized = 1;
496         return false;           // disable the default action
497 }
498
499
500 function NotesResizeMouseDown(evt, uid) {
501         saved_x = (ns6 ? evt.clientX : event.clientX);
502         saved_y = (ns6 ? evt.clientY : event.clientY);
503         document.onmouseup = NotesResizeMouseUp;
504         document.onmousemove = NotesResizeMouseMove;
505         if (document.layers) {
506                 document.captureEvents(Event.MOUSEUP | Event.MOUSEMOVE);
507         }
508         uid_of_note_being_resized = uid;
509         d = $('note-' + uid_of_note_being_resized);
510         saved_cursor_style = d.style.cursor;
511         d.style.cursor = 'move';
512         return false;           // disable the default action
513 }
514
515
516 function DeleteStickyNote(evt, uid, confirmation_prompt) {
517         uid_of_note_being_deleted = uid;
518         d = $('note-' + uid_of_note_being_deleted);
519
520         if (confirm(confirmation_prompt)) {
521                 new Effect.Puff(d);
522
523                 // submit an ajax http call to delete it on the server
524                 p = 'note_uid=' + uid_of_note_being_deleted
525                         + '&deletenote=yes'
526                         + '&r=' + CtdlRandomString();
527                 new Ajax.Request(
528                         'ajax_update_note',
529                         {
530                                 method: 'post',
531                                 parameters: p
532                         }
533                 );
534         }
535 }
536
537 function ctdl_ts_getInnerText(el) {
538         if (typeof el == "string") return el;
539         if (typeof el == "undefined") { return el };
540         if (el.innerText) return el.innerText;  //Not needed but it is faster
541         var str = "";
542         
543         var cs = el.childNodes;
544         var l = cs.length;
545         for (var i = 0; i < l; i++) {
546                 switch (cs[i].nodeType) {
547                         case 1: //ELEMENT_NODE
548                                 str += ts_getInnerText(cs[i]);
549                                 break;
550                         case 3: //TEXT_NODE
551                                 str += cs[i].nodeValue;
552                                 break;
553                 }
554         }
555         return str;
556 }
557
558
559 // Place a gradient loadscreen on an element, e.g to use before Ajax.updater
560 function CtdlLoadScreen(elementid) {
561 var elem = document.getElementById(elementid);
562 elem.innerHTML = "<div align=center><br><table border=0 cellpadding=10 bgcolor=\"#ffffff\"><tr><td><img src=\"static/throbber.gif\" /><font color=\"#AAAAAA\">&nbsp;&nbsp;Loading....</font></td></tr></table><br /></div>";
563 }
564
565
566
567 // Pop open the address book (target_input is the INPUT field to populate)
568
569 function PopOpenAddressBook(target_input) {
570         $('address_book_popup').style.display = 'block';
571         p = 'target_input=' + target_input + '&r=' + CtdlRandomString();
572         new Ajax.Updater(
573                 'address_book_popup_middle_div',
574                 'display_address_book_middle_div',
575                 {
576                         method: 'get',
577                         parameters: p,
578                         evalScripts: true
579                 }
580         );
581 }
582
583 function PopulateAddressBookInnerDiv(which_addr_book, target_input) {
584         $('address_book_inner_div').innerHTML = "<div align=center><br><table border=0 cellpadding=10 bgcolor=\"#ffffff\"><tr><td><img src=\"static/throbber.gif\" /><font color=\"#AAAAAA\">&nbsp;&nbsp;Loading....</font></td></tr></table><br /></div>";
585         p = 'which_addr_book=' + which_addr_book
586           + '&target_input=' + target_input
587           + '&r=' + CtdlRandomString();
588         new Ajax.Updater(
589                 'address_book_inner_div',
590                 'display_address_book_inner_div',
591                 {
592                         method: 'get',
593                         parameters: p
594                 }
595         );
596 }
597
598 // What happens when a contact is selected from the address book popup
599 // (populate the specified target)
600
601 function AddContactsToTarget(target, whichaddr) {
602         while (whichaddr.selectedIndex != -1) {
603                 if (target.value.length > 0) {
604                         target.value = target.value + ', ';
605                 }
606                 target.value = target.value + whichaddr.value;
607                 whichaddr.options[whichaddr.selectedIndex].selected = false;
608         }
609 }
610
611 // Respond to a meeting invitation
612 function RespondToInvitation(question_divname, title_divname, msgnum, cal_partnum, sc) {
613         p = 'msgnum=' + msgnum + '&cal_partnum=' + cal_partnum + '&sc=' + sc ;
614         new Ajax.Updater(title_divname, 'respond_to_request', { method: 'post', parameters: p } );
615         Effect.Fade(question_divname, { duration: 0.5 });
616 }
617
618 // Handle a received RSVP
619 function HandleRSVP(question_divname, title_divname, msgnum, cal_partnum, sc) {
620         p = 'msgnum=' + msgnum + '&cal_partnum=' + cal_partnum + '&sc=' + sc ;
621         new Ajax.Updater(title_divname, 'handle_rsvp', { method: 'post', parameters: p } );
622         Effect.Fade(question_divname, { duration: 0.5 });
623 }
624 /* var fakeMouse = document.createEvent("MouseEvents");
625  fakeMouse.initMouseEvent("click", true, true, window, 
626    0,0,0,0,0, false, false, false, false, 0, null); */
627 // TODO: Collapse into one function
628 function toggleTaskDtStart(event) {
629         var checkBox = $('nodtstart');
630         dtStart = document.getElementById("dtstart");
631         if (checkBox.checked) {
632                 dtStart.disabled = true;
633                 dtStart.style.textDecoration = "line-through";
634         } else {
635                 dtStart.disabled = false;
636                 dtStart.style.textDecoration = "";
637                 if (dtStart.value.length == 0)
638                         dtStart.dpck._initCurrentDate();
639         }
640 }
641 function toggleTaskDue(event) {
642         var checkBox = $('nodue');
643         dueField = document.getElementById("due");
644         if (checkBox.checked) {
645                 dueField.disabled = true;
646                 dueField.style.textDecoration = "line-through";
647         } else {
648                 dueField.disabled = false;
649                 dueField.style.textDecoration = "";
650                 if (dueField.value.length == 0)
651                         dueField.dpck._initCurrentDate();
652         }
653 }
654 function ToggleTaskDateOrNoDateActivate(event) {
655         var dtstart = document.getElementById("nodtstart");
656         if (dtstart != null) {
657                 toggleTaskDtStart(null);
658                 toggleTaskDue(null);
659                 $('nodtstart').observe('click', toggleTaskDtStart);
660                 $('nodue').observe('click', toggleTaskDue);
661         } 
662 }
663 function TaskViewGatherCategoriesFromTable() {
664         var table = $('taskview');
665         
666 }
667 function attachDatePicker(relative) {
668         var dpck = new DatePicker({
669         relative: relative,
670               language: 'en', //wclang.substr(0,2),
671               disableFutureDate: false,
672               dateFormat: [ ["yyyy", "mm", "dd"], "-"],
673               showDuration: 0.2
674         });
675         document.getElementById(relative).dpck = dpck; // attach a ref to it
676 }
677 function eventEditAllDay() {
678         var allDayCheck = document.getElementById("alldayevent");
679         var dtend= document.getElementById("dtendcell");
680         if(allDayCheck.checked) {
681                 //dtend.disabled = true;
682                 dtend.style.textDecoration = "line-through";
683         } else {
684                 //dtend_day.disabled = false;
685                 dtend.style.textDecoration = "";
686         }
687 }
688
689 // Functions which handle show/hide of various elements in the recurrence editor
690
691 function RecurrenceShowHide() {
692
693         if ($('is_recur').checked) {
694                 $('rrule_div').style.display = 'block';
695         }
696         else {
697                 $('rrule_div').style.display = 'none';
698         }
699
700         if ($('freq_selector').selectedIndex == 4) {
701                 $('weekday_selector').style.display = 'block';
702         }
703         else {
704                 $('weekday_selector').style.display = 'none';
705         }
706
707         if ($('freq_selector').selectedIndex == 5) {
708                 $('monthday_selector').style.display = 'block';
709         }
710         else {
711                 $('monthday_selector').style.display = 'none';
712         }
713
714         if ($('rrend_count').checked) {
715                 $('rrcount').disabled = false;
716         }
717         else {
718                 $('rrcount').disabled = true;
719         }
720
721         if ($('rrend_until').checked) {
722                 $('rruntil').disabled = false;
723         }
724         else {
725                 $('rruntil').disabled = true;
726         }
727
728         if ($('rrmonthtype_mday').checked) {
729                 $('rrmday').disabled = false;
730         }
731         else {
732                 $('rrmday').disabled = true;
733         }
734
735         if ($('rrmonthtype_wday').checked) {
736                 $('rrmweek').disabled = false;
737                 $('rrmweekday').disabled = false;
738         }
739         else {
740                 $('rrmweek').disabled = true;
741                 $('rrmweekday').disabled = true;
742         }
743
744         if ($('freq_selector').selectedIndex == 6) {
745                 $('yearday_selector').style.display = 'block';
746         }
747         else {
748                 $('yearday_selector').style.display = 'none';
749         }
750
751         $('ymday').innerHTML = 'XXXX-' + $('dtstart').value.substr(5);
752         $('rrmday').innerHTML = $('dtstart').value.substr(8);
753
754         if ($('rryeartype_ywday').checked) {
755                 $('rrymweek').disabled = false;
756                 $('rrymweekday').disabled = false;
757                 $('rrymonth').disabled = false;
758         }
759         else {
760                 $('rrymweek').disabled = true;
761                 $('rrymweekday').disabled = true;
762                 $('rrymonth').disabled = true;
763         }
764
765 }
766 function launchChat(event) {
767 window.open('chat', 'ctdl_chat_window', 'toolbar=no,location=no,directories=no,copyhistory=no,status=no,scrollbars=yes,resizable=yes');
768 }
769 // logger
770 function WCLog(msg) {
771   if (!!window.console && !!console.log) {
772     console.log(msg);
773   } else if (!!window.opera && !!opera.postError) {
774     opera.postError(msg);
775   } else {
776     wc_log += msg + "\r\n";
777   }
778 }
779
780 function fixMissingCSSTable(elems) {
781  if (elems[0] == null || elems[1] == null) {
782     return;
783   }
784   if (elems[0].getStyle("display") != "table-cell") {
785     var parentNode = elems[0].parentNode;
786     var table = document.createElement("table");
787     table.style.width = "100%";
788     var tbody = document.createElement("tbody");
789     table.appendChild(tbody);
790     var tr = document.createElement("tr");
791     tbody.appendChild(tr);
792     parentNode.appendChild(table);
793     for(var i=0; i<elems.length; i++) {
794       parentNode.removeChild(elems[i]);
795       var td = document.createElement("td");
796       td.appendChild(elems[i]);
797       tr.appendChild(td);
798     }
799   }
800 }
801 function fixbanner() {
802   // Use prototype api methods here
803   var elems = [$('room_banner'),$('actiondiv')];
804   fixMissingCSSTable(elems);
805   if (!is_ie6) {
806     Event.observe(window, 'resize', makeContentScrollable);
807     makeContentScrollable();
808   }
809 }
810 function makeContentScrollable() {
811 if (document.getElementById("banner")
812       && document.getElementById("content") 
813       && !document.getElementById("summary_view")) {
814   WCLog("makeContentScrollable");
815     document.body.style.overflowY="hidden";
816     var global = $("global");
817     global.className += "scrollable";
818     var content = document.getElementById("content");
819     var banner = document.getElementById("banner");
820     var bannerHeight = banner.offsetHeight;
821     banner.style.width="100%";
822     var bannerPercent = (bannerHeight/document.viewport.getHeight())*100;
823     //banner.style.height=bannerPercent+"%";
824     content.style.overflowY="scroll";
825     //content.style.top=bannerPercent+"%";
826     content.style.height=(100-bannerPercent)+"%";
827     content.style.right="0px";
828   }
829 }
830 function fixOffsetBanner() {
831   var banner = document.getElementById("banner");
832   if (banner.offsetLeft > 0) {
833     var viewportWidth = document.viewport.getWidth();
834     var iconbarWidth = document.getElementById("iconbar").offsetWidth;
835     var contentDiv = document.getElementById("content");
836     var newContentWidth = viewportWidth-iconbarWidth;
837     contentDiv.style.width = newContentWidth+"px";
838   }
839 }
840 /** Attempt to stop overflowing in x-axis in IE6 */
841 function resizeViewport() {
842   var documentWidth = 0;
843   var viewportWidth = document.viewport.getWidth();
844   var iconbar = $('iconbar');
845   var global = $('global');
846   if (iconbar == null || global == null || document.documentElement == null) {
847     return;
848   }
849   if (typeof window.offsetWidth != 'undefined') {
850     documentWidth = window.offsetWidth;
851   } else {
852     documentWidth = document.documentElement.offsetWidth;
853   }
854   if (documentWidth > viewportWidth) {
855     WCLog("resizeViewport");
856     document.documentElement.style.width = viewportWidth+"px";
857     document.documentElement.style.overflowX = "hidden";
858     //viewportWidth = 0.98 * viewportWidth;
859     var newIconBarSize = 0.16 * viewportWidth;
860     var newContentSize = viewportWidth - newIconBarSize;
861     iconbar.style.width = newIconBarSize+"px";
862     global.style.width = newContentSize+"px";
863   }
864 }