Aleksander Machniak
2016-02-05 bd0551b22076b82a6d49e9f7a2b2e0c90a1b2326
commit | author | age
b34d67 1 /**
TB 2  * (Manage)Sieve Filters plugin
3  *
4  * @licstart  The following is the entire license notice for the
5  * JavaScript code in this file.
6  *
7  * Copyright (c) 2012-2014, The Roundcube Dev Team
8  *
9  * The JavaScript code in this page is free software: you can redistribute it
10  * and/or modify it under the terms of the GNU General Public License
11  * as published by the Free Software Foundation, either version 3 of
12  * the License, or (at your option) any later version.
13  *
14  * @licend  The above is the entire license notice
15  * for the JavaScript code in this file.
16  */
48e9c1 17
T 18 if (window.rcmail) {
19   rcmail.addEventListener('init', function(evt) {
20     // add managesieve-create command to message_commands array,
21     // so it's state will be updated on message selection/unselection
22     if (rcmail.env.task == 'mail') {
23       if (rcmail.env.action != 'show')
24         rcmail.env.message_commands.push('managesieve-create');
25       else
26         rcmail.enable_command('managesieve-create', true);
27     }
28
27f0c2 29     if (rcmail.env.task == 'mail' || rcmail.env.action.startsWith('plugin.managesieve')) {
48e9c1 30       // Create layer for form tips
T 31       if (!rcmail.env.framed) {
32         rcmail.env.ms_tip_layer = $('<div id="managesieve-tip" class="popupmenu"></div>');
33         rcmail.env.ms_tip_layer.appendTo(document.body);
34       }
35     }
36
37     // register commands
38     rcmail.register_command('plugin.managesieve-save', function() { rcmail.managesieve_save() });
39     rcmail.register_command('plugin.managesieve-act', function() { rcmail.managesieve_act() });
40     rcmail.register_command('plugin.managesieve-add', function() { rcmail.managesieve_add() });
41     rcmail.register_command('plugin.managesieve-del', function() { rcmail.managesieve_del() });
42     rcmail.register_command('plugin.managesieve-move', function() { rcmail.managesieve_move() });
43     rcmail.register_command('plugin.managesieve-setadd', function() { rcmail.managesieve_setadd() });
44     rcmail.register_command('plugin.managesieve-setdel', function() { rcmail.managesieve_setdel() });
45     rcmail.register_command('plugin.managesieve-setact', function() { rcmail.managesieve_setact() });
46     rcmail.register_command('plugin.managesieve-setget', function() { rcmail.managesieve_setget() });
47
27f0c2 48     if (rcmail.env.action.startsWith('plugin.managesieve')) {
48e9c1 49       if (rcmail.gui_objects.sieveform) {
T 50         rcmail.enable_command('plugin.managesieve-save', true);
581b6b 51         sieve_form_init();
48e9c1 52       }
T 53       else {
54         rcmail.enable_command('plugin.managesieve-add', 'plugin.managesieve-setadd', !rcmail.env.sieveconnerror);
55       }
56
13b33d 57       var setcnt, set = rcmail.env.currentset;
48e9c1 58
T 59       if (rcmail.gui_objects.filterslist) {
60         rcmail.filters_list = new rcube_list_widget(rcmail.gui_objects.filterslist,
13b33d 61           {multiselect:false, draggable:true, keyboard:true});
a2e09c 62
AM 63         rcmail.filters_list
13b33d 64           .addEventListener('select', function(e) { rcmail.managesieve_select(e); })
AM 65           .addEventListener('dragstart', function(e) { rcmail.managesieve_dragstart(e); })
66           .addEventListener('dragend', function(e) { rcmail.managesieve_dragend(e); })
a2e09c 67           .addEventListener('initrow', function(row) {
13b33d 68             row.obj.onmouseover = function() { rcmail.managesieve_focus_filter(row); };
AM 69             row.obj.onmouseout = function() { rcmail.managesieve_unfocus_filter(row); };
a2e09c 70           })
13b33d 71           .init();
48e9c1 72       }
T 73
74       if (rcmail.gui_objects.filtersetslist) {
a2e09c 75         rcmail.filtersets_list = new rcube_list_widget(rcmail.gui_objects.filtersetslist,
13b33d 76           {multiselect:false, draggable:false, keyboard:true});
a2e09c 77
13b33d 78         rcmail.filtersets_list.init().focus();
48e9c1 79
T 80         if (set != null) {
81           set = rcmail.managesieve_setid(set);
13b33d 82           rcmail.filtersets_list.select(set);
48e9c1 83         }
13b33d 84
AM 85         // attach select event after initial record was selected
86         rcmail.filtersets_list.addEventListener('select', function(e) { rcmail.managesieve_setselect(e); });
48e9c1 87
T 88         setcnt = rcmail.filtersets_list.rowcount;
89         rcmail.enable_command('plugin.managesieve-set', true);
90         rcmail.enable_command('plugin.managesieve-setact', 'plugin.managesieve-setget', setcnt);
91         rcmail.enable_command('plugin.managesieve-setdel', setcnt > 1);
92
93         // Fix dragging filters over sets list
13b33d 94         $('tr', rcmail.gui_objects.filtersetslist).each(function (i, e) { rcmail.managesieve_fixdragend(e); });
48e9c1 95       }
T 96     }
13b33d 97
48e9c1 98     if (rcmail.gui_objects.sieveform && rcmail.env.rule_disabled)
T 99       $('#disabled').attr('checked', true);
100   });
101 };
102
103 /*********************************************************/
104 /*********       Managesieve UI methods          *********/
105 /*********************************************************/
106
107 rcube_webmail.prototype.managesieve_add = function()
108 {
109   this.load_managesieveframe();
110   this.filters_list.clear_selection();
111 };
112
113 rcube_webmail.prototype.managesieve_del = function()
114 {
115   var id = this.filters_list.get_single_selection();
116   if (confirm(this.get_label('managesieve.filterdeleteconfirm'))) {
117     var lock = this.set_busy(true, 'loading');
27f0c2 118     this.http_post('plugin.managesieve-action',
48e9c1 119       '_act=delete&_fid='+this.filters_list.rows[id].uid, lock);
T 120   }
121 };
122
123 rcube_webmail.prototype.managesieve_act = function()
124 {
125   var id = this.filters_list.get_single_selection(),
126     lock = this.set_busy(true, 'loading');
127
27f0c2 128   this.http_post('plugin.managesieve-action',
48e9c1 129     '_act=act&_fid='+this.filters_list.rows[id].uid, lock);
T 130 };
131
132 // Filter selection
133 rcube_webmail.prototype.managesieve_select = function(list)
134 {
135   var id = list.get_single_selection();
136   if (id != null)
137     this.load_managesieveframe(list.rows[id].uid);
138 };
139
140 // Set selection
141 rcube_webmail.prototype.managesieve_setselect = function(list)
142 {
143   this.show_contentframe(false);
144   this.filters_list.clear(true);
145   this.enable_command('plugin.managesieve-setdel', list.rowcount > 1);
27f0c2 146   this.enable_command('plugin.managesieve-setact', 'plugin.managesieve-setget', true);
48e9c1 147
T 148   var id = list.get_single_selection();
149   if (id != null)
150     this.managesieve_list(this.env.filtersets[id]);
151 };
152
153 rcube_webmail.prototype.managesieve_rowid = function(id)
154 {
155   var i, rows = this.filters_list.rows;
156
78ef00 157   for (i in rows)
48e9c1 158     if (rows[i] != null && rows[i].uid == id)
T 159       return i;
160 };
161
162 // Returns set's identifier
163 rcube_webmail.prototype.managesieve_setid = function(name)
164 {
165   for (var i in this.env.filtersets)
166     if (this.env.filtersets[i] == name)
167       return i;
168 };
169
170 // Filters listing request
171 rcube_webmail.prototype.managesieve_list = function(script)
172 {
173   var lock = this.set_busy(true, 'loading');
174
27f0c2 175   this.http_post('plugin.managesieve-action', '_act=list&_set='+urlencode(script), lock);
48e9c1 176 };
T 177
178 // Script download request
179 rcube_webmail.prototype.managesieve_setget = function()
180 {
181   var id = this.filtersets_list.get_single_selection(),
182     script = this.env.filtersets[id];
183
bd0551 184   this.goto_url('plugin.managesieve-action', {_act: 'setget', _set: script}, false, true);
48e9c1 185 };
T 186
187 // Set activate/deactivate request
188 rcube_webmail.prototype.managesieve_setact = function()
189 {
190   var id = this.filtersets_list.get_single_selection(),
191    lock = this.set_busy(true, 'loading'),
192     script = this.env.filtersets[id],
193     action = $('#rcmrow'+id).hasClass('disabled') ? 'setact' : 'deact';
194
27f0c2 195   this.http_post('plugin.managesieve-action', '_act='+action+'&_set='+urlencode(script), lock);
48e9c1 196 };
T 197
198 // Set delete request
199 rcube_webmail.prototype.managesieve_setdel = function()
200 {
201   if (!confirm(this.get_label('managesieve.setdeleteconfirm')))
202     return false;
203
204   var id = this.filtersets_list.get_single_selection(),
205     lock = this.set_busy(true, 'loading'),
206     script = this.env.filtersets[id];
207
27f0c2 208   this.http_post('plugin.managesieve-action', '_act=setdel&_set='+urlencode(script), lock);
48e9c1 209 };
T 210
211 // Set add request
212 rcube_webmail.prototype.managesieve_setadd = function()
213 {
214   this.filters_list.clear_selection();
215   this.enable_command('plugin.managesieve-act', 'plugin.managesieve-del', false);
216
217   if (this.env.contentframe && window.frames && window.frames[this.env.contentframe]) {
218     var lock = this.set_busy(true, 'loading');
219     target = window.frames[this.env.contentframe];
27f0c2 220     target.location.href = this.env.comm_path+'&_action=plugin.managesieve-action&_framed=1&_newset=1&_unlock='+lock;
48e9c1 221   }
T 222 };
223
224 rcube_webmail.prototype.managesieve_updatelist = function(action, o)
225 {
226   this.set_busy(true);
227
228   switch (action) {
229     // Delete filter row
230     case 'del':
022f51 231       var id = o.id, list = this.filters_list;
48e9c1 232
T 233       list.remove_row(this.managesieve_rowid(o.id));
234       list.clear_selection();
235       this.show_contentframe(false);
236       this.enable_command('plugin.managesieve-del', 'plugin.managesieve-act', false);
237
da7905 238       // filter identifiers changed, fix the list
AM 239       $('tr', this.filters_list.list).each(function() {
240         // remove hidden (deleted) rows
241         if (this.style.display == 'none') {
242           $(this).detach();
243           return;
244         }
245
022f51 246         var rowid = this.id.substr(6);
AM 247
248         // remove all attached events
d9ff47 249         $(this).off();
022f51 250
AM 251         // update row id
224a1b 252         if (rowid > id) {
AM 253           this.uid = rowid - 1;
254           $(this).attr('id', 'rcmrow' + this.uid);
255         }
da7905 256       });
AM 257       list.init();
48e9c1 258
T 259       break;
260
261     // Update filter row
262     case 'update':
da7905 263       var i, row = $('#rcmrow'+this.managesieve_rowid(o.id));
48e9c1 264
T 265       if (o.name)
d6b592 266         $('td', row).text(o.name);
48e9c1 267       if (o.disabled)
T 268         row.addClass('disabled');
269       else
270         row.removeClass('disabled');
271
272       $('#disabled', $('iframe').contents()).prop('checked', o.disabled);
273
274       break;
275
276     // Add filter row to the list
277     case 'add':
278       var list = this.filters_list,
279         row = $('<tr><td class="name"></td></tr>');
280
d6b592 281       $('td', row).text(o.name);
48e9c1 282       row.attr('id', 'rcmrow'+o.id);
T 283       if (o.disabled)
284         row.addClass('disabled');
285
286       list.insert_row(row.get(0));
287       list.highlight_row(o.id);
288
289       this.enable_command('plugin.managesieve-del', 'plugin.managesieve-act', true);
290
291       break;
292
293     // Filling rules list
294     case 'list':
295       var i, tr, td, el, list = this.filters_list;
296
297       if (o.clear)
298         list.clear();
299
300       for (i in o.list) {
301         el = o.list[i];
302         tr = document.createElement('TR');
303         td = document.createElement('TD');
304
d6b592 305         $(td).text(el.name);
48e9c1 306         td.className = 'name';
T 307         tr.id = 'rcmrow' + el.id;
308         if (el['class'])
309             tr.className = el['class'];
310         tr.appendChild(td);
311
312         list.insert_row(tr);
313       }
314
315       if (o.set)
316         list.highlight_row(o.set);
317       else
318         this.enable_command('plugin.managesieve-del', 'plugin.managesieve-act', false);
319
320       break;
321
322     // Sactivate/deactivate set
323     case 'setact':
324       var id = this.managesieve_setid(o.name), row = $('#rcmrow' + id);
325       if (o.active) {
326         if (o.all)
327           $('tr', this.gui_objects.filtersetslist).addClass('disabled');
328         row.removeClass('disabled');
329       }
330       else
331         row.addClass('disabled');
332
333       break;
334
335     // Delete set row
336     case 'setdel':
337       var id = this.managesieve_setid(o.name);
338
339       this.filtersets_list.remove_row(id);
340       this.filters_list.clear();
341       this.show_contentframe(false);
342       this.enable_command('plugin.managesieve-setdel', 'plugin.managesieve-setact', 'plugin.managesieve-setget', false);
343
344       delete this.env.filtersets[id];
345
346       break;
347
348     // Create set row
349     case 'setadd':
350       var id = 'S' + new Date().getTime(),
351         list = this.filtersets_list,
352         row = $('<tr class="disabled"><td class="name"></td></tr>');
353
d6b592 354       $('td', row).text(o.name);
48e9c1 355       row.attr('id', 'rcmrow'+id);
T 356
357       this.env.filtersets[id] = o.name;
358       list.insert_row(row.get(0));
359
360       // move row into its position on the list
361       if (o.index != list.rowcount-1) {
362         row.detach();
363         var elem = $('tr:visible', list.list).get(o.index);
364         row.insertBefore(elem);
365       }
366
367       list.select(id);
368
369       // Fix dragging filters over sets list
370       this.managesieve_fixdragend(row);
371
372       break;
373   }
374
375   this.set_busy(false);
376 };
377
378 // load filter frame
379 rcube_webmail.prototype.load_managesieveframe = function(id)
380 {
381   var has_id = typeof(id) != 'undefined' && id != null;
382   this.enable_command('plugin.managesieve-act', 'plugin.managesieve-del', has_id);
383
384   if (this.env.contentframe && window.frames && window.frames[this.env.contentframe]) {
385     target = window.frames[this.env.contentframe];
386     var msgid = this.set_busy(true, 'loading');
27f0c2 387     target.location.href = this.env.comm_path+'&_action=plugin.managesieve-action&_framed=1'
a648ba 388       +(has_id ? '&_fid='+id : '')+'&_unlock='+msgid;
48e9c1 389   }
T 390 };
391
392 // load filter frame
393 rcube_webmail.prototype.managesieve_dragstart = function(list)
394 {
395   var id = this.filters_list.get_single_selection();
396
397   this.drag_active = true;
398   this.drag_filter = id;
399 };
400
401 rcube_webmail.prototype.managesieve_dragend = function(e)
402 {
403   if (this.drag_active) {
404     if (this.drag_filter_target) {
405       var lock = this.set_busy(true, 'loading');
406
407       this.show_contentframe(false);
27f0c2 408       this.http_post('plugin.managesieve-action', '_act=move&_fid='+this.drag_filter
48e9c1 409         +'&_to='+this.drag_filter_target, lock);
T 410     }
411     this.drag_active = false;
412   }
413 };
414
415 // Fixes filters dragging over sets list
416 // @TODO: to be removed after implementing copying filters
417 rcube_webmail.prototype.managesieve_fixdragend = function(elem)
418 {
419   var p = this;
d9ff47 420   $(elem).on('mouseup' + ((bw.iphone || bw.ipad) ? ' touchend' : ''), function(e) {
48e9c1 421     if (p.drag_active)
T 422       p.filters_list.drag_mouse_up(e);
423   });
424 };
425
426 rcube_webmail.prototype.managesieve_focus_filter = function(row)
427 {
428   var id = row.id.replace(/^rcmrow/, '');
429   if (this.drag_active && id != this.drag_filter) {
430     this.drag_filter_target = id;
431     $(row.obj).addClass(id < this.drag_filter ? 'filtermoveup' : 'filtermovedown');
432   }
433 };
434
435 rcube_webmail.prototype.managesieve_unfocus_filter = function(row)
436 {
437   if (this.drag_active) {
438     $(row.obj).removeClass('filtermoveup filtermovedown');
439     this.drag_filter_target = null;
440   }
441 };
442
443 /*********************************************************/
444 /*********          Filter Form methods          *********/
445 /*********************************************************/
446
447 // Form submition
448 rcube_webmail.prototype.managesieve_save = function()
449 {
50a57e 450   if (this.env.action == 'plugin.managesieve-vacation') {
AM 451     var data = $(this.gui_objects.sieveform).serialize();
452     this.http_post('plugin.managesieve-vacation', data, this.display_message(this.get_label('managesieve.vacation.saving'), 'loading'));
453     return;
454   }
455
48e9c1 456   if (parent.rcmail && parent.rcmail.filters_list && this.gui_objects.sieveform.name != 'filtersetform') {
T 457     var id = parent.rcmail.filters_list.get_single_selection();
458     if (id != null)
459       this.gui_objects.sieveform.elements['_fid'].value = parent.rcmail.filters_list.rows[id].uid;
460   }
461   this.gui_objects.sieveform.submit();
462 };
463
464 // Operations on filters form
465 rcube_webmail.prototype.managesieve_ruleadd = function(id)
466 {
27f0c2 467   this.http_post('plugin.managesieve-action', '_act=ruleadd&_rid='+id);
48e9c1 468 };
T 469
470 rcube_webmail.prototype.managesieve_rulefill = function(content, id, after)
471 {
472   if (content != '') {
473     // create new element
474     var div = document.getElementById('rules'),
475       row = document.createElement('div');
476
477     this.managesieve_insertrow(div, row, after);
478     // fill row after inserting (for IE)
479     row.setAttribute('id', 'rulerow'+id);
480     row.className = 'rulerow';
481     row.innerHTML = content;
482
c6f075 483     // initialize smart list inputs
AM 484     $('textarea[data-type="list"]', row).each(function() {
485       smart_field_init(this);
486     });
487
48e9c1 488     this.managesieve_formbuttons(div);
T 489   }
490 };
491
492 rcube_webmail.prototype.managesieve_ruledel = function(id)
493 {
494   if ($('#ruledel'+id).hasClass('disabled'))
495     return;
496
497   if (confirm(this.get_label('managesieve.ruledeleteconfirm'))) {
498     var row = document.getElementById('rulerow'+id);
499     row.parentNode.removeChild(row);
500     this.managesieve_formbuttons(document.getElementById('rules'));
501   }
502 };
503
504 rcube_webmail.prototype.managesieve_actionadd = function(id)
505 {
27f0c2 506   this.http_post('plugin.managesieve-action', '_act=actionadd&_aid='+id);
48e9c1 507 };
T 508
509 rcube_webmail.prototype.managesieve_actionfill = function(content, id, after)
510 {
511   if (content != '') {
512     var div = document.getElementById('actions'),
513       row = document.createElement('div');
514
515     this.managesieve_insertrow(div, row, after);
516     // fill row after inserting (for IE)
517     row.className = 'actionrow';
518     row.setAttribute('id', 'actionrow'+id);
519     row.innerHTML = content;
520
9a0900 521     // initialize smart list inputs
AM 522     $('textarea[data-type="list"]', row).each(function() {
523       smart_field_init(this);
524     });
525
48e9c1 526     this.managesieve_formbuttons(div);
T 527   }
528 };
529
530 rcube_webmail.prototype.managesieve_actiondel = function(id)
531 {
532   if ($('#actiondel'+id).hasClass('disabled'))
533     return;
534
535   if (confirm(this.get_label('managesieve.actiondeleteconfirm'))) {
536     var row = document.getElementById('actionrow'+id);
537     row.parentNode.removeChild(row);
538     this.managesieve_formbuttons(document.getElementById('actions'));
539   }
540 };
541
542 // insert rule/action row in specified place on the list
543 rcube_webmail.prototype.managesieve_insertrow = function(div, row, after)
544 {
545   for (var i=0; i<div.childNodes.length; i++) {
546     if (div.childNodes[i].id == (div.id == 'rules' ? 'rulerow' : 'actionrow')  + after)
547       break;
548   }
549
550   if (div.childNodes[i+1])
551     div.insertBefore(row, div.childNodes[i+1]);
552   else
553     div.appendChild(row);
554 };
555
556 // update Delete buttons status
557 rcube_webmail.prototype.managesieve_formbuttons = function(div)
558 {
559   var i, button, buttons = [];
560
561   // count and get buttons
562   for (i=0; i<div.childNodes.length; i++) {
563     if (div.id == 'rules' && div.childNodes[i].id) {
564       if (/rulerow/.test(div.childNodes[i].id))
565         buttons.push('ruledel' + div.childNodes[i].id.replace(/rulerow/, ''));
566     }
567     else if (div.childNodes[i].id) {
568       if (/actionrow/.test(div.childNodes[i].id))
569         buttons.push( 'actiondel' + div.childNodes[i].id.replace(/actionrow/, ''));
570     }
571   }
572
573   for (i=0; i<buttons.length; i++) {
574     button = document.getElementById(buttons[i]);
575     if (i>0 || buttons.length>1) {
576       $(button).removeClass('disabled');
577     }
578     else {
579       $(button).addClass('disabled');
580     }
581   }
582 };
583
9c38c5 584 // update vacation addresses field with user identities
AM 585 rcube_webmail.prototype.managesieve_vacation_addresses = function(id)
586 {
587   var lock = this.set_busy(true, 'loading');
588   this.http_post('plugin.managesieve-action', {_act: 'addresses', _aid: id}, lock);
589 };
590
591 // update vacation addresses field with user identities
592 rcube_webmail.prototype.managesieve_vacation_addresses_update = function(id, addresses)
593 {
594   var field = $('#vacation_addresses,#action_addresses' + (id || ''));
595   smart_field_reset(field.get(0), addresses);
596 };
597
48e9c1 598 function rule_header_select(id)
T 599 {
600   var obj = document.getElementById('header' + id),
601     size = document.getElementById('rule_size' + id),
602     op = document.getElementById('rule_op' + id),
a1679c 603     header = document.getElementById('custom_header' + id + '_list'),
48e9c1 604     mod = document.getElementById('rule_mod' + id),
T 605     trans = document.getElementById('rule_trans' + id),
0185a2 606     comp = document.getElementById('rule_comp' + id),
AM 607     datepart = document.getElementById('rule_date_part' + id),
608     dateheader = document.getElementById('rule_date_header_div' + id),
609     h = obj.value;
48e9c1 610
0185a2 611   if (h == 'size') {
48e9c1 612     size.style.display = 'inline';
0185a2 613     $.each([op, header, mod, trans, comp], function() { this.style.display = 'none'; });
48e9c1 614   }
T 615   else {
0185a2 616     header.style.display = h != '...' ? 'none' : 'inline-block';
48e9c1 617     size.style.display = 'none';
T 618     op.style.display = 'inline';
619     comp.style.display = '';
0185a2 620     mod.style.display = h == 'body' || h == 'currentdate' || h == 'date' ? 'none' : 'block';
AM 621     trans.style.display = h == 'body' ? 'block' : 'none';
48e9c1 622   }
T 623
0185a2 624   if (datepart)
AM 625     datepart.style.display = h == 'currentdate' || h == 'date' ? 'inline' : 'none';
626   if (dateheader)
627     dateheader.style.display = h == 'date' ? '' : 'none';
628
629   rule_op_select(op, id, h);
630   rule_mod_select(id, h);
631   obj.style.width = h == '...' ? '40px' : '';
48e9c1 632 };
T 633
c6f075 634 function rule_op_select(obj, id, header)
48e9c1 635 {
5c6e74 636   var target = document.getElementById('rule_target' + id + '_list');
48e9c1 637
5c6e74 638   if (!header)
AM 639     header = document.getElementById('header' + id).value;
640
641   target.style.display = obj.value == 'exists' || obj.value == 'notexists' || header == 'size' ? 'none' : 'inline-block';
48e9c1 642 };
T 643
644 function rule_trans_select(id)
645 {
646   var obj = document.getElementById('rule_trans_op' + id),
647     target = document.getElementById('rule_trans_type' + id);
648
649   target.style.display = obj.value != 'content' ? 'none' : 'inline';
650 };
651
0185a2 652 function rule_mod_select(id, header)
48e9c1 653 {
T 654   var obj = document.getElementById('rule_mod_op' + id),
0185a2 655     target = document.getElementById('rule_mod_type' + id),
AM 656     index = document.getElementById('rule_index_div' + id);
657
658   if (!header)
659     header = document.getElementById('header' + id).value;
48e9c1 660
T 661   target.style.display = obj.value != 'address' && obj.value != 'envelope' ? 'none' : 'inline';
0185a2 662
AM 663   if (index)
664     index.style.display = header != 'body' && header != 'currentdate' && header != 'size' && obj.value != 'envelope'  ? '' : 'none';
48e9c1 665 };
T 666
667 function rule_join_radio(value)
668 {
669   $('#rules').css('display', value == 'any' ? 'none' : 'block');
670 };
671
672 function rule_adv_switch(id, elem)
673 {
674   var elem = $(elem), enabled = elem.hasClass('hide'), adv = $('#rule_advanced'+id);
675
676   if (enabled) {
677     adv.hide();
678     elem.removeClass('hide').addClass('show');
679   }
680   else {
681     adv.show();
682     elem.removeClass('show').addClass('hide');
683   }
684 }
685
686 function action_type_select(id)
687 {
688   var obj = document.getElementById('action_type' + id),
f001af 689     v = obj.value, enabled = {},
48e9c1 690     elems = {
T 691       mailbox: document.getElementById('action_mailbox' + id),
0f4806 692       target: document.getElementById('redirect_target' + id),
48e9c1 693       target_area: document.getElementById('action_target_area' + id),
T 694       flags: document.getElementById('action_flags' + id),
ebb204 695       vacation: document.getElementById('action_vacation' + id),
2e7bd6 696       set: document.getElementById('action_set' + id),
PS 697       notify: document.getElementById('action_notify' + id)
48e9c1 698     };
T 699
0185a2 700   if (v == 'fileinto' || v == 'fileinto_copy') {
48e9c1 701     enabled.mailbox = 1;
T 702   }
0185a2 703   else if (v == 'redirect' || v == 'redirect_copy') {
48e9c1 704     enabled.target = 1;
T 705   }
0185a2 706   else if (v.match(/^reject|ereject$/)) {
48e9c1 707     enabled.target_area = 1;
T 708   }
0185a2 709   else if (v.match(/^(add|set|remove)flag$/)) {
48e9c1 710     enabled.flags = 1;
T 711   }
0185a2 712   else if (v == 'vacation') {
48e9c1 713     enabled.vacation = 1;
T 714   }
0185a2 715   else if (v == 'set') {
ebb204 716     enabled.set = 1;
AM 717   }
0185a2 718   else if (v == 'notify') {
2e7bd6 719     enabled.notify = 1;
PS 720   }
48e9c1 721
T 722   for (var x in elems) {
723     elems[x].style.display = !enabled[x] ? 'none' : 'inline';
724   }
725 };
726
c883f6 727 function vacation_action_select()
AM 728 {
729   var selected = $('#vacation_action').val();
730
731   $('#action_target_span')[selected == 'discard' || selected == 'keep' ? 'hide' : 'show']();
732 };
733
c6f075 734 // Inititalizes smart list input
AM 735 function smart_field_init(field)
736 {
737   var id = field.id + '_list',
738     area = $('<span class="listarea"></span>'),
739     list = field.value ? field.value.split("\n") : [''];
740
741   if ($('#'+id).length)
742     return;
743
744   // add input rows
745   $.each(list, function(i, v) {
746     area.append(smart_field_row(v, field.name, i, $(field).data('size')));
747   });
748
749   area.attr('id', id);
750   field = $(field);
751
752   if (field.attr('disabled'))
753     area.hide();
8b5038 754   // disable the original field anyway, we don't want it in POST
AM 755   else
756     field.prop('disabled', true);
c6f075 757
AM 758   field.after(area);
759
760   if (field.hasClass('error')) {
761     area.addClass('error');
762     rcmail.managesieve_tip_register([[id, field.data('tip')]]);
763   }
764 };
765
766 function smart_field_row(value, name, idx, size)
767 {
768   // build row element content
769   var input, content = '<span class="listelement">'
bba781 770       + '<span class="reset"></span><input type="text"></span>',
c6f075 771     elem = $(content),
AM 772     attrs = {value: value, name: name + '[]'};
773
774   if (size)
775     attrs.size = size;
776
bba781 777   input = $('input', elem).attr(attrs).keydown(function(e) {
AM 778     var input = $(this);
13b33d 779
bba781 780     // element creation event (on Enter)
AM 781     if (e.which == 13) {
782       var name = input.attr('name').replace(/\[\]$/, ''),
783         dt = (new Date()).getTime(),
784         elem = smart_field_row('', name, dt, size);
c6f075 785
bba781 786       input.parent().after(elem);
AM 787       $('input', elem).focus();
788     }
13b33d 789     // backspace or delete: remove input, focus previous one
AM 790     else if ((e.which == 8 || e.which == 46) && input.val() == '') {
791
792       var parent = input.parent(), siblings = parent.parent().children();
793
794       if (siblings.length > 1) {
795         if (parent.prev().length)
796           parent.prev().children('input').focus();
797         else
798           parent.next().children('input').focus();
799
800         parent.remove();
801         return false;
802       }
803     }
c6f075 804   });
AM 805
806   // element deletion event
807   $('span[class="reset"]', elem).click(function() {
bba781 808     var span = $(this.parentNode);
c6f075 809
AM 810     if (span.parent().children().length > 1)
811       span.remove();
812     else
813       $('input', span).val('').focus();
814   });
815
816   return elem;
817 }
818
9c38c5 819 // Reset and fill the smart list input with new data
AM 820 function smart_field_reset(field, data)
821 {
822   var id = field.id + '_list',
823     list = data.length ? data : [''];
824     area = $('#' + id);
825
826   area.empty();
827
828   // add input rows
829   $.each(list, function(i, v) {
830     area.append(smart_field_row(v, field.name, i, $(field).data('size')));
831   });
832 }
833
48e9c1 834 // Register onmouse(leave/enter) events for tips on specified form element
T 835 rcube_webmail.prototype.managesieve_tip_register = function(tips)
836 {
837   var n, framed = parent.rcmail,
838     tip = framed ? parent.rcmail.env.ms_tip_layer : rcmail.env.ms_tip_layer;
839
d9ff47 840   for (n in tips) {
48e9c1 841     $('#'+tips[n][0])
c6f075 842       .data('tip', tips[n][1])
d9ff47 843       .mouseleave(function(e) { tip.hide(); })
AM 844       .mouseenter(function(e) {
c6f075 845         var elem = $(this),
AM 846           offset = elem.offset(),
847           left = offset.left,
848           top = offset.top - 12,
849           minwidth = elem.width();
48e9c1 850
c6f075 851         if (framed) {
AM 852           offset = $((rcmail.env.task == 'mail'  ? '#sievefilterform > iframe' : '#filter-box'), parent.document).offset();
853           top  += offset.top;
854           left += offset.left;
855         }
48e9c1 856
c6f075 857         tip.html(elem.data('tip'));
AM 858         top -= tip.height();
48e9c1 859
c6f075 860         tip.css({left: left, top: top, minWidth: (minwidth-2) + 'px'}).show();
d9ff47 861       });
48e9c1 862   }
T 863 };
864
581b6b 865 // format time string
AM 866 function sieve_formattime(hour, minutes)
867 {
868   var i, c, h, time = '', format = rcmail.env.time_format || 'H:i';
869
870   for (i=0; i<format.length; i++) {
871     c = format.charAt(i);
872     switch (c) {
873       case 'a': time += hour > 12 ? 'am' : 'pm'; break;
874       case 'A': time += hour > 12 ? 'AM' : 'PM'; break;
875       case 'g':
876       case 'h':
877         h = hour == 0 ? 12 : hour > 12 ? hour - 12 : hour;
878         time += (c == 'h' && hour < 10 ? '0' : '') + hour;
879         break;
880       case 'G': time += hour; break;
881       case 'H': time += (hour < 10 ? '0' : '') + hour; break;
882       case 'i': time += (minutes < 10 ? '0' : '') + minutes; break;
883       case 's': time += '00';
884       default: time += c;
885     }
886   }
887
888   return time;
889 }
890
891 function sieve_form_init()
892 {
893   // small resize for header element
894   $('select[name="_header[]"]', rcmail.gui_objects.sieveform).each(function() {
895     if (this.value == '...') this.style.width = '40px';
896   });
897
898   // resize dialog window
899   if (rcmail.env.action == 'plugin.managesieve' && rcmail.env.task == 'mail') {
900     parent.rcmail.managesieve_dialog_resize(rcmail.gui_objects.sieveform);
901   }
902
903   $('input[type="text"]:first', rcmail.gui_objects.sieveform).focus();
904
905   // initialize smart list inputs
906   $('textarea[data-type="list"]', rcmail.gui_objects.sieveform).each(function() {
907     smart_field_init(this);
908   });
909
910   // enable date pickers on date fields
911   if ($.datepicker && rcmail.env.date_format) {
912     $.datepicker.setDefaults({
913       dateFormat: rcmail.env.date_format,
914       changeMonth: true,
915       showOtherMonths: true,
916       selectOtherMonths: true,
917       onSelect: function(dateText) { $(this).focus().val(dateText); }
918     });
919     $('input.datepicker').datepicker();
920   }
921
922   // configure drop-down menu on time input fields based on jquery UI autocomplete
923   $('#vacation_timefrom, #vacation_timeto')
924     .attr('autocomplete', "off")
925     .autocomplete({
926       delay: 100,
927       minLength: 1,
928       source: function(p, callback) {
929         var h, result = [];
930         for (h = 0; h < 24; h++)
931           result.push(sieve_formattime(h, 0));
932         result.push(sieve_formattime(23, 59));
933
934         return callback(result);
935       },
936       open: function(event, ui) {
937         // scroll to current time
938         var $this = $(this), val = $this.val(),
939           widget = $this.autocomplete('widget').css('width', '10em'),
940           menu = $this.data('ui-autocomplete').menu;
941
942         if (val && val.length)
943           widget.children().each(function() {
944             var li = $(this);
945             if (li.text().indexOf(val) == 0)
946               menu._scrollIntoView(li);
947           });
948       },
949       select: function(event, ui) {
950         $(this).val(ui.item.value);
951         return false;
952       }
953     })
954     .click(function() {  // show drop-down upon clicks
955       $(this).autocomplete('search', $(this).val() || ' ');
956     })
957 }
958
959
48e9c1 960 /*********************************************************/
T 961 /*********           Mail UI methods             *********/
962 /*********************************************************/
963
fb5255 964 rcube_webmail.prototype.managesieve_create = function(force)
48e9c1 965 {
6e6f9c 966   if (!force && this.env.action != 'show') {
fb5255 967     var uid = this.message_list.get_single_selection(),
AM 968       lock = this.set_busy(true, 'loading');
969
970     this.http_post('plugin.managesieve-action', {_uid: uid}, lock);
971     return;
972   }
973
974   if (!this.env.sieve_headers || !this.env.sieve_headers.length)
48e9c1 975     return;
T 976
977   var i, html, buttons = {}, dialog = $("#sievefilterform");
978
979   // create dialog window
980   if (!dialog.length) {
981     dialog = $('<div id="sievefilterform"></div>');
982     $('body').append(dialog);
983   }
984
985   // build dialog window content
8f8bea 986   html = '<fieldset><legend>'+this.get_label('managesieve.usedata')+'</legend><ul>';
fb5255 987   for (i in this.env.sieve_headers)
48e9c1 988     html += '<li><input type="checkbox" name="headers[]" id="sievehdr'+i+'" value="'+i+'" checked="checked" />'
fb5255 989       +'<label for="sievehdr'+i+'">'+this.env.sieve_headers[i][0]+':</label> '+this.env.sieve_headers[i][1]+'</li>';
48e9c1 990   html += '</ul></fieldset>';
T 991
992   dialog.html(html);
993
994   // [Next Step] button action
8f8bea 995   buttons[this.get_label('managesieve.nextstep')] = function () {
48e9c1 996     // check if there's at least one checkbox checked
T 997     var hdrs = $('input[name="headers[]"]:checked', dialog);
998     if (!hdrs.length) {
8f8bea 999       alert(rcmail.get_label('managesieve.nodata'));
48e9c1 1000       return;
T 1001     }
1002
1003     // build frame URL
1004     var url = rcmail.get_task_url('mail');
1005     url = rcmail.add_url(url, '_action', 'plugin.managesieve');
1006     url = rcmail.add_url(url, '_framed', 1);
1007
1008     hdrs.map(function() {
1009       var val = rcmail.env.sieve_headers[this.value];
1010       url = rcmail.add_url(url, 'r['+this.value+']', val[0]+':'+val[1]);
1011     });
1012
1013     // load form in the iframe
1014     var frame = $('<iframe>').attr({src: url, frameborder: 0})
46f06c 1015     dialog.empty().append(frame).dialog('widget').resize();
48e9c1 1016
T 1017     // Change [Next Step] button with [Save] button
1018     buttons = {};
8f8bea 1019     buttons[rcmail.get_label('save')] = function() {
48e9c1 1020       var win = $('iframe', dialog).get(0).contentWindow;
T 1021       win.rcmail.managesieve_save();
1022     };
1023     dialog.dialog('option', 'buttons', buttons);
1024   };
1025
1026   // show dialog window
1027   dialog.dialog({
1028     modal: false,
64542f 1029     resizable: true,
AM 1030     closeOnEscape: !bw.ie7,  // disable for performance reasons
8f8bea 1031     title: this.get_label('managesieve.newfilter'),
48e9c1 1032     close: function() { rcmail.managesieve_dialog_close(); },
T 1033     buttons: buttons,
1034     minWidth: 600,
1035     minHeight: 300,
1036     height: 250
1037   }).show();
1038
1039   this.env.managesieve_dialog = dialog;
1040 }
1041
1042 rcube_webmail.prototype.managesieve_dialog_close = function()
1043 {
1044   var dialog = this.env.managesieve_dialog;
1045
1046   // BUG(?): if we don't remove the iframe first, it will be reloaded
1047   dialog.html('');
1048   dialog.dialog('destroy').hide();
1049 }
1050
1051 rcube_webmail.prototype.managesieve_dialog_resize = function(o)
1052 {
1053   var dialog = this.env.managesieve_dialog,
1054     win = $(window), form = $(o);
1055     width = $('fieldset:first', o).width(), // fieldset width is more appropriate here
1056     height = form.height(),
1057     w = win.width(), h = win.height();
1058
1059   dialog.dialog('option', { height: Math.min(h-20, height+120), width: Math.min(w-20, width+65) })
1060     .dialog('option', 'position', ['center', 'center']);  // works in a separate call only (!?)
1061 }