]> code.citadel.org Git - citadel.git/blob - webcit/static/wclib.js
* Clicking on the expanded floor div collapses it.
[citadel.git] / webcit / static / wclib.js
1 //
2 // $Id: wclib.js,v 625.2 2005/09/18 04:04:32 ajc Exp $
3 //
4 // JavaScript function library for WebCit.
5 //
6 //
7
8
9 var browserType;
10
11 if (document.layers) {browserType = "nn4"}
12 if (document.all) {browserType = "ie"}
13 if (window.navigator.userAgent.toLowerCase().match("gecko")) {
14         browserType= "gecko"
15 }
16
17 var ns6=document.getElementById&&!document.all;
18
19
20 //
21 // This code handles the popups for instant messages.
22 //
23
24
25 function hide_page_popup() {
26         if (browserType == "gecko" )
27                 document.poppedLayer = eval('document.getElementById(\'page_popup\')');
28         else if (browserType == "ie")
29                 document.poppedLayer = eval('document.all[\'page_popup\']');
30         else
31                 document.poppedLayer = eval('document.layers[\'`page_popup\']');
32
33         document.poppedLayer.style.visibility = "hidden";
34 }
35
36 function hide_imsg_popup() {
37         if (browserType == "gecko" )
38                 document.poppedLayer = eval('document.getElementById(\'important_message\')');
39         else if (browserType == "ie")
40                 document.poppedLayer = eval('document.all[\'important_message\']');
41         else
42                 document.poppedLayer = eval('document.layers[\'`important_message\']');
43
44         document.poppedLayer.style.visibility = "hidden";
45 }
46
47 // This function activates the ajax-powered recipient autocompleters on the message entry screen.
48 function activate_entmsg_autocompleters() {
49         new Ajax.Autocompleter('cc_id', 'cc_name_choices', 'cc_autocomplete', {} );
50         new Ajax.Autocompleter('bcc_id', 'bcc_name_choices', 'bcc_autocomplete', {} );
51         new Ajax.Autocompleter('recp_id', 'recp_name_choices', 'recp_autocomplete', {} );
52 }
53
54
55
56 // Toggle the icon bar between menu/roomlist...
57 var which_div_expanded = null;
58 var num_drop_targets = 0;
59 var drop_targets_elements = new Array();
60 var drop_targets_roomnames = new Array();
61
62 function switch_to_room_list() {
63         $('iconbar').innerHTML = $('iconbar').innerHTML.substr(0, $('iconbar').innerHTML.indexOf('switch'));
64         new Ajax.Updater('iconbar', 'iconbar_ajax_rooms', { method: 'get' } );
65 }
66
67 function expand_floor(floor_div) {
68         if (which_div_expanded != null) {
69                 $(which_div_expanded).style.display = 'none' ;
70         }
71         if (which_div_expanded == floor_div) {
72                 which_div_expanded = null;
73                 return true;
74         }
75         $(floor_div).style.display = 'block';
76         which_div_expanded = floor_div;
77 }
78
79 function switch_to_menu_buttons() {
80         which_div_expanded = null;
81         num_drop_targets = 0;
82         new Ajax.Updater('iconbar', 'iconbar_ajax_menu', { method: 'get' } );
83 }
84
85
86 // Static variables for mailbox view...
87 //
88 var CtdlNumMsgsSelected = 0;
89 var CtdlMsgsSelected = new Array();
90
91 // This gets called when you single click on a message in the mailbox view.
92 // We know that the element id of the table row will be the letter 'm' plus the message number.
93 //
94 function CtdlSingleClickMsg(evt, msgnum) {
95
96         // Clear the preview pane until we load the new message
97         $('preview_pane').innerHTML = '';
98
99         // De-select any messages that were already selected, *unless* the Ctrl key
100         // is being pressed, in which case the user wants multi select.
101         if (!evt.ctrlKey) {
102                 if (CtdlNumMsgsSelected > 0) {
103                         for (i=0; i<CtdlNumMsgsSelected; ++i) {
104                                 $('m'+CtdlMsgsSelected[i]).style.backgroundColor = '#fff';
105                                 $('m'+CtdlMsgsSelected[i]).style.color = '#000';
106                         }
107                         CtdlNumMsgsSelected = 0;
108                 }
109         }
110
111         // For multi select ... is the message being clicked already selected?
112         already_selected = 0;
113         if ( (evt.ctrlKey) && (CtdlNumMsgsSelected > 0) ) {
114                 for (i=0; i<CtdlNumMsgsSelected; ++i) {
115                         if (CtdlMsgsSelected[i] == msgnum) {
116                                 already_selected = 1;
117                         }
118                 }
119         }
120
121         // Now select (or de-select) the message
122         if ( (evt.ctrlKey) && (already_selected == 1) ) {
123                 $('m'+msgnum).style.backgroundColor = '#fff';
124                 $('m'+msgnum).style.color = '#000';
125         }
126         else {
127                 $('m'+msgnum).style.backgroundColor='#69aaff';
128                 $('m'+msgnum).style.color='#fff';
129                 CtdlNumMsgsSelected = CtdlNumMsgsSelected + 1;
130                 CtdlMsgsSelected[CtdlNumMsgsSelected-1] = msgnum;
131         }
132
133         // Update the preview pane
134         new Ajax.Updater('preview_pane', 'msg/'+msgnum, { method: 'get' } );
135
136         // Mark the message as read
137         new Ajax.Request(
138                 'ajax_servcmd', {
139                         method: 'post',
140                         parameters: 'g_cmd=SEEN '+msgnum+'|1',
141                         onComplete: CtdlRemoveTheUnseenBold(msgnum)
142                 }
143         );
144
145         return false;           // try to defeat the default click behavior
146 }
147
148 // Delete selected messages.
149 function CtdlDeleteSelectedMessages(evt) {
150         
151         if (CtdlNumMsgsSelected < 1) {
152                 // Nothing to delete, so exit silently.
153                 return false;
154         }
155         for (i=0; i<CtdlNumMsgsSelected; ++i) {
156                 new Ajax.Request(
157                         'ajax_servcmd', {
158                                 method: 'post',
159                                 parameters: 'g_cmd=MOVE ' + CtdlMsgsSelected[i] + '|_TRASH_|0',
160                                 onComplete: CtdlClearDeletedMsg(CtdlMsgsSelected[i])
161                         }
162                 );
163         }
164         CtdlNumMsgsSelected = 0;
165
166         // Clear the preview pane too.
167         $('preview_pane').innerHTML = '';
168 }
169
170
171 // Move selected messages.
172 function CtdlMoveSelectedMessages(evt, target_roomname) {
173         
174         if (CtdlNumMsgsSelected < 1) {
175                 // Nothing to delete, so exit silently.
176                 return false;
177         }
178         for (i=0; i<CtdlNumMsgsSelected; ++i) {
179                 new Ajax.Request(
180                         'ajax_servcmd', {
181                                 method:'post',
182                                 parameters:'g_cmd=MOVE ' + CtdlMsgsSelected[i] + '|' + target_roomname + '|0',
183                                 onComplete:CtdlClearDeletedMsg(CtdlMsgsSelected[i])
184                         }
185                 );
186         }
187         CtdlNumMsgsSelected = 0;
188
189         // Clear the preview pane too.
190         $('preview_pane').innerHTML = '';
191 }
192
193
194
195 // This gets called when the user touches the keyboard after selecting messages...
196 function CtdlMsgListKeyPress(evt) {
197         if(document.all) {                              // aIEeee
198                 var whichKey = window.event.keyCode;
199         }
200         else {                                          // non-sux0r browsers
201                 var whichKey = evt.which;
202         }
203         if (whichKey == 46) {                           // DELETE key
204                 CtdlDeleteSelectedMessages(evt);
205         }
206         return true;
207 }
208
209 // Take the boldface away from a message to indicate that it has been seen.
210 function CtdlRemoveTheUnseenBold(msgnum) {
211         $('m'+msgnum).style.fontWeight='normal';
212 }
213
214 // A message has been deleted, so yank it from the list.
215 // (IE barfs on m9999.innerHTML='' so we use a script.aculo.us effect instead.)
216 function CtdlClearDeletedMsg(msgnum) {
217         new Effect.Squish('m'+msgnum);
218 }
219
220
221 // These functions called when the user down-clicks on the message list resizer bar
222
223 var saved_x = 0;
224 var saved_y = 0;
225
226 function CtdlResizeMsgListMouseUp(evt) {
227         document.onmouseup = null;
228         document.onmousemove = null;
229         if (document.layers) {
230                 document.releaseEvents(Event.MOUSEUP | Event.MOUSEMOVE);
231         }
232         return true;
233 }
234
235 function CtdlResizeMsgListMouseMove(evt) {
236         y = (ns6 ? evt.clientY : event.clientY);
237         increment = y - saved_y;
238
239         // First move the bottom of the message list...
240         d = $('message_list');
241         if (d.offsetHeight){
242                 divHeight = d.offsetHeight;
243         }
244         else if (d.style.pixelHeight) {
245                 divHeight = d.style.pixelHeight;
246         }
247         d.style.height = (divHeight + increment) + 'px';
248
249         // Then move the top of the preview pane...
250         d = $('preview_pane');
251         if (d.offsetTop){
252                 divTop = d.offsetTop;
253         }
254         else if (d.style.pixelTop) {
255                 divTop = d.style.pixelTop;
256         }
257         d.style.top = (divTop + increment) + 'px';
258
259         // Resize the bottom of the preview pane...
260         d = $('preview_pane');
261         if (d.offsetHeight){
262                 divHeight = d.offsetHeight;
263         }
264         else if (d.style.pixelHeight) {
265                 divHeight = d.style.pixelHeight;
266         }
267         d.style.height = (divHeight - increment) + 'px';
268
269         // Then move the top of the slider bar.
270         d = $('resize_msglist');
271         if (d.offsetTop){
272                 divTop = d.offsetTop;
273         }
274         else if (d.style.pixelTop) {
275                 divTop = d.style.pixelTop;
276         }
277         d.style.top = (divTop + increment) + 'px';
278
279         saved_y = y;
280         return true;
281 }
282
283 function CtdlResizeMsgListMouseDown(evt) {
284         saved_y = (ns6 ? evt.clientY : event.clientY);
285         document.onmouseup = CtdlResizeMsgListMouseUp;
286         document.onmousemove = CtdlResizeMsgListMouseMove;
287         if (document.layers) {
288                 document.captureEvents(Event.MOUSEUP | Event.MOUSEMOVE);
289         }
290         return false;           // disable the default action
291 }
292
293
294
295 // These functions handle drag and drop message moving
296
297 var mm_div = null;
298
299 function CtdlMoveMsgMouseDown(evt, msgnum) {
300
301         // do the highlight first
302         CtdlSingleClickMsg(evt, msgnum);
303
304         // Now handle the possibility of dragging
305         saved_x = (ns6 ? evt.clientX : event.clientX);
306         saved_y = (ns6 ? evt.clientY : event.clientY);
307         document.onmouseup = CtdlMoveMsgMouseUp;
308         document.onmousemove = CtdlMoveMsgMouseMove;
309         if (document.layers) {
310                 document.captureEvents(Event.MOUSEUP | Event.MOUSEMOVE);
311         }
312
313         return false;
314 }
315
316 function CtdlMoveMsgMouseMove(evt) {
317         x = (ns6 ? evt.clientX : event.clientX);
318         y = (ns6 ? evt.clientY : event.clientY);
319
320         if ( (x == saved_x) && (y == saved_y) ) {
321                 return true;
322         }
323
324         if (CtdlNumMsgsSelected < 1) { 
325                 return true;
326         }
327
328         if (!mm_div) {
329
330
331                 drag_o_text = "<div style=\"overflow:none; background-color:#fff; color:#000; border: 1px solid black; filter:alpha(opacity=75); -moz-opacity:.75; opacity:.75;\"><tr><td>";
332                 for (i=0; i<CtdlNumMsgsSelected; ++i) {
333                         drag_o_text = drag_o_text + 
334                                 ctdl_ts_getInnerText(
335                                         $('m'+CtdlMsgsSelected[i]).cells[0]
336                                 ) + '<br>';
337                 }
338                 drag_o_text = drag_o_text + "<div>";
339
340                 mm_div = document.createElement("DIV");
341                 mm_div.style.position='absolute';
342                 mm_div.style.top = y + 'px';
343                 mm_div.style.left = x + 'px';
344                 mm_div.style.pixelHeight = '300';
345                 mm_div.style.pixelWidth = '300';
346                 mm_div.innerHTML = drag_o_text;
347                 document.body.appendChild(mm_div);
348         }
349         else {
350                 mm_div.style.top = y + 'px';
351                 mm_div.style.left = x + 'px';
352         }
353
354         return false;   // prevent the default mouse action from happening?
355 }
356
357 function CtdlMoveMsgMouseUp(evt) {
358         document.onmouseup = null;
359         document.onmousemove = null;
360         if (document.layers) {
361                 document.releaseEvents(Event.MOUSEUP | Event.MOUSEMOVE);
362         }
363
364         if (mm_div) {
365                 document.body.removeChild(mm_div);      
366                 mm_div = null;
367         }
368
369         if (num_drop_targets < 1) {     // nowhere to drop
370                 return true;
371         }
372
373         // Did we release the mouse button while hovering over a drop target?
374         // NOTE: this only works cross-browser because the iconbar div is always
375         //      positioned at 0,0.  Browsers differ in whether the 'offset'
376         //      functions return pos relative to the document or parent.
377
378         for (i=0; i<num_drop_targets; ++i) {
379
380                 x = (ns6 ? evt.clientX : event.clientX);
381                 y = (ns6 ? evt.clientY : event.clientY);
382
383                 l = parseInt(drop_targets_elements[i].offsetLeft);
384                 t = parseInt(drop_targets_elements[i].offsetTop);
385                 r = parseInt(drop_targets_elements[i].offsetLeft)
386                   + parseInt(drop_targets_elements[i].offsetWidth);
387                 b = parseInt(drop_targets_elements[i].offsetTop)
388                   + parseInt(drop_targets_elements[i].offsetHeight);
389
390                 /* alert('Offsets are: ' + l + ' ' + t + ' ' + r + ' ' + b + '.'); */
391         
392                 if ( (x >= l) && (x <= r) && (y >= t) && (y <= b) ) {
393                         // Yes, we dropped it on a hotspot.
394                         CtdlMoveSelectedMessages(evt, drop_targets_roomnames[i]);
395                         return true;
396                 }
397         }
398
399         return true;
400 }
401
402
403 function ctdl_ts_getInnerText(el) {
404         if (typeof el == "string") return el;
405         if (typeof el == "undefined") { return el };
406         if (el.innerText) return el.innerText;  //Not needed but it is faster
407         var str = "";
408         
409         var cs = el.childNodes;
410         var l = cs.length;
411         for (var i = 0; i < l; i++) {
412                 switch (cs[i].nodeType) {
413                         case 1: //ELEMENT_NODE
414                                 str += ts_getInnerText(cs[i]);
415                                 break;
416                         case 3: //TEXT_NODE
417                                 str += cs[i].nodeValue;
418                                 break;
419                 }
420         }
421         return str;
422 }
423
424