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