alecpl
2011-06-24 5bfa4445d52fc831330600e581656142b30f0ca3
commit | author | age
5f660c 1 /**
e019f2 2  * Roundcube functions for default skin interface
5f660c 3  */
A 4
5 /**
6  * Settings
7  */
8
9 function rcube_init_settings_tabs()
10 {
cc97ea 11   var tab = '#settingstabdefault';
5f660c 12   if (window.rcmail && rcmail.env.action)
cc97ea 13     tab = '#settingstab' + (rcmail.env.action=='preferences' ? 'default' : (rcmail.env.action.indexOf('identity')>0 ? 'identities' : rcmail.env.action.replace(/\./g, '')));
T 14
15   $(tab).addClass('tablink-selected');
8c27d0 16   $(tab + '> a').removeAttr('onclick').click(function() { return false; });
5f660c 17 }
A 18
19 function rcube_show_advanced(visible)
20 {
cc97ea 21   $('tr.advanced').css('display', (visible ? (bw.ie ? 'block' : 'table-row') : 'none'));
5f660c 22 }
A 23
6769ba 24 // Fieldsets-to-tabs converter
A 25 // Warning: don't place "caller" <script> inside page element (id)
26 function rcube_init_tabs(id, current)
27 {
0501b6 28   var content = $('#'+id),
T 29     fs = content.children('fieldset');
7403ab 30
A 31   if (!fs.length)
32     return;
6769ba 33
A 34   current = current ? current : 0;
35
36   // first hide not selected tabs
37   fs.each(function(idx) { if (idx != current) $(this).hide(); });
38
39   // create tabs container
5744bf 40   var tabs = $('<div>').addClass('tabsbar').appendTo(content);
6769ba 41
A 42   // convert fildsets into tabs
43   fs.each(function(idx) {
0501b6 44     var tab, a, elm = $(this), legend = elm.children('legend');
6769ba 45
A 46     // create a tab
47     a   = $('<a>').text(legend.text()).attr('href', '#');
48     tab = $('<span>').attr({'id': 'tab'+idx, 'class': 'tablink'})
361ce6 49         .click(function() { rcube_show_tab(id, idx); return false })
6769ba 50
A 51     // remove legend
52     legend.remove();
53     // style fieldset
54     elm.addClass('tabbed');
55     // style selected tab
56     if (idx == current)
57       tab.addClass('tablink-selected');
58
59     // add the tab to container
60     tab.append(a).appendTo(tabs);
61   });
62 }
63
64 function rcube_show_tab(id, index)
65 {
0501b6 66   var fs = $('#'+id).children('fieldset');
6769ba 67
A 68   fs.each(function(idx) {
69     // Show/hide fieldset (tab content)
70     $(this)[index==idx ? 'show' : 'hide']();
71     // Select/unselect tab
72     $('#tab'+idx).toggleClass('tablink-selected', idx==index);
73   });
74 }
75
5f660c 76 /**
3940ba 77  * Mail UI
5f660c 78  */
A 79
80 function rcube_mail_ui()
81 {
9e5550 82   this.popups = {
A 83     markmenu:       {id:'markmessagemenu'},
e25a35 84     replyallmenu:   {id:'replyallmenu'},
a208a4 85     forwardmenu:    {id:'forwardmenu'},
9e5550 86     searchmenu:     {id:'searchmenu', editable:1},
A 87     messagemenu:    {id:'messagemenu'},
88     listmenu:       {id:'listmenu', editable:1},
89     dragmessagemenu:{id:'dragmessagemenu', sticky:1},
90     groupmenu:      {id:'groupoptionsmenu', above:1},
91     mailboxmenu:    {id:'mailboxoptionsmenu', above:1},
92     composemenu:    {id:'composeoptionsmenu', editable:1},
71f60c 93     // toggle: #1486823, #1486930
0501b6 94     uploadmenu:     {id:'attachment-form', editable:1, above:1, toggle:!bw.ie&&!bw.linux },
T 95     uploadform:     {id:'upload-form', editable:1, toggle:!bw.ie&&!bw.linux }
a61bbb 96   };
3940ba 97
a61bbb 98   var obj;
9e5550 99   for (var k in this.popups) {
A 100     obj = $('#'+this.popups[k].id)
a61bbb 101     if (obj.length)
9e5550 102       this.popups[k].obj = obj;
A 103     else {
104       delete this.popups[k];
105     }
a61bbb 106   }
5f660c 107 }
A 108
109 rcube_mail_ui.prototype = {
110
9e5550 111 show_popup: function(popup, show)
5f660c 112 {
9e5550 113   if (typeof this[popup] == 'function')
A 114     return this[popup](show);
115   else
116     return this.show_popupmenu(popup, show);
117 },
118
119 show_popupmenu: function(popup, show)
120 {
121   var obj = this.popups[popup].obj,
122     above = this.popups[popup].above,
123     ref = rcube_find_object(popup+'link');
124
5f660c 125   if (typeof show == 'undefined')
a61bbb 126     show = obj.is(':visible') ? false : true;
0e2ccb 127   else if (this.popups[popup].toggle && show && this.popups[popup].obj.is(':visible') )
T 128     show = false;
6c9d49 129
a61bbb 130   if (show && ref) {
8431a7 131     var parent = $(ref).parent(),
26e76d 132       win = $(window),
8431a7 133       pos = parent.hasClass('dropbutton') ? parent.offset() : $(ref).offset();
A 134
26e76d 135     if (!above && pos.top + ref.offsetHeight + obj.height() > win.height())
b218aa 136       above = true;
26e76d 137     if (pos.left + obj.width() > win.width())
T 138       pos.left = win.width() - obj.width() - 30;
8431a7 139
a61bbb 140     obj.css({ left:pos.left, top:(pos.top + (above ? -obj.height() : ref.offsetHeight)) });
T 141   }
3940ba 142
a61bbb 143   obj[show?'show':'hide']();
T 144 },
145
9e5550 146 dragmessagemenu: function(show)
a61bbb 147 {
9e5550 148   this.popups.dragmessagemenu.obj[show?'show':'hide']();
511420 149 },
A 150
a509bb 151 forwardmenu: function(show)
A 152 {
153   $("input[name='forwardtype'][value="+(rcmail.env.forward_attachment ? 1 : 0)+"]", this.popups.forwardmenu.obj)
154     .prop('checked', true);
155   this.show_popupmenu('forwardmenu', show);
156 },
157
9e5550 158 uploadmenu: function(show)
087c7d 159 {
A 160   if (typeof show == 'object') // called as event handler
161     show = false;
64fa95 162
T 163   // clear upload form
164   if (!show) {
165     try { $('#attachment-form form')[0].reset(); }
166     catch(e){}  // ignore errors
167   }
b218aa 168
9e5550 169   this.show_popupmenu('uploadmenu', show);
b218aa 170
9a4fd7 171   if (!document.all && this.popups.uploadmenu.obj.is(':visible'))
b218aa 172     $('#attachment-form input[type=file]').click();
5f660c 173 },
A 174
9e5550 175 searchmenu: function(show)
30b152 176 {
9e5550 177   var obj = this.popups.searchmenu.obj,
A 178     ref = rcube_find_object('searchmenulink');
30b152 179
9e5550 180   if (typeof show == 'undefined')
A 181     show = obj.is(':visible') ? false : true;
182
30b152 183   if (show && ref) {
A 184     var pos = $(ref).offset();
9e5550 185     obj.css({ left:pos.left, top:(pos.top + ref.offsetHeight + 2)})
491133 186         .find(':checked').prop('checked', false);
30b152 187
A 188     if (rcmail.env.search_mods) {
3cacf9 189       var n, mbox = rcmail.env.mailbox, mods = rcmail.env.search_mods;
A 190
191       if (rcmail.env.task != 'addressbook') {
192         mods = mods[mbox] ? mods[mbox] : mods['*'];
193
194         for (n in mods)
195           $('#s_mod_' + n).prop('checked', true);
196       }
197       else {
198         if (mods['*'])
199           $('input:checkbox[name="s_mods[]"]').map(function() {
200             this.checked = true;
201             this.disabled = this.value != '*';
202           });
203         else {
204           for (n in mods)
205             $('#s_mod_' + n).prop('checked', true);
206         }
207       }
30b152 208     }
A 209   }
9e5550 210   obj[show?'show':'hide']();
30b152 211 },
3940ba 212
30b152 213 set_searchmod: function(elem)
A 214 {
3cacf9 215   var task = rcmail.env.task,
A 216     mods = rcmail.env.search_mods,
217     mbox = rcmail.env.mailbox;
3940ba 218
3cacf9 219   if (!mods)
A 220     mods = {};
3940ba 221
3cacf9 222   if (task == 'mail') {
A 223     if (!mods[mbox])
224       mods[mbox] = rcube_clone_object(mods['*']);
225     if (!elem.checked)
226       delete(mods[mbox][elem.value]);
227     else
228       mods[mbox][elem.value] = 1;
229   }
230   else { //addressbook
231     if (!elem.checked)
232       delete(mods[elem.value]);
233     else
234       mods[elem.value] = 1;
235
236     // mark all fields
237     if (elem.value == '*') {
238       $('input:checkbox[name="s_mods[]"]').map(function() {
239         if (this == elem)
240           return;
241
242         if (elem.checked) {
243           mods[this.value] = 1;
244           this.checked = true;
245           this.disabled = true;
246         }
247         else {
248           this.disabled = false;
249         }
250       });
251     }
252   }
253
254   rcmail.env.search_mods = mods;
30b152 255 },
A 256
9e5550 257 listmenu: function(show)
f52c93 258 {
9e5550 259   var obj = this.popups.listmenu.obj,
A 260     ref = rcube_find_object('listmenulink');
f52c93 261
9e5550 262   if (typeof show == 'undefined')
A 263     show = obj.is(':visible') ? false : true;
264
f52c93 265   if (show && ref) {
6c9d49 266     var pos = $(ref).offset(),
9e5550 267       menuwidth = obj.width(),
6c9d49 268       pagewidth = $(document).width();
A 269
270     if (pagewidth - pos.left < menuwidth && pos.left > menuwidth)
271       pos.left = pos.left - menuwidth;
272
9e5550 273     obj.css({ left:pos.left, top:(pos.top + ref.offsetHeight + 2)});
f52c93 274     // set form values
491133 275     $('input[name="sort_col"][value="'+rcmail.env.sort_col+'"]').prop('checked', true);
A 276     $('input[name="sort_ord"][value="DESC"]').prop('checked', rcmail.env.sort_order == 'DESC');
277     $('input[name="sort_ord"][value="ASC"]').prop('checked', rcmail.env.sort_order != 'DESC');
278     $('input[name="view"][value="thread"]').prop('checked', rcmail.env.threading ? true : false);
279     $('input[name="view"][value="list"]').prop('checked', rcmail.env.threading ? false : true);
f52c93 280     // list columns
491133 281     var found, cols = $('input[name="list_col[]"]');
f52c93 282     for (var i=0; i<cols.length; i++) {
T 283       if (cols[i].value != 'from')
284         found = jQuery.inArray(cols[i].value, rcmail.env.coltypes) != -1;
285       else
286         found = (jQuery.inArray('from', rcmail.env.coltypes) != -1
491133 287             || jQuery.inArray('to', rcmail.env.coltypes) != -1);
A 288       $(cols[i]).prop('checked', found);
f52c93 289     }
T 290   }
291
9e5550 292   obj[show?'show':'hide']();
f52c93 293
T 294   if (show) {
295     var maxheight=0;
296     $('#listmenu fieldset').each(function() {
297       var height = $(this).height();
298       if (height > maxheight) {
299         maxheight = height;
300       }
301     });
302     $('#listmenu fieldset').css("min-height", maxheight+"px")
303     // IE6 complains if you set this attribute using either method:
304     //$('#listmenu fieldset').css({'height':'auto !important'});
305     //$('#listmenu fieldset').css("height","auto !important");
306       .height(maxheight);
307   };
308 },
309
310 open_listmenu: function(e)
311 {
9e5550 312   this.listmenu();
f52c93 313 },
T 314
315 save_listmenu: function()
316 {
9e5550 317   this.listmenu();
f52c93 318
a80405 319   var sort = $('input[name="sort_col"]:checked').val(),
A 320     ord = $('input[name="sort_ord"]:checked').val(),
321     thread = $('input[name="view"]:checked').val(),
322     cols = $('input[name="list_col[]"]:checked')
323       .map(function(){ return this.value; }).get();
f52c93 324
T 325   rcmail.set_list_options(cols, sort, ord, thread == 'thread' ? 1 : 0);
326 },
327
ec581c 328 body_mouseup: function(evt, p)
5f660c 329 {
9e5550 330   var i, target = rcube_event.get_target(evt);
f52c93 331
9e5550 332   for (i in this.popups) {
A 333     if (this.popups[i].obj.is(':visible') && target != rcube_find_object(i+'link')
0e2ccb 334       && !this.popups[i].toggle
9e5550 335       && (!this.popups[i].editable || !this.target_overlaps(target, this.popups[i].id))
A 336       && (!this.popups[i].sticky || !rcube_mouse_is_over(evt, rcube_find_object(this.popups[i].id)))
337     ) {
c7f7ce 338       window.setTimeout('$("#'+this.popups[i].id+'").hide()', 50);
9e5550 339     }
30b152 340   }
087c7d 341 },
A 342
343 target_overlaps: function (target, elementid)
344 {
345   var element = rcube_find_object(elementid);
346   while (target.parentNode) {
347     if (target.parentNode == element)
348       return true;
349     target = target.parentNode;
350   }
351   return false;
5f660c 352 },
A 353
0a36c3 354 body_keydown: function(evt, p)
5f660c 355 {
30b152 356   if (rcube_event.get_keycode(evt) == 27) {
9e5550 357     for (var k in this.popups) {
A 358       if (this.popups[k].obj.is(':visible'))
359         this.show_popup(k, false);
a61bbb 360     }
30b152 361   }
ce06d3 362 },
A 363
364 switch_preview_pane: function(elem)
365 {
366   var uid, prev_frm = $('#mailpreviewframe');
367
368   if (elem.checked) {
369     rcmail.env.contentframe = 'messagecontframe';
370     if (mailviewsplit.layer) {
371       mailviewsplit.resize();
372       mailviewsplit.layer.elm.style.display = '';
129997 373     }
A 374     else
ce06d3 375       mailviewsplit.init();
129997 376
A 377     if (bw.opera) {
378       $('#messagelistcontainer').css({height: ''});
379     }
ce06d3 380     prev_frm.show();
129997 381
ce06d3 382     if (uid = rcmail.message_list.get_single_selection())
A 383       rcmail.show_message(uid, false, true);
129997 384   }
A 385   else {
ce06d3 386     prev_frm.hide();
A 387     if (bw.ie6 || bw.ie7) {
388       var fr = document.getElementById('mailcontframe');
389       fr.style.bottom = 0;
129997 390       fr.style.height = parseInt(fr.parentNode.offsetHeight)+'px';
ce06d3 391     }
129997 392     else {
ce06d3 393       $('#mailcontframe').css({height: 'auto', bottom: 0});
129997 394       if (bw.opera)
A 395         $('#messagelistcontainer').css({height: 'auto'});
396     }
ce06d3 397     if (mailviewsplit.layer)
A 398       mailviewsplit.layer.elm.style.display = 'none';
129997 399
ce06d3 400     rcmail.env.contentframe = null;
A 401     rcmail.show_contentframe(false);
402   }
9b6c82 403
A 404   rcmail.command('save-pref', {name: 'preview_pane', value: (elem.checked?1:0)});
3940ba 405 },
A 406
407 /* Message composing */
408 init_compose_form: function()
409 {
3ee5a7 410   var f, field, fields = ['cc', 'bcc', 'replyto', 'followupto'],
3940ba 411     div = document.getElementById('compose-div'),
A 412     headers_div = document.getElementById('compose-headers-div');
413
e25a35 414   // Show input elements with non-empty value
A 415   for (f=0; f<fields.length; f++) {
416     if ((field = $('#_'+fields[f])) && field.length && field.val() != '')
417       rcmail_ui.show_header_form(fields[f]);
418   }
3940ba 419
A 420   // prevent from form data loss when pressing ESC key in IE
421   if (bw.ie) {
422     var form = rcube_find_object('form');
423     form.onkeydown = function (e) {
424       if (rcube_event.get_keycode(e) == 27)
425         rcube_event.cancel(e);
426     };
427   }
428
429   $(window).resize(function() {
430     rcmail_ui.resize_compose_body();
431   });
432
433   $('#compose-container').resize(function() {
434     rcmail_ui.resize_compose_body();
435   });
436
b218aa 437   div.style.top = (parseInt(headers_div.offsetHeight, 10) + 3) + 'px';
3940ba 438   $(window).resize();
A 439 },
440
441 resize_compose_body: function()
442 {
b218aa 443   var div = $('#compose-div .boxlistcontent'), w = div.width(), h = div.height();
T 444   w -= 8;  // 2 x 3px padding + 2 x 1px border
445   h -= 4;
3940ba 446
b218aa 447   $('#compose-body').width(w+'px').height(h+'px');
3940ba 448
A 449   if (window.tinyMCE && tinyMCE.get('compose-body')) {
b218aa 450     $('#compose-body_tbl').width((w+6)+'px').height('');
T 451     $('#compose-body_ifr').width((w+6)+'px').height((h-54)+'px');
3940ba 452   }
b8d4fe 453   else {
9bfcb3 454     $('#googie_edit_layer').height(h+'px');
b8d4fe 455   }
7534f6 456 },
A 457
458 resize_compose_body_ev: function()
459 {
460   window.setTimeout(function(){rcmail_ui.resize_compose_body();}, 100);
3940ba 461 },
A 462
463 show_header_form: function(id)
464 {
465   var row, s,
466     link = document.getElementById(id + '-link');
467
468   if ((s = this.next_sibling(link)))
469     s.style.display = 'none';
470   else if ((s = this.prev_sibling(link)))
471     s.style.display = 'none';
472
473   link.style.display = 'none';
474
475   if ((row = document.getElementById('compose-' + id))) {
476     var div = document.getElementById('compose-div'),
477       headers_div = document.getElementById('compose-headers-div');
478     row.style.display = (document.all && !window.opera) ? 'block' : 'table-row';
b218aa 479     div.style.top = (parseInt(headers_div.offsetHeight, 10) + 3) + 'px';
3940ba 480     this.resize_compose_body();
A 481   }
482
483   return false;
484 },
485
486 hide_header_form: function(id)
487 {
488   var row, ns,
489     link = document.getElementById(id + '-link'),
490     parent = link.parentNode,
491     links = parent.getElementsByTagName('a');
492
493   link.style.display = '';
494
495   for (var i=0; i<links.length; i++)
496     if (links[i].style.display != 'none')
497       for (var j=i+1; j<links.length; j++)
498         if (links[j].style.display != 'none')
499           if ((ns = this.next_sibling(links[i]))) {
500             ns.style.display = '';
501             break;
502           }
503
504   document.getElementById('_' + id).value = '';
505
506   if ((row = document.getElementById('compose-' + id))) {
507     var div = document.getElementById('compose-div'),
508       headers_div = document.getElementById('compose-headers-div');
509     row.style.display = 'none';
510     div.style.top = (parseInt(headers_div.offsetHeight, 10) + 1) + 'px';
511     this.resize_compose_body();
512   }
513
514   return false;
515 },
516
517 next_sibling: function(elm)
518 {
519   var ns = elm.nextSibling;
520   while (ns && ns.nodeType == 3)
521     ns = ns.nextSibling;
522   return ns;
523 },
524
525 prev_sibling: function(elm)
526 {
527   var ps = elm.previousSibling;
528   while (ps && ps.nodeType == 3)
529     ps = ps.previousSibling;
530   return ps;
5f660c 531 }
A 532
533 };
3940ba 534
5f660c 535
59ed6f 536 var rcmail_ui;
5f660c 537
A 538 function rcube_init_mail_ui()
539 {
540   rcmail_ui = new rcube_mail_ui();
ec581c 541   rcube_event.add_listener({ object:rcmail_ui, method:'body_mouseup', event:'mouseup' });
0a36c3 542   rcube_event.add_listener({ object:rcmail_ui, method:'body_keydown', event:'keydown' });
e2b0a0 543
A 544   $('iframe').load(iframe_events)
ec581c 545     .contents().mouseup(function(e){rcmail_ui.body_mouseup(e)});
e2b0a0 546
a61bbb 547   if (rcmail.env.task == 'mail') {
T 548     rcmail.addEventListener('menu-open', 'open_listmenu', rcmail_ui);
549     rcmail.addEventListener('menu-save', 'save_listmenu', rcmail_ui);
9e5550 550     rcmail.addEventListener('aftersend-attachment', 'uploadmenu', rcmail_ui);
7534f6 551     rcmail.addEventListener('aftertoggle-editor', 'resize_compose_body_ev', rcmail_ui);
a61bbb 552     rcmail.gui_object('message_dragmenu', 'dragmessagemenu');
3940ba 553
9e1daa 554     if (rcmail.gui_objects.mailboxlist) {
T 555       rcmail.addEventListener('responseaftermark', rcube_render_mailboxlist);
556       rcmail.addEventListener('responseaftergetunread', rcube_render_mailboxlist);
557       rcmail.addEventListener('responseaftercheck-recent', rcube_render_mailboxlist);
558       rcmail.addEventListener('aftercollapse-folder', rcube_render_mailboxlist);
559       rcube_render_mailboxlist();
560     }
561
3940ba 562     if (rcmail.env.action == 'compose')
A 563       rcmail_ui.init_compose_form();
a61bbb 564   }
0501b6 565   else if (rcmail.env.task == 'addressbook') {
T 566     rcmail.addEventListener('afterupload-photo', function(){ rcmail_ui.show_popup('uploadform', false); });
567   }
5f660c 568 }
e2b0a0 569
A 570 // Events handling in iframes (eg. preview pane)
571 function iframe_events()
572 {
573   // this==iframe
574   var doc = this.contentDocument ? this.contentDocument : this.contentWindow ? this.contentWindow.document : null;
ec581c 575   rcube_event.add_listener({ element: doc, object:rcmail_ui, method:'body_mouseup', event:'mouseup' });
e2b0a0 576 }
A 577
9e1daa 578 // Abbreviate mailbox names to fit width of the container
T 579 function rcube_render_mailboxlist()
580 {
581   if (bw.ie6)  // doesn't work well on IE6
582     return;
583
584   $('#mailboxlist > li a, #mailboxlist ul:visible > li a').each(function(){
585     var elem = $(this);
586     var text = elem.data('text');
587     if (!text) {
588       text = elem.text().replace(/\s+\(.+$/, '');
589       elem.data('text', text);
590     }
591     if (text.length < 6)
592       return;
593
594     var abbrev = fit_string_to_size(text, elem, elem.width() - elem.children('span.unreadcount').width());
595     if (abbrev != text)
596       elem.attr('title', text);
597     elem.contents().filter(function(){ return (this.nodeType == 3); }).get(0).data = abbrev;
598   });
599 }
600
601 // inspired by https://gist.github.com/24261/7fdb113f1e26111bd78c0c6fe515f6c0bf418af5
602 function fit_string_to_size(str, elem, len)
603 {
604     var result = str;
605     var ellip = '...';
606     var span = $('<b>').css({ visibility:'hidden', padding:'0px' }).appendTo(elem).get(0);
607
608     // on first run, check if string fits into the length already.
609     span.innerHTML = result;
610     if (span.offsetWidth > len) {
611         var cut = Math.max(1, Math.floor(str.length * ((span.offsetWidth - len) / span.offsetWidth) / 2)),
612           mid = Math.floor(str.length / 2);
613         var offLeft = mid, offRight = mid;
614         while (true) {
615             offLeft = mid - cut;
616             offRight = mid + cut;
617             span.innerHTML = str.substring(0,offLeft) + ellip + str.substring(offRight);
618
619             // break loop if string fits size
620             if (span.offsetWidth <= len || offLeft < 3)
621               break;
622
623             cut++;
624         }
625
626         // build resulting string
627         result = str.substring(0,offLeft) + ellip + str.substring(offRight);
628     }
629     
630     span.parentNode.removeChild(span);
631     return result;
632 }
90550b 633
V 634 // Optional parameters used by TinyMCE
635 var rcmail_editor_settings = {
636   skin : "default", // "default", "o2k7"
637   skin_variant : "" // "", "silver", "black"
638 };