* Fix user push email config
[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   var curRoomName = "";
201   if (document.getElementById("rmname")) {
202     curRoomName = getTextContent(document.getElementById("rmname"));
203   }
204   currentDropTargets = new Array();
205   var iconbar = document.getElementById("iconbar");
206   roomlist = document.getElementById("roomlist");
207   var ul = document.createElement("ul");
208   roomlist.appendChild(ul);
209   // Add mailbox, because they are special
210   var mailboxLI = document.createElement("li");
211   ul.appendChild(mailboxLI);
212   var mailboxSPAN = document.createElement("span");
213   var _mailbox = getTextContent(document.getElementById("mbox_template"));
214   mailboxSPAN.appendChild(document.createTextNode(_mailbox));
215   $(mailboxSPAN).observe('click', expandFloorEvent);
216   mailboxLI.appendChild(mailboxSPAN);
217   mailboxLI.setAttribute("class", "floor");
218   var mailboxUL = document.createElement("ul");
219   mailboxLI.appendChild(mailboxUL);
220   var mailboxRooms = GetMailboxRooms();
221   for(var i=0; i<mailboxRooms.length; i++) {
222     var room = mailboxRooms[i];
223     currentDropTargets.push(addRoomToList(mailboxUL, room, curRoomName));
224   }
225   if (currentExpanded != null && currentExpanded == _mailbox ) {
226     expandFloor(mailboxSPAN);
227   }
228   for(var a=0; a<floors.length; a++) {
229     var floor = floors[a];
230     var floornum = floor[0];
231     var name = floor[1];
232     var floorLI = document.createElement("li");
233     ul.appendChild(floorLI);
234     var floorSPAN = document.createElement("span");
235     floorSPAN.appendChild(document.createTextNode(name));
236     $(floorSPAN).observe('click', expandFloorEvent);
237     floorLI.appendChild(floorSPAN);
238     floorLI.setAttribute("class", "floor");
239     var floorUL = document.createElement("ul");
240     floorLI.appendChild(floorUL);
241     var roomsForFloor = GetRoomsByFloorNum(floornum);
242     for(var b=0; b<roomsForFloor.length; b++) {
243       var room = roomsForFloor[b];
244       currentDropTargets.push(addRoomToList(floorUL, room, curRoomName));
245     }
246     if (currentExpanded != null && currentExpanded == name) {
247       expandFloor(floorSPAN);
248     }
249   }
250 }
251
252 function addRoomToList(floorUL,room, roomToEmphasize) {
253   var roomName = room[RN_ROOM_NAME];
254   var flag = room[RN_ROOM_FLAG];
255   var curView = room[RN_CUR_VIEW];
256   var view = room[RN_DEF_VIEW];
257   var isMailBox = ((flag & QR_MAILBOX) == QR_MAILBOX);
258   var hasNewMsgs = ((curView & UA_HASNEWMSGS) == UA_HASNEWMSGS);
259   var roomLI = document.createElement("li");
260   var roomA = document.createElement("a");
261   roomA.setAttribute("href","dotgoto?room="+roomName);
262   roomA.appendChild(document.createTextNode(roomName));
263   roomLI.appendChild(roomA);
264   floorUL.appendChild(roomLI);
265   var className = "room ";
266   if (view == VIEW_MAILBOX) {
267     className += "room-private"
268   } else if (view == VIEW_ADDRESSBOOK) {
269     className += "room-addr";
270   } else if (view == VIEW_CALENDAR || view == VIEW_CALBRIEF) {
271     className += "room-cal";
272   } else if (view == VIEW_TASKS) {
273     className += "room-tasks";
274   } else if (view == VIEW_NOTES) {
275     className += "room-notes";
276   } else {
277     className += "room-chat";
278   }
279   if (hasNewMsgs) {
280     className += " room-newmsgs";
281   }
282   if (roomName == roomToEmphasize) {
283     className += " room-emphasized";
284   }
285   roomLI.setAttribute("class", className);
286   roomA.dropTarget = true;
287   roomA.dropHandler = roomListDropHandler;
288   return roomLI;
289 }
290
291 function roomListDropHandler(target, dropped) {
292   if (dropped.ctdlMsgId) {
293     var room = getTextContent(target);
294     var msgIds = "";
295     for(msgId in currentlyMarkedRows) { //defined in summaryview.js
296       msgIds += ","+msgId;
297     }
298     var mvCommand = "g_cmd=MOVE " + msgIds + "|"+room+"|0";
299     new Ajax.Request('ajax_servcmd', {
300       method: 'post',
301           parameters: mvCommand,
302           onComplete: deleteAllMarkedRows()});
303     } 
304 }
305 function expandFloorEvent(event) {
306   expandFloor(event.target);
307 }
308 function expandFloor(target) {
309   if (target.nodeName.toLowerCase() != "span") {
310     return; // ignore clicks on child UL
311   }
312   ctdlLocalPrefs.setPref("rooms_expanded", target.firstChild.nodeValue);
313   var parentUL = target.parentNode;
314   if (currentlyExpandedFloor != null) {
315     currentlyExpandedFloor.className = currentlyExpandedFloor.className.replace("floor-expanded","");
316   }
317   parentUL.className = parentUL.className + " floor-expanded";
318   currentlyExpandedFloor = parentUL;
319 }
320
321 // These functions handle moving sticky notes around the screen by dragging them
322
323 var uid_of_note_being_dragged = 0;
324 var saved_cursor_style = 'default';
325 var note_was_dragged = 0;
326
327 function NotesDragMouseUp(evt) {
328         document.onmouseup = null;
329         document.onmousemove = null;
330         if (document.layers) {
331                 document.releaseEvents(Event.MOUSEUP | Event.MOUSEMOVE);
332         }
333
334         d = $('note-' + uid_of_note_being_dragged);
335         d.style.cursor = saved_cursor_style;
336
337         // If any motion actually occurred, submit an ajax http call to record it to the server
338         if (note_was_dragged > 0) {
339                 p = 'note_uid=' + uid_of_note_being_dragged
340                         + '&left=' + d.style.left
341                         + '&top=' + d.style.top
342                         + '&r=' + CtdlRandomString();
343                 new Ajax.Request(
344                         'ajax_update_note',
345                         {
346                                 method: 'post',
347                                 parameters: p
348                         }
349                 );
350         }
351
352         uid_of_note_being_dragged = '';
353         return true;
354 }
355
356 function NotesDragMouseMove(evt) {
357         x = (ns6 ? evt.clientX : event.clientX);
358         x_increment = x - saved_x;
359         y = (ns6 ? evt.clientY : event.clientY);
360         y_increment = y - saved_y;
361
362         // Move the div
363         d = $('note-' + uid_of_note_being_dragged);
364
365         divTop = parseInt(d.style.top);
366         divLeft = parseInt(d.style.left);
367
368         d.style.top = (divTop + y_increment) + 'px';
369         d.style.left = (divLeft + x_increment) + 'px';
370
371         saved_x = x;
372         saved_y = y;
373         note_was_dragged = 1;
374         return true;
375 }
376
377
378 function NotesDragMouseDown(evt, uid) {
379         saved_x = (ns6 ? evt.clientX : event.clientX);
380         saved_y = (ns6 ? evt.clientY : event.clientY);
381         document.onmouseup = NotesDragMouseUp;
382         document.onmousemove = NotesDragMouseMove;
383         if (document.layers) {
384                 document.captureEvents(Event.MOUSEUP | Event.MOUSEMOVE);
385         }
386         uid_of_note_being_dragged = uid;
387         d = $('note-' + uid_of_note_being_dragged);
388         saved_cursor_style = d.style.cursor;
389         d.style.cursor = 'move';
390         return false;           // disable the default action
391 }
392
393
394 // Called when the user clicks on the palette icon of a sticky note to change its color.
395 // It toggles the color selector visible or invisible.
396
397 function NotesClickPalette(evt, uid) {
398         uid_of_note_being_colored = uid;
399         d = $('palette-' + uid_of_note_being_colored);
400
401         if (d.style.display) {
402                 if (d.style.display == 'none') {
403                         d.style.display = 'block';
404                 }
405                 else {
406                         d.style.display = 'none';
407                 }
408         }
409         else {
410                 d.style.display = 'block';
411         }
412
413         return true;
414 }
415
416
417 // Called when the user clicks on one of the colors in an open color selector.
418 // Sets the desired color and then closes the color selector.
419
420 function NotesClickColor(evt, uid, red, green, blue, notecolor, titlecolor) {
421         uid_of_note_being_colored = uid;
422         palette_button = $('palette-' + uid_of_note_being_colored);
423         note_div = $('note-' + uid_of_note_being_colored);
424         titlebar_div = $('titlebar-' + uid_of_note_being_colored);
425
426         // alert('FIXME red=' + red + ' green=' + green + ' blue=' + blue);
427
428         note_div.style.backgroundColor = notecolor;
429         titlebar_div.style.backgroundColor = titlecolor;
430         palette_button.style.display = 'none';
431
432         // submit an ajax http call to record it to the server
433         p = 'note_uid=' + uid_of_note_being_colored
434                 + '&red=' + red
435                 + '&green=' + green
436                 + '&blue=' + blue
437                 + '&r=' + CtdlRandomString();
438         new Ajax.Request(
439                 'ajax_update_note',
440                 {
441                         method: 'post',
442                         parameters: p
443                 }
444         );
445 }
446
447
448
449
450 // These functions handle resizing sticky notes by dragging the resize handle
451
452 var uid_of_note_being_resized = 0;
453 var saved_cursor_style = 'default';
454 var note_was_resized = 0;
455
456 function NotesResizeMouseUp(evt) {
457         document.onmouseup = null;
458         document.onmousemove = null;
459         if (document.layers) {
460                 document.releaseEvents(Event.MOUSEUP | Event.MOUSEMOVE);
461         }
462
463         d = $('note-' + uid_of_note_being_resized);
464         d.style.cursor = saved_cursor_style;
465
466         // If any motion actually occurred, submit an ajax http call to record it to the server
467         if (note_was_resized > 0) {
468                 p = 'note_uid=' + uid_of_note_being_resized
469                         + '&width=' + d.style.width
470                         + '&height=' + d.style.height
471                         + '&r=' + CtdlRandomString();
472                 new Ajax.Request(
473                         'ajax_update_note',
474                         {
475                                 method: 'post',
476                                 parameters: p
477                         }
478                 );
479         }
480
481         uid_of_note_being_resized = '';
482         return false;           // disable the default action
483 }
484
485 function NotesResizeMouseMove(evt) {
486         x = (ns6 ? evt.clientX : event.clientX);
487         x_increment = x - saved_x;
488         y = (ns6 ? evt.clientY : event.clientY);
489         y_increment = y - saved_y;
490
491         // Move the div
492         d = $('note-' + uid_of_note_being_resized);
493
494         divTop = parseInt(d.style.height);
495         divLeft = parseInt(d.style.width);
496
497         d.style.height = (divTop + y_increment) + 'px';
498         d.style.width = (divLeft + x_increment) + 'px';
499
500         saved_x = x;
501         saved_y = y;
502         note_was_resized = 1;
503         return false;           // disable the default action
504 }
505
506
507 function NotesResizeMouseDown(evt, uid) {
508         saved_x = (ns6 ? evt.clientX : event.clientX);
509         saved_y = (ns6 ? evt.clientY : event.clientY);
510         document.onmouseup = NotesResizeMouseUp;
511         document.onmousemove = NotesResizeMouseMove;
512         if (document.layers) {
513                 document.captureEvents(Event.MOUSEUP | Event.MOUSEMOVE);
514         }
515         uid_of_note_being_resized = uid;
516         d = $('note-' + uid_of_note_being_resized);
517         saved_cursor_style = d.style.cursor;
518         d.style.cursor = 'move';
519         return false;           // disable the default action
520 }
521
522
523 function DeleteStickyNote(evt, uid, confirmation_prompt) {
524         uid_of_note_being_deleted = uid;
525         d = $('note-' + uid_of_note_being_deleted);
526
527         if (confirm(confirmation_prompt)) {
528                 new Effect.Puff(d);
529
530                 // submit an ajax http call to delete it on the server
531                 p = 'note_uid=' + uid_of_note_being_deleted
532                         + '&deletenote=yes'
533                         + '&r=' + CtdlRandomString();
534                 new Ajax.Request(
535                         'ajax_update_note',
536                         {
537                                 method: 'post',
538                                 parameters: p
539                         }
540                 );
541         }
542 }
543
544 function ctdl_ts_getInnerText(el) {
545         if (typeof el == "string") return el;
546         if (typeof el == "undefined") { return el };
547         if (el.innerText) return el.innerText;  //Not needed but it is faster
548         var str = "";
549         
550         var cs = el.childNodes;
551         var l = cs.length;
552         for (var i = 0; i < l; i++) {
553                 switch (cs[i].nodeType) {
554                         case 1: //ELEMENT_NODE
555                                 str += ts_getInnerText(cs[i]);
556                                 break;
557                         case 3: //TEXT_NODE
558                                 str += cs[i].nodeValue;
559                                 break;
560                 }
561         }
562         return str;
563 }
564
565
566 // Place a gradient loadscreen on an element, e.g to use before Ajax.updater
567 function CtdlLoadScreen(elementid) {
568 var elem = document.getElementById(elementid);
569 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>";
570 }
571
572
573
574 // Pop open the address book (target_input is the INPUT field to populate)
575
576 function PopOpenAddressBook(target_input) {
577         $('address_book_popup').style.display = 'block';
578         p = 'target_input=' + target_input + '&r=' + CtdlRandomString();
579         new Ajax.Updater(
580                 'address_book_popup_middle_div',
581                 'display_address_book_middle_div',
582                 {
583                         method: 'get',
584                         parameters: p,
585                         evalScripts: true
586                 }
587         );
588 }
589
590 function PopulateAddressBookInnerDiv(which_addr_book, target_input) {
591         $('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>";
592         p = 'which_addr_book=' + which_addr_book
593           + '&target_input=' + target_input
594           + '&r=' + CtdlRandomString();
595         new Ajax.Updater(
596                 'address_book_inner_div',
597                 'display_address_book_inner_div',
598                 {
599                         method: 'get',
600                         parameters: p
601                 }
602         );
603 }
604
605 // What happens when a contact is selected from the address book popup
606 // (populate the specified target)
607
608 function AddContactsToTarget(target, whichaddr) {
609         while (whichaddr.selectedIndex != -1) {
610                 if (target.value.length > 0) {
611                         target.value = target.value + ', ';
612                 }
613                 target.value = target.value + whichaddr.value;
614                 whichaddr.options[whichaddr.selectedIndex].selected = false;
615         }
616 }
617
618 // Respond to a meeting invitation
619 function RespondToInvitation(question_divname, title_divname, msgnum, cal_partnum, sc) {
620         p = 'msgnum=' + msgnum + '&cal_partnum=' + cal_partnum + '&sc=' + sc ;
621         new Ajax.Updater(title_divname, 'respond_to_request', { method: 'post', parameters: p } );
622         Effect.Fade(question_divname, { duration: 0.5 });
623 }
624
625 // Handle a received RSVP
626 function HandleRSVP(question_divname, title_divname, msgnum, cal_partnum, sc) {
627         p = 'msgnum=' + msgnum + '&cal_partnum=' + cal_partnum + '&sc=' + sc ;
628         new Ajax.Updater(title_divname, 'handle_rsvp', { method: 'post', parameters: p } );
629         Effect.Fade(question_divname, { duration: 0.5 });
630 }
631 /* var fakeMouse = document.createEvent("MouseEvents");
632  fakeMouse.initMouseEvent("click", true, true, window, 
633    0,0,0,0,0, false, false, false, false, 0, null); */
634 // TODO: Collapse into one function
635 function toggleTaskDtStart(event) {
636         var checkBox = $('nodtstart');
637         dtStart = document.getElementById("dtstart");
638         if (checkBox.checked) {
639                 dtStart.disabled = true;
640                 dtStart.style.textDecoration = "line-through";
641         } else {
642                 dtStart.disabled = false;
643                 dtStart.style.textDecoration = "";
644                 if (dtStart.value.length == 0)
645                         dtStart.dpck._initCurrentDate();
646         }
647 }
648 function toggleTaskDue(event) {
649         var checkBox = $('nodue');
650         dueField = document.getElementById("due");
651         if (checkBox.checked) {
652                 dueField.disabled = true;
653                 dueField.style.textDecoration = "line-through";
654         } else {
655                 dueField.disabled = false;
656                 dueField.style.textDecoration = "";
657                 if (dueField.value.length == 0)
658                         dueField.dpck._initCurrentDate();
659         }
660 }
661 function ToggleTaskDateOrNoDateActivate(event) {
662         var dtstart = document.getElementById("nodtstart");
663         if (dtstart != null) {
664                 toggleTaskDtStart(null);
665                 toggleTaskDue(null);
666                 $('nodtstart').observe('click', toggleTaskDtStart);
667                 $('nodue').observe('click', toggleTaskDue);
668         } 
669 }
670 function TaskViewGatherCategoriesFromTable() {
671         var table = $('taskview');
672         
673 }
674 function attachDatePicker(relative) {
675         var dpck = new DatePicker({
676         relative: relative,
677               language: 'en', //wclang.substr(0,2),
678               disableFutureDate: false,
679               dateFormat: [ ["yyyy", "mm", "dd"], "-"],
680               showDuration: 0.2
681         });
682         document.getElementById(relative).dpck = dpck; // attach a ref to it
683 }
684 function eventEditAllDay() {
685         var allDayCheck = document.getElementById("alldayevent");
686         var dtend= document.getElementById("dtendcell");
687         if(allDayCheck.checked) {
688                 //dtend.disabled = true;
689                 dtend.style.textDecoration = "line-through";
690         } else {
691                 //dtend_day.disabled = false;
692                 dtend.style.textDecoration = "";
693         }
694 }
695
696 // Functions which handle show/hide of various elements in the recurrence editor
697
698 function RecurrenceShowHide() {
699
700         if ($('is_recur').checked) {
701                 $('rrule_div').style.display = 'block';
702         }
703         else {
704                 $('rrule_div').style.display = 'none';
705         }
706
707         if ($('freq_selector').selectedIndex == 4) {
708                 $('weekday_selector').style.display = 'block';
709         }
710         else {
711                 $('weekday_selector').style.display = 'none';
712         }
713
714         if ($('freq_selector').selectedIndex == 5) {
715                 $('monthday_selector').style.display = 'block';
716         }
717         else {
718                 $('monthday_selector').style.display = 'none';
719         }
720
721         if ($('rrend_count').checked) {
722                 $('rrcount').disabled = false;
723         }
724         else {
725                 $('rrcount').disabled = true;
726         }
727
728         if ($('rrend_until').checked) {
729                 $('rruntil').disabled = false;
730         }
731         else {
732                 $('rruntil').disabled = true;
733         }
734
735         if ($('rrmonthtype_mday').checked) {
736                 $('rrmday').disabled = false;
737         }
738         else {
739                 $('rrmday').disabled = true;
740         }
741
742         if ($('rrmonthtype_wday').checked) {
743                 $('rrmweek').disabled = false;
744                 $('rrmweekday').disabled = false;
745         }
746         else {
747                 $('rrmweek').disabled = true;
748                 $('rrmweekday').disabled = true;
749         }
750
751         if ($('freq_selector').selectedIndex == 6) {
752                 $('yearday_selector').style.display = 'block';
753         }
754         else {
755                 $('yearday_selector').style.display = 'none';
756         }
757
758         $('ymday').innerHTML = 'XXXX-' + $('dtstart').value.substr(5);
759         $('rrmday').innerHTML = $('dtstart').value.substr(8);
760
761         if ($('rryeartype_ywday').checked) {
762                 $('rrymweek').disabled = false;
763                 $('rrymweekday').disabled = false;
764                 $('rrymonth').disabled = false;
765         }
766         else {
767                 $('rrymweek').disabled = true;
768                 $('rrymweekday').disabled = true;
769                 $('rrymonth').disabled = true;
770         }
771
772 }
773 function launchChat(event) {
774 window.open('chat', 'ctdl_chat_window', 'toolbar=no,location=no,directories=no,copyhistory=no,status=no,scrollbars=yes,resizable=yes');
775 }
776 // logger
777 function WCLog(msg) {
778   if (!!window.console && !!console.log) {
779     console.log(msg);
780   } else if (!!window.opera && !!opera.postError) {
781     opera.postError(msg);
782   } else {
783     wc_log += msg + "\r\n";
784   }
785 }
786
787 function fixMissingCSSTable(elems) {
788  if (elems[0] == null || elems[1] == null) {
789     return;
790   }
791   if (elems[0].getStyle("display") != "table-cell") {
792     var parentNode = elems[0].parentNode;
793     var table = document.createElement("table");
794     table.style.width = "100%";
795     var tbody = document.createElement("tbody");
796     table.appendChild(tbody);
797     var tr = document.createElement("tr");
798     tbody.appendChild(tr);
799     parentNode.appendChild(table);
800     for(var i=0; i<elems.length; i++) {
801       parentNode.removeChild(elems[i]);
802       var td = document.createElement("td");
803       td.appendChild(elems[i]);
804       tr.appendChild(td);
805     }
806   }
807 }
808 function fixbanner() {
809   // Use prototype api methods here
810   var elems = [$('room_banner'),$('actiondiv')];
811   fixMissingCSSTable(elems);
812   if (!is_ie6) {
813     Event.observe(window, 'resize', makeContentScrollable);
814     makeContentScrollable();
815   }
816 }
817 function makeContentScrollable() {
818 if (document.getElementById("banner")
819       && document.getElementById("content") 
820       && !document.getElementById("summary_view")) {
821   WCLog("makeContentScrollable");
822     document.body.style.overflowY="hidden";
823     var global = $("global");
824     global.className += "scrollable";
825     var content = document.getElementById("content");
826     var banner = document.getElementById("banner");
827     var bannerHeight = banner.offsetHeight;
828     banner.style.width="100%";
829     var bannerPercent = (bannerHeight/document.viewport.getHeight())*100;
830     //banner.style.height=bannerPercent+"%";
831     content.style.overflowY="scroll";
832     //content.style.top=bannerPercent+"%";
833     content.style.height=(100-bannerPercent)+"%";
834     content.style.right="0px";
835   }
836 }
837 function fixOffsetBanner() {
838   var banner = document.getElementById("banner");
839   if (banner.offsetLeft > 0) {
840     var viewportWidth = document.viewport.getWidth();
841     var iconbarWidth = document.getElementById("iconbar").offsetWidth;
842     var contentDiv = document.getElementById("content");
843     var newContentWidth = viewportWidth-iconbarWidth;
844     contentDiv.style.width = newContentWidth+"px";
845   }
846 }
847 /** Attempt to stop overflowing in x-axis in IE6 */
848 function resizeViewport() {
849   var documentWidth = 0;
850   var viewportWidth = document.viewport.getWidth();
851   var iconbar = $('iconbar');
852   var global = $('global');
853   if (iconbar == null || global == null || document.documentElement == null) {
854     return;
855   }
856   if (typeof window.offsetWidth != 'undefined') {
857     documentWidth = window.offsetWidth;
858   } else {
859     documentWidth = document.documentElement.offsetWidth;
860   }
861   if (documentWidth > viewportWidth) {
862     WCLog("resizeViewport");
863     document.documentElement.style.width = viewportWidth+"px";
864     document.documentElement.style.overflowX = "hidden";
865     //viewportWidth = 0.98 * viewportWidth;
866     var newIconBarSize = 0.16 * viewportWidth;
867     var newContentSize = viewportWidth - newIconBarSize;
868     iconbar.style.width = newIconBarSize+"px";
869     global.style.width = newContentSize+"px";
870   }
871 }