summaryrefslogtreecommitdiff
path: root/program/js/app.js
diff options
context:
space:
mode:
Diffstat (limited to 'program/js/app.js')
-rw-r--r--program/js/app.js687
1 files changed, 447 insertions, 240 deletions
diff --git a/program/js/app.js b/program/js/app.js
index 7fb644145..f586c1143 100644
--- a/program/js/app.js
+++ b/program/js/app.js
@@ -3,8 +3,8 @@
| Roundcube Webmail Client Script |
| |
| This file is part of the Roundcube Webmail client |
- | Copyright (C) 2005-2013, The Roundcube Dev Team |
- | Copyright (C) 2011-2013, Kolab Systems AG |
+ | Copyright (C) 2005-2014, The Roundcube Dev Team |
+ | Copyright (C) 2011-2014, Kolab Systems AG |
| |
| Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. |
@@ -31,6 +31,7 @@ function rcube_webmail()
this.onloads = [];
this.messages = {};
this.group2expand = {};
+ this.http_request_jobs = {};
// webmail client settings
this.dblclick_time = 500;
@@ -138,11 +139,11 @@ function rcube_webmail()
// initialize webmail client
this.init = function()
{
- var n, p = this;
+ var n;
this.task = this.env.task;
// check browser
- if (!bw.dom || !bw.xmlhttp_test() || (bw.mz && bw.vendver < 1.9)) {
+ if (this.env.server_error != 409 && (!bw.dom || !bw.xmlhttp_test() || (bw.mz && bw.vendver < 1.9) || (bw.ie && bw.vendver < 7))) {
this.goto_url('error', '_code=0x199');
return;
}
@@ -199,23 +200,29 @@ function rcube_webmail()
column_movable:this.env.col_movable, dblclick_time:this.dblclick_time
});
this.message_list
- .addEventListener('initrow', function(o) { p.init_message_row(o); })
- .addEventListener('dblclick', function(o) { p.msglist_dbl_click(o); })
- .addEventListener('click', function(o) { p.msglist_click(o); })
- .addEventListener('keypress', function(o) { p.msglist_keypress(o); })
- .addEventListener('select', function(o) { p.msglist_select(o); })
- .addEventListener('dragstart', function(o) { p.drag_start(o); })
- .addEventListener('dragmove', function(e) { p.drag_move(e); })
- .addEventListener('dragend', function(e) { p.drag_end(e); })
- .addEventListener('expandcollapse', function(o) { p.msglist_expand(o); })
- .addEventListener('column_replace', function(o) { p.msglist_set_coltypes(o); })
- .addEventListener('listupdate', function(o) { p.triggerEvent('listupdate', o); })
+ .addEventListener('initrow', function(o) { ref.init_message_row(o); })
+ .addEventListener('dblclick', function(o) { ref.msglist_dbl_click(o); })
+ .addEventListener('click', function(o) { ref.msglist_click(o); })
+ .addEventListener('keypress', function(o) { ref.msglist_keypress(o); })
+ .addEventListener('select', function(o) { ref.msglist_select(o); })
+ .addEventListener('dragstart', function(o) { ref.drag_start(o); })
+ .addEventListener('dragmove', function(e) { ref.drag_move(e); })
+ .addEventListener('dragend', function(e) { ref.drag_end(e); })
+ .addEventListener('expandcollapse', function(o) { ref.msglist_expand(o); })
+ .addEventListener('column_replace', function(o) { ref.msglist_set_coltypes(o); })
+ .addEventListener('listupdate', function(o) { ref.triggerEvent('listupdate', o); })
.init();
- document.onmouseup = function(e){ return p.doc_mouse_up(e); };
- this.gui_objects.messagelist.parentNode.onmousedown = function(e){ return p.click_on_list(e); };
+ // TODO: this should go into the list-widget code
+ $(this.message_list.thead).on('click', 'a.sortcol', function(e){
+ return ref.command('sort', $(this).attr('rel'), this);
+ });
+
+ document.onmouseup = function(e){ return ref.doc_mouse_up(e); };
+ this.gui_objects.messagelist.parentNode.onmousedown = function(e){ return ref.click_on_list(e); };
this.enable_command('toggle_status', 'toggle_flag', 'sort', true);
+ this.enable_command('set-listmode', this.env.threads && !this.is_multifolder_listing());
// load messages
this.command('list');
@@ -288,7 +295,7 @@ function rcube_webmail()
}
}
- document.onmouseup = function(e){ return p.doc_mouse_up(e); };
+ document.onmouseup = function(e){ return ref.doc_mouse_up(e); };
// init message compose form
this.init_messageform();
@@ -315,7 +322,7 @@ function rcube_webmail()
this.contact_list = new rcube_list_widget(this.gui_objects.contactslist,
{ multiselect:true, draggable:false, keyboard:false });
this.contact_list
- .addEventListener('initrow', function(o) { p.triggerEvent('insertrow', { cid:o.uid, row:o }); })
+ .addEventListener('initrow', function(o) { ref.triggerEvent('insertrow', { cid:o.uid, row:o }); })
.addEventListener('select', function(o) { ref.compose_recipient_select(o); })
.addEventListener('dblclick', function(o) { ref.compose_add_recipient('to'); })
.init();
@@ -356,21 +363,21 @@ function rcube_webmail()
this.contact_list = new rcube_list_widget(this.gui_objects.contactslist,
{multiselect:true, draggable:this.gui_objects.folderlist?true:false, keyboard:true});
this.contact_list
- .addEventListener('initrow', function(o) { p.triggerEvent('insertrow', { cid:o.uid, row:o }); })
- .addEventListener('keypress', function(o) { p.contactlist_keypress(o); })
- .addEventListener('select', function(o) { p.contactlist_select(o); })
- .addEventListener('dragstart', function(o) { p.drag_start(o); })
- .addEventListener('dragmove', function(e) { p.drag_move(e); })
- .addEventListener('dragend', function(e) { p.drag_end(e); })
+ .addEventListener('initrow', function(o) { ref.triggerEvent('insertrow', { cid:o.uid, row:o }); })
+ .addEventListener('keypress', function(o) { ref.contactlist_keypress(o); })
+ .addEventListener('select', function(o) { ref.contactlist_select(o); })
+ .addEventListener('dragstart', function(o) { ref.drag_start(o); })
+ .addEventListener('dragmove', function(e) { ref.drag_move(e); })
+ .addEventListener('dragend', function(e) { ref.drag_end(e); })
.init();
if (this.env.cid)
this.contact_list.highlight_row(this.env.cid);
- this.gui_objects.contactslist.parentNode.onmousedown = function(e){ return p.click_on_list(e); };
- document.onmouseup = function(e){ return p.doc_mouse_up(e); };
+ this.gui_objects.contactslist.parentNode.onmousedown = function(e){ return ref.click_on_list(e); };
+ document.onmouseup = function(e){ return ref.doc_mouse_up(e); };
- $(this.gui_objects.qsearchbox).focusin(function() { rcmail.contact_list.blur(); });
+ $(this.gui_objects.qsearchbox).focusin(function() { ref.contact_list.blur(); });
this.update_group_commands();
this.command('list');
@@ -422,7 +429,7 @@ function rcube_webmail()
this.identity_list = new rcube_list_widget(this.gui_objects.identitieslist,
{multiselect:false, draggable:false, keyboard:false});
this.identity_list
- .addEventListener('select', function(o) { p.identity_select(o); })
+ .addEventListener('select', function(o) { ref.identity_select(o); })
.init()
.focus();
@@ -432,7 +439,7 @@ function rcube_webmail()
else if (this.gui_objects.sectionslist) {
this.sections_list = new rcube_list_widget(this.gui_objects.sectionslist, {multiselect:false, draggable:false, keyboard:false});
this.sections_list
- .addEventListener('select', function(o) { p.section_select(o); })
+ .addEventListener('select', function(o) { ref.section_select(o); })
.init()
.focus();
}
@@ -444,10 +451,10 @@ function rcube_webmail()
this.responses_list
.addEventListener('select', function(list) {
var win, id = list.get_single_selection();
- p.enable_command('delete', !!id && $.inArray(id, p.env.readonly_responses) < 0);
- if (id && (win = p.get_frame_window(p.env.contentframe))) {
- p.set_busy(true);
- p.location_href({ _action:'edit-response', _key:id, _framed:1 }, win);
+ ref.enable_command('delete', !!id && $.inArray(id, ref.env.readonly_responses) < 0);
+ if (id && (win = ref.get_frame_window(ref.env.contentframe))) {
+ ref.set_busy(true);
+ ref.location_href({ _action:'edit-response', _key:id, _framed:1 }, win);
}
})
.init()
@@ -466,7 +473,7 @@ function rcube_webmail()
$('#rcmloginpwd').focus();
// detect client timezone
- if (window.jstz && !bw.ie6) {
+ if (window.jstz) {
var timezone = jstz.determine();
if (timezone.name())
$('#rcmlogintz').val(timezone.name());
@@ -569,7 +576,8 @@ function rcube_webmail()
if (obj && obj.blur)
obj.blur();
- if (this.busy)
+ // do nothing if interface is locked by other command (with exception for searching reset)
+ if (this.busy && !(command == 'reset-search' && this.last_command == 'search'))
return false;
// let the browser handle this click (shift/ctrl usually opens the link in a new window/tab)
@@ -595,6 +603,8 @@ function rcube_webmail()
this.remove_compose_data(this.env.compose_id);
}
+ this.last_command = command;
+
// process external commands
if (typeof this.command_handlers[command] === 'function') {
ret = this.command_handlers[command](props, obj);
@@ -689,7 +699,7 @@ function rcube_webmail()
case 'open':
if (uid = this.get_single_uid()) {
- obj.href = this.url('show', {_mbox: this.env.mailbox, _uid: uid});
+ obj.href = this.url('show', {_mbox: this.get_message_mailbox(uid), _uid: uid});
return true;
}
break;
@@ -700,8 +710,17 @@ function rcube_webmail()
break;
case 'list':
- if (props && props != '')
- this.reset_qsearch();
+ // re-send search query for the selected folder
+ if (props && props != '' && this.env.search_request && this.gui_objects.qsearchbox.value) {
+ var oldmbox = this.env.search_scope == 'all' ? '*' : this.env.mailbox;
+ this.env.search_mods[props] = this.env.search_mods[oldmbox]; // copy search mods from active search
+ this.env.mailbox = props;
+ this.env.search_scope = 'sub';
+ this.qsearch(this.gui_objects.qsearchbox.value);
+ this.select_folder(this.env.mailbox, '', true);
+ break;
+ }
+
if (this.env.action == 'compose' && this.env.extwin)
window.close();
else if (this.task == 'mail') {
@@ -712,6 +731,10 @@ function rcube_webmail()
this.list_contacts(props);
break;
+ case 'set-listmode':
+ this.set_list_options(null, undefined, undefined, props == 'threads' ? 1 : 0);
+ break;
+
case 'sort':
var sort_order = this.env.sort_order,
sort_col = !this.env.disabled_sort_col ? props : this.env.sort_col;
@@ -792,9 +815,9 @@ function rcube_webmail()
this.load_contact(cid, 'edit');
else if (this.task == 'settings' && props)
this.load_identity(props, 'edit-identity');
- else if (this.task == 'mail' && (cid = this.get_single_uid())) {
- url = { _mbox: this.env.mailbox };
- url[this.env.mailbox == this.env.drafts_mailbox && props != 'new' ? '_draft_uid' : '_uid'] = cid;
+ else if (this.task == 'mail' && (uid = this.get_single_uid())) {
+ url = { _mbox: this.get_message_mailbox(uid) };
+ url[this.env.mailbox == this.env.drafts_mailbox && props != 'new' ? '_draft_uid' : '_uid'] = uid;
this.open_compose_step(url);
}
break;
@@ -1054,8 +1077,9 @@ function rcube_webmail()
// Reset the auto-save timer
clearTimeout(this.save_timer);
- if (!this.upload_file(props || this.gui_objects.uploadform, 'upload')) {
- alert(this.get_label('selectimportfile'));
+ if (!(flag = this.upload_file(props || this.gui_objects.uploadform, 'upload'))) {
+ if (flag !== false)
+ alert(this.get_label('selectimportfile'));
aborted = true;
}
break;
@@ -1077,7 +1101,7 @@ function rcube_webmail()
case 'reply-list':
case 'reply':
if (uid = this.get_single_uid()) {
- url = {_reply_uid: uid, _mbox: this.env.mailbox};
+ url = {_reply_uid: uid, _mbox: this.get_message_mailbox(uid)};
if (command == 'reply-all')
// do reply-list, when list is detected and popup menu wasn't used
url._all = (!props && this.env.reply_all_mode == 1 && this.commands['reply-list'] ? 'list' : 'all');
@@ -1093,7 +1117,7 @@ function rcube_webmail()
case 'forward':
var uids = this.env.uid ? [this.env.uid] : (this.message_list ? this.message_list.get_selection() : []);
if (uids.length) {
- url = { _forward_uid: this.uids_to_list(uids), _mbox: this.env.mailbox };
+ url = { _forward_uid: this.uids_to_list(uids), _mbox: this.env.mailbox, _search: this.env.search_request };
if (command == 'forward-attachment' || (!props && this.env.forward_attachment) || uids.length > 1)
url._attachment = 1;
this.open_compose_step(url);
@@ -1105,7 +1129,7 @@ function rcube_webmail()
this.gui_objects.messagepartframe.contentWindow.print();
}
else if (uid = this.get_single_uid()) {
- ref.printwin = this.open_window(this.env.comm_path+'&_action=print&_uid='+uid+'&_mbox='+urlencode(this.env.mailbox)+(this.env.safemode ? '&_safe=1' : ''), true, true);
+ ref.printwin = this.open_window(this.env.comm_path+'&_action=print&_uid='+uid+'&_mbox='+urlencode(this.get_message_mailbox(uid))+(this.env.safemode ? '&_safe=1' : ''), true, true);
if (this.printwin) {
if (this.env.action != 'show')
this.mark_message('read', uid);
@@ -1122,8 +1146,9 @@ function rcube_webmail()
if (this.env.action == 'get') {
location.href = location.href.replace(/_frame=/, '_download=');
}
- else if (uid = this.get_single_uid())
- this.goto_url('viewsource', { _uid: uid, _mbox: this.env.mailbox, _save: 1 });
+ else if (uid = this.get_single_uid()) {
+ this.goto_url('viewsource', { _uid: uid, _mbox: this.get_message_mailbox(uid), _save: 1 });
+ }
break;
// quicksearch
@@ -1179,12 +1204,15 @@ function rcube_webmail()
break;
case 'import-messages':
- var form = props || this.gui_objects.importform;
- var importlock = this.set_busy(true, 'importwait');
+ var form = props || this.gui_objects.importform,
+ importlock = this.set_busy(true, 'importwait');
+
$('input[name="_unlock"]', form).val(importlock);
- if (!this.upload_file(form, 'import')) {
+
+ if (!(flag = this.upload_file(form, 'import'))) {
this.set_busy(false, null, importlock);
- alert(this.get_label('selectimportfile'));
+ if (flag !== false)
+ alert(this.get_label('selectimportfile'));
aborted = true;
}
break;
@@ -1275,6 +1303,11 @@ function rcube_webmail()
}
};
+ this.command_enabled = function(cmd)
+ {
+ return this.commands[cmd];
+ }
+
// lock/unlock interface
this.set_busy = function(a, message, id)
{
@@ -1630,7 +1663,7 @@ function rcube_webmail()
var uid = list.get_single_selection();
- if (uid && this.env.mailbox == this.env.drafts_mailbox)
+ if (uid && (this.env.messages[uid].mbox || this.env.mailbox) == this.env.drafts_mailbox)
this.open_compose_step({ _draft_uid: uid, _mbox: this.env.mailbox });
else if (uid)
this.show_message(uid, false, false);
@@ -1671,28 +1704,30 @@ function rcube_webmail()
{
var i, found, name, cols = list.thead.rows[0].cells;
- this.env.coltypes = [];
+ this.env.listcols = [];
for (i=0; i<cols.length; i++)
if (cols[i].id && cols[i].id.startsWith('rcm')) {
name = cols[i].id.slice(3);
- this.env.coltypes.push(name);
+ this.env.listcols.push(name);
}
- if ((found = $.inArray('flag', this.env.coltypes)) >= 0)
+ if ((found = $.inArray('flag', this.env.listcols)) >= 0)
this.env.flagged_col = found;
- if ((found = $.inArray('subject', this.env.coltypes)) >= 0)
+ if ((found = $.inArray('subject', this.env.listcols)) >= 0)
this.env.subject_col = found;
- this.command('save-pref', { name: 'list_cols', value: this.env.coltypes, session: 'list_attrib/columns' });
+ this.command('save-pref', { name: 'list_cols', value: this.env.listcols, session: 'list_attrib/columns' });
};
this.check_droptarget = function(id)
{
switch (this.task) {
case 'mail':
- return (this.env.mailboxes[id] && this.env.mailboxes[id].id != this.env.mailbox && !this.env.mailboxes[id].virtual) ? 1 : 0;
+ return (this.env.mailboxes[id]
+ && !this.env.mailboxes[id].virtual
+ && (this.env.mailboxes[id].id != this.env.mailbox || this.is_multifolder_listing())) ? 1 : 0;
case 'settings':
return id != this.env.mailbox ? 1 : 0;
@@ -1761,31 +1796,31 @@ function rcube_webmail()
this.init_message_row = function(row)
{
- var i, fn = {}, self = this, uid = row.uid,
- status_icon = (this.env.status_col != null ? 'status' : 'msg') + 'icn' + row.uid;
+ var i, fn = {}, uid = row.uid,
+ status_icon = (this.env.status_col != null ? 'status' : 'msg') + 'icn' + row.id;
if (uid && this.env.messages[uid])
$.extend(row, this.env.messages[uid]);
// set eventhandler to status icon
if (row.icon = document.getElementById(status_icon)) {
- fn.icon = function(e) { self.command('toggle_status', uid); };
+ fn.icon = function(e) { ref.command('toggle_status', uid); };
}
// save message icon position too
if (this.env.status_col != null)
- row.msgicon = document.getElementById('msgicn'+row.uid);
+ row.msgicon = document.getElementById('msgicn'+row.id);
else
row.msgicon = row.icon;
// set eventhandler to flag icon
- if (this.env.flagged_col != null && (row.flagicon = document.getElementById('flagicn'+row.uid))) {
- fn.flagicon = function(e) { self.command('toggle_flag', uid); };
+ if (this.env.flagged_col != null && (row.flagicon = document.getElementById('flagicn'+row.id))) {
+ fn.flagicon = function(e) { ref.command('toggle_flag', uid); };
}
// set event handler to thread expand/collapse icon
- if (!row.depth && row.has_children && (row.expando = document.getElementById('rcmexpando'+row.uid))) {
- fn.expando = function(e) { self.expand_message_row(e, uid); };
+ if (!row.depth && row.has_children && (row.expando = document.getElementById('rcmexpando'+row.id))) {
+ fn.expando = function(e) { ref.expand_message_row(e, uid); };
}
// attach events
@@ -1831,6 +1866,7 @@ function rcube_webmail()
selected: this.select_all_mode || this.message_list.in_selection(uid),
ml: flags.ml?1:0,
ctype: flags.ctype,
+ mbox: flags.mbox,
// flags from plugins
flags: flags.extra_flags
});
@@ -1845,7 +1881,7 @@ function rcube_webmail()
+ (flags.deleted ? ' deleted' : '')
+ (flags.flagged ? ' flagged' : '')
+ (message.selected ? ' selected' : ''),
- row = { cols:[], style:{}, id:'rcmrow'+uid };
+ row = { cols:[], style:{}, id:'rcmrow'+this.html_identifier(uid,true), uid:uid };
// message status icons
css_class = 'msgicon';
@@ -1871,7 +1907,7 @@ function rcube_webmail()
if (this.env.threading) {
if (message.depth) {
// This assumes that div width is hardcoded to 15px,
- tree += '<span id="rcmtab' + uid + '" class="branch" style="width:' + (message.depth * 15) + 'px;">&nbsp;&nbsp;</span>';
+ tree += '<span id="rcmtab' + row.id + '" class="branch" style="width:' + (message.depth * 15) + 'px;">&nbsp;&nbsp;</span>';
if ((rows[message.parent_uid] && rows[message.parent_uid].expanded === false)
|| ((this.env.autoexpand_threads == 0 || this.env.autoexpand_threads == 2) &&
@@ -1890,7 +1926,7 @@ function rcube_webmail()
message.expanded = true;
}
- expando = '<div id="rcmexpando' + uid + '" class="' + (message.expanded ? 'expanded' : 'collapsed') + '">&nbsp;&nbsp;</div>';
+ expando = '<div id="rcmexpando' + row.id + '" class="' + (message.expanded ? 'expanded' : 'collapsed') + '">&nbsp;&nbsp;</div>';
row_class += ' thread' + (message.expanded? ' expanded' : '');
}
@@ -1898,28 +1934,34 @@ function rcube_webmail()
row_class += ' unroot';
}
- tree += '<span id="msgicn'+uid+'" class="'+css_class+'">&nbsp;</span>';
+ tree += '<span id="msgicn'+row.id+'" class="'+css_class+'">&nbsp;</span>';
row.className = row_class;
- // build subject link
+ // build subject link
if (cols.subject) {
var action = flags.mbox == this.env.drafts_mailbox ? 'compose' : 'show';
var uid_param = flags.mbox == this.env.drafts_mailbox ? '_draft_uid' : '_uid';
- cols.subject = '<a href="./?_task=mail&_action='+action+'&_mbox='+urlencode(flags.mbox)+'&'+uid_param+'='+uid+'"'+
+ cols.subject = '<a href="./?_task=mail&_action='+action+'&_mbox='+urlencode(flags.mbox)+'&'+uid_param+'='+urlencode(uid)+'"'+
' onclick="return rcube_event.cancel(event)" onmouseover="rcube_webmail.long_subject_title(this,'+(message.depth+1)+')"><span>'+cols.subject+'</span></a>';
}
// add each submitted col
- for (n in this.env.coltypes) {
- c = this.env.coltypes[n];
- col = { className: String(c).toLowerCase() };
+ for (n in this.env.listcols) {
+ c = this.env.listcols[n];
+ col = {className: String(c).toLowerCase(), events:{}};
+
+ if (this.env.coltypes[c] && this.env.coltypes[c].hidden) {
+ col.className += ' hidden';
+ }
if (c == 'flag') {
css_class = (flags.flagged ? 'flagged' : 'unflagged');
- html = '<span id="flagicn'+uid+'" class="'+css_class+'">&nbsp;</span>';
+ html = '<span id="flagicn'+row.id+'" class="'+css_class+'">&nbsp;</span>';
}
else if (c == 'attachment') {
- if (/application\/|multipart\/(m|signed)/.test(flags.ctype))
+ if (flags.attachmentClass)
+ html = '<span class="'+flags.attachmentClass+'">&nbsp;</span>';
+ else if (/application\/|multipart\/(m|signed)/.test(flags.ctype))
html = '<span class="attachment">&nbsp;</span>';
else if (/multipart\/report/.test(flags.ctype))
html = '<span class="report">&nbsp;</span>';
@@ -1935,16 +1977,13 @@ function rcube_webmail()
css_class = 'unreadchildren';
else
css_class = 'msgicon';
- html = '<span id="statusicn'+uid+'" class="'+css_class+'">&nbsp;</span>';
+ html = '<span id="statusicn'+row.id+'" class="'+css_class+'">&nbsp;</span>';
}
else if (c == 'threads')
html = expando;
else if (c == 'subject') {
- if (bw.ie) {
- col.onmouseover = function() { rcube_webmail.long_subject_title_ex(this, message.depth+1); };
- if (bw.ie8)
- tree = '<span></span>' + tree; // #1487821
- }
+ if (bw.ie)
+ col.events.mouseover = function() { rcube_webmail.long_subject_title_ex(this); };
html = tree + cols[c];
}
else if (c == 'priority') {
@@ -1953,6 +1992,9 @@ function rcube_webmail()
else
html = '&nbsp;';
}
+ else if (c == 'folder') {
+ html = '<span onmouseover="rcube_webmail.long_subject_title(this)">' + cols[c] + '<span>';
+ }
else
html = cols[c];
@@ -2002,7 +2044,7 @@ function rcube_webmail()
if (cols && cols.length) {
// make sure new columns are added at the end of the list
- var i, idx, name, newcols = [], oldcols = this.env.coltypes;
+ var i, idx, name, newcols = [], oldcols = this.env.listcols;
for (i=0; i<oldcols.length; i++) {
name = oldcols[i];
idx = $.inArray(name, cols);
@@ -2033,7 +2075,7 @@ function rcube_webmail()
var win, target = window,
action = preview ? 'preview': 'show',
- url = '&_action='+action+'&_uid='+id+'&_mbox='+urlencode(this.env.mailbox);
+ url = '&_action='+action+'&_uid='+id+'&_mbox='+urlencode(this.get_message_mailbox(id));
if (preview && (win = this.get_frame_window(this.env.contentframe))) {
target = win;
@@ -2150,7 +2192,7 @@ function rcube_webmail()
var lock = this.set_busy(true, 'checkingmail'),
params = this.check_recent_params();
- this.http_request('check-recent', params, lock);
+ this.http_post('check-recent', params, lock);
};
// list messages of a specific mailbox using filter
@@ -2162,11 +2204,20 @@ function rcube_webmail()
// reset vars
this.env.current_page = 1;
+ this.env.search_filter = filter;
this.http_request('search', this.search_params(false, filter), lock);
};
+ // reload the current message listing
+ this.refresh_list = function()
+ {
+ this.list_mailbox(this.env.mailbox, this.env.current_page || 1, null, { _clear:1 }, true);
+ if (this.message_list)
+ this.message_list.clear_selection();
+ };
+
// list messages of a specific mailbox
- this.list_mailbox = function(mbox, page, sort, url)
+ this.list_mailbox = function(mbox, page, sort, url, update_only)
{
var win, target = window;
@@ -2191,15 +2242,17 @@ function rcube_webmail()
this.select_all_mode = false;
}
- // unselect selected messages and clear the list and message data
- this.clear_message_list();
+ if (!update_only) {
+ // unselect selected messages and clear the list and message data
+ this.clear_message_list();
- if (mbox != this.env.mailbox || (mbox == this.env.mailbox && !page && !sort))
- url._refresh = 1;
+ if (mbox != this.env.mailbox || (mbox == this.env.mailbox && !page && !sort))
+ url._refresh = 1;
- this.select_folder(mbox, '', true);
- this.unmark_folder(mbox, 'recent', '', true);
- this.env.mailbox = mbox;
+ this.select_folder(mbox, '', true);
+ this.unmark_folder(mbox, 'recent', '', true);
+ this.env.mailbox = mbox;
+ }
// load message list remotely
if (this.gui_objects.messagelist) {
@@ -2233,20 +2286,17 @@ function rcube_webmail()
};
// send remote request to load message list
- this.list_mailbox_remote = function(mbox, page, post_data)
+ this.list_mailbox_remote = function(mbox, page, url)
{
- // clear message list first
- this.message_list.clear();
-
var lock = this.set_busy(true, 'loading');
- if (typeof post_data != 'object')
- post_data = {};
- post_data._mbox = mbox;
+ if (typeof url != 'object')
+ url = {};
+ url._mbox = mbox;
if (page)
- post_data._page = page;
+ url._page = page;
- this.http_request('list', post_data, lock);
+ this.http_request('list', url, lock);
};
// removes messages that doesn't exists from list selection array
@@ -2398,7 +2448,7 @@ function rcube_webmail()
}
if (html)
- $('#rcmtab'+uid).html(html);
+ $('#rcmtab'+this.html_identifier(uid, true)).html(html);
};
// update parent in a thread
@@ -2462,14 +2512,14 @@ function rcube_webmail()
r.depth--; // move left
// reset width and clear the content of a tab, icons will be added later
- $('#rcmtab'+r.uid).width(r.depth * 15).html('');
+ $('#rcmtab'+r.id).width(r.depth * 15).html('');
if (!r.depth) { // a new root
count++; // increase roots count
r.parent_uid = 0;
if (r.has_children) {
// replace 'leaf' with 'collapsed'
- $('#rcmrow'+r.uid+' '+'.leaf:first')
- .attr('id', 'rcmexpando' + r.uid)
+ $('#'+r.id+' .leaf:first')
+ .attr('id', 'rcmexpando' + r.id)
.attr('class', (r.obj.style.display != 'none' ? 'expanded' : 'collapsed'))
.bind('mousedown', {uid:r.uid, p:this},
function(e) { return e.data.p.expand_message_row(e, e.data.uid); });
@@ -2663,7 +2713,7 @@ function rcube_webmail()
return this.folder_selector(obj, function(folder) { ref.command('move', folder); });
// exit if current or no mailbox specified
- if (!mbox || mbox == this.env.mailbox)
+ if (!mbox || (mbox == this.env.mailbox && !this.is_multifolder_listing()))
return;
var lock = false, post_data = this.selection_post_data({_target_mbox: mbox});
@@ -2731,7 +2781,8 @@ function rcube_webmail()
// @private
this._with_selected_messages = function(action, post_data, lock)
{
- var count = 0, msg;
+ var count = 0, msg,
+ remove = (action == 'delete' || !this.is_multifolder_listing());
// update the list (remove rows, clear selection)
if (this.message_list) {
@@ -2748,10 +2799,11 @@ function rcube_webmail()
roots.push(root);
}
}
- this.message_list.remove_row(id, (this.env.display_next && n == selection.length-1));
+ if (remove)
+ this.message_list.remove_row(id, (this.env.display_next && n == selection.length-1));
}
// make sure there are no selected rows
- if (!this.env.display_next)
+ if (!this.env.display_next && remove)
this.message_list.clear_selection();
// update thread tree icons
for (n=0, len=roots.length; n<len; n++) {
@@ -2762,9 +2814,12 @@ function rcube_webmail()
if (count < 0)
post_data._count = (count*-1);
// remove threads from the end of the list
- else if (count > 0)
+ else if (count > 0 && remove)
this.delete_excessive_thread_rows();
+ if (!remove)
+ post_data._refresh = 1;
+
if (!lock) {
msg = action == 'move' ? 'movingmessage' : 'deletingmessage';
lock = this.display_message(this.get_label(msg), 'loading');
@@ -2974,7 +3029,8 @@ function rcube_webmail()
var icn_src, uid, i, len,
rows = this.message_list ? this.message_list.rows : {};
- uids = String(uids).split(',');
+ if (typeof uids == 'string')
+ uids = String(uids).split(',');
for (i=0, len=uids.length; i<len; i++) {
uid = uids[i];
@@ -2987,7 +3043,7 @@ function rcube_webmail()
// with select_all mode checking
this.uids_to_list = function(uids)
{
- return this.select_all_mode ? '*' : uids.join(',');
+ return this.select_all_mode ? '*' : (uids.length <= 1 ? uids.join(',') : uids);
};
// Sets title of the delete button
@@ -3060,8 +3116,8 @@ function rcube_webmail()
// handler for keyboard events on the _user field
this.login_user_keyup = function(e)
{
- var key = rcube_event.get_keycode(e);
- var passwd = $('#rcmloginpwd');
+ var key = rcube_event.get_keycode(e),
+ passwd = $('#rcmloginpwd');
// enter
if (key == 13 && passwd.length && !passwd.val()) {
@@ -3638,9 +3694,12 @@ function rcube_webmail()
$("input[name='_draft_saveid']").val(id);
// reset history of hidden iframe used for saving draft (#1489643)
- if (window.frames['savetarget'] && window.frames['savetarget'].history) {
+ // but don't do this on timer-triggered draft-autosaving (#1489789)
+ if (window.frames['savetarget'] && window.frames['savetarget'].history && !this.draft_autosave_submit) {
window.frames['savetarget'].history.back();
}
+
+ this.draft_autosave_submit = false;
}
// always remove local copy upon saving as draft
@@ -3650,7 +3709,11 @@ function rcube_webmail()
this.auto_save_start = function()
{
if (this.env.draft_autosave)
- this.save_timer = setTimeout(function(){ ref.command("savedraft"); }, this.env.draft_autosave * 1000);
+ this.draft_autosave_submit = false;
+ this.save_timer = setTimeout(function(){
+ ref.draft_autosave_submit = true; // set auto-saved flag (#1489789)
+ ref.command("savedraft");
+ }, this.env.draft_autosave * 1000);
// save compose form content to local storage every 5 seconds
if (!this.local_save_timer && window.localStorage) {
@@ -3796,9 +3859,9 @@ function rcube_webmail()
this.clear_compose_data = function()
{
if (window.localStorage) {
- var index = this.local_storage_get_item('compose.index', []);
+ var i, index = this.local_storage_get_item('compose.index', []);
- for (var i=0; i < index.length; i++) {
+ for (i=0; i < index.length; i++) {
this.local_storage_remove_item('compose.' + index[i]);
}
this.local_storage_remove_item('compose.index');
@@ -3969,7 +4032,7 @@ function rcube_webmail()
this.upload_file = function(form, action)
{
if (!form)
- return false;
+ return;
// count files and size on capable browser
var size = 0, numfiles = 0;
@@ -4029,8 +4092,6 @@ function rcube_webmail()
this.gui_objects.attachmentform = form;
return true;
}
-
- return false;
};
// add file name to attachment list
@@ -4052,7 +4113,7 @@ function rcube_webmail()
li.attr('id', name)
.addClass(att.classname)
.html(att.html)
- .on('mouseover', function() { rcube_webmail.long_subject_title_ex(this, 0); });
+ .on('mouseover', function() { rcube_webmail.long_subject_title_ex(this); });
// replace indicator's li
if (upload_id && (indicator = document.getElementById(upload_id))) {
@@ -4148,15 +4209,32 @@ function rcube_webmail()
r = this.http_request(action, url, lock);
this.env.qsearch = {lock: lock, request: r};
+ this.enable_command('set-listmode', this.env.threads && (this.env.search_scope || 'base') == 'base');
+
+ return true;
}
+
+ return false;
+ };
+
+ this.continue_search = function(request_id)
+ {
+ var lock = ref.set_busy(true, 'stillsearching');
+
+ setTimeout(function(){
+ var url = ref.search_params();
+ url._continue = request_id;
+ ref.env.qsearch = { lock: lock, request: ref.http_request('search', url, lock) };
+ }, 100);
};
// build URL params for search
- this.search_params = function(search, filter)
+ this.search_params = function(search, filter, smods)
{
var n, url = {}, mods_arr = [],
mods = this.env.search_mods,
- mbox = this.env.mailbox;
+ scope = this.env.search_scope || 'base',
+ mbox = scope == 'all' ? '*' : this.env.mailbox;
if (!filter && this.gui_objects.search_filter)
filter = this.gui_objects.search_filter.value;
@@ -4170,17 +4248,19 @@ function rcube_webmail()
if (search) {
url._q = search;
- if (mods && this.message_list)
- mods = mods[mbox] ? mods[mbox] : mods['*'];
+ if (!smods && mods && this.message_list)
+ smods = mods[mbox] || mods['*'];
- if (mods) {
- for (n in mods)
+ if (smods) {
+ for (n in smods)
mods_arr.push(n);
url._headers = mods_arr.join(',');
}
}
- if (mbox)
+ if (scope)
+ url._scope = scope;
+ if (mbox && scope != 'all')
url._mbox = mbox;
return url;
@@ -4198,8 +4278,44 @@ function rcube_webmail()
this.env.qsearch = null;
this.env.search_request = null;
this.env.search_id = null;
+
+ this.enable_command('set-listmode', this.env.threads);
+ };
+
+ this.set_searchscope = function(scope)
+ {
+ var old = this.env.search_scope;
+ this.env.search_scope = scope;
+
+ // re-send search query with new scope
+ if (scope != old && this.env.search_request) {
+ if (!this.qsearch(this.gui_objects.qsearchbox.value) && this.env.search_filter && this.env.search_filter != 'ALL')
+ this.filter_mailbox(this.env.search_filter);
+ if (scope != 'all')
+ this.select_folder(this.env.mailbox, '', true);
+ }
+ };
+
+ this.set_searchmods = function(mods)
+ {
+ var mbox = rcmail.env.mailbox,
+ scope = this.env.search_scope || 'base';
+
+ if (scope == 'all')
+ mbox = '*';
+
+ if (!this.env.search_mods)
+ this.env.search_mods = {};
+
+ this.env.search_mods[mbox] = mods;
};
+ this.is_multifolder_listing = function()
+ {
+ return typeof this.env.multifolder_listing != 'undefined' ? this.env.multifolder_listing :
+ (this.env.search_request && (this.env.search_scope || 'base') != 'base');
+ }
+
this.sent_successfully = function(type, msg, folders)
{
this.display_message(msg, type);
@@ -4376,7 +4492,7 @@ function rcube_webmail()
p = inp_value.lastIndexOf(this.env.recipients_separator, cpos-1),
q = inp_value.substring(p+1, cpos),
min = this.env.autocomplete_min_length,
- ac = this.ksearch_data;
+ data = this.ksearch_data;
// trim query string
q = $.trim(q);
@@ -4403,34 +4519,26 @@ function rcube_webmail()
return;
// ...new search value contains old one and previous search was not finished or its result was empty
- if (old_value && old_value.length && q.startsWith(old_value) && (!ac || ac.num <= 0) && this.env.contacts && !this.env.contacts.length)
+ if (old_value && old_value.length && q.startsWith(old_value) && (!data || data.num <= 0) && this.env.contacts && !this.env.contacts.length)
return;
- var i, lock, source, xhr, reqid = new Date().getTime(),
- post_data = {_search: q, _id: reqid},
- threads = props && props.threads ? props.threads : 1,
- sources = props && props.sources ? props.sources : [],
- action = props && props.action ? props.action : 'mail/autocomplete';
-
- this.ksearch_data = {id: reqid, sources: sources.slice(), action: action,
- locks: [], requests: [], num: sources.length};
-
- for (i=0; i<threads; i++) {
- source = this.ksearch_data.sources.shift();
- if (threads > 1 && source === undefined)
- break;
-
- post_data._source = source ? source : '';
- lock = this.display_message(this.get_label('searching'), 'loading');
- xhr = this.http_post(action, post_data, lock);
+ var sources = props && props.sources ? props.sources : [''];
+ var reqid = this.multi_thread_http_request({
+ items: sources,
+ threads: props && props.threads ? props.threads : 1,
+ action: props && props.action ? props.action : 'mail/autocomplete',
+ postdata: { _search:q, _source:'%s' },
+ lock: this.display_message(this.get_label('searching'), 'loading')
+ });
- this.ksearch_data.locks.push(lock);
- this.ksearch_data.requests.push(xhr);
- }
+ this.ksearch_data = { id:reqid, sources:sources.slice(), num:sources.length };
};
this.ksearch_query_results = function(results, search, reqid)
{
+ // trigger multi-thread http response callback
+ this.multi_thread_http_response(results, reqid);
+
// search stopped in meantime?
if (!this.ksearch_value)
return;
@@ -4442,7 +4550,6 @@ function rcube_webmail()
// display search results
var i, len, ul, li, text, type, init,
value = this.ksearch_value,
- data = this.ksearch_data,
maxlen = this.env.autocomplete_max ? this.env.autocomplete_max : 15;
// create results pane if not present
@@ -4498,27 +4605,8 @@ function rcube_webmail()
if (len)
this.env.contacts = this.env.contacts.concat(results);
- // run next parallel search
- if (data.id == reqid) {
- data.num--;
- if (maxlen > 0 && data.sources.length) {
- var lock, xhr, source = data.sources.shift(), post_data;
- if (source) {
- post_data = {_search: value, _id: reqid, _source: source};
- lock = this.display_message(this.get_label('searching'), 'loading');
- xhr = this.http_post(data.action, post_data, lock);
-
- this.ksearch_data.locks.push(lock);
- this.ksearch_data.requests.push(xhr);
- }
- }
- else if (!maxlen) {
- if (!this.ksearch_msg)
- this.ksearch_msg = this.display_message(this.get_label('autocompletemore'));
- // abort pending searches
- this.ksearch_abort();
- }
- }
+ if (this.ksearch_data.id == reqid)
+ this.ksearch_data.num--;
};
this.ksearch_click = function(node)
@@ -4553,7 +4641,8 @@ function rcube_webmail()
// Clears autocomplete data/requests
this.ksearch_destroy = function()
{
- this.ksearch_abort();
+ if (this.ksearch_data)
+ this.multi_thread_request_abort(this.ksearch_data.id);
if (this.ksearch_info)
this.hide_message(this.ksearch_info);
@@ -4564,18 +4653,6 @@ function rcube_webmail()
this.ksearch_data = null;
this.ksearch_info = null;
this.ksearch_msg = null;
- }
-
- // Aborts pending autocomplete requests
- this.ksearch_abort = function()
- {
- var i, len, ac = this.ksearch_data;
-
- if (!ac)
- return;
-
- for (i=0, len=ac.locks.length; i<len; i++)
- this.abort_request({request: ac.requests[i], lock: ac.locks[i]});
};
@@ -4594,7 +4671,7 @@ function rcube_webmail()
if (this.preview_timer)
clearTimeout(this.preview_timer);
- var n, id, sid, contact, ref = this, writable = false,
+ var n, id, sid, contact, writable = false,
source = this.env.source ? this.env.address_sources[this.env.source] : null;
// we don't have dblclick handler here, so use 200 instead of this.dblclick_time
@@ -5011,7 +5088,7 @@ function rcube_webmail()
this.init_contact_form = function()
{
- var ref = this, col;
+ var col;
if (this.env.coltypes) {
this.set_photo_actions($('#ff_photo').val());
@@ -5659,25 +5736,25 @@ function rcube_webmail()
this.init_subscription_list = function()
{
- var p = this, delim = RegExp.escape(this.env.delimiter);
+ var delim = RegExp.escape(this.env.delimiter);
this.last_sub_rx = RegExp('['+delim+']?[^'+delim+']+$');
this.subscription_list = new rcube_list_widget(this.gui_objects.subscriptionlist,
{multiselect:false, draggable:true, keyboard:false, toggleselect:true});
this.subscription_list
- .addEventListener('select', function(o){ p.subscription_select(o); })
- .addEventListener('dragstart', function(o){ p.drag_active = true; })
- .addEventListener('dragend', function(o){ p.subscription_move_folder(o); })
+ .addEventListener('select', function(o){ ref.subscription_select(o); })
+ .addEventListener('dragstart', function(o){ ref.drag_active = true; })
+ .addEventListener('dragend', function(o){ ref.subscription_move_folder(o); })
.addEventListener('initrow', function (row) {
- row.obj.onmouseover = function() { p.focus_subscription(row.id); };
- row.obj.onmouseout = function() { p.unfocus_subscription(row.id); };
+ row.obj.onmouseover = function() { ref.focus_subscription(row.id); };
+ row.obj.onmouseout = function() { ref.unfocus_subscription(row.id); };
})
.init();
$('#mailboxroot')
- .mouseover(function(){ p.focus_subscription(this.id); })
- .mouseout(function(){ p.unfocus_subscription(this.id); })
+ .mouseover(function(){ ref.focus_subscription(this.id); })
+ .mouseout(function(){ ref.unfocus_subscription(this.id); })
};
this.focus_subscription = function(id)
@@ -6221,8 +6298,7 @@ function rcube_webmail()
type = type ? type : 'notice';
- var ref = this,
- key = this.html_identifier(msg),
+ var key = this.html_identifier(msg),
date = new Date(),
id = type + date.getTime();
@@ -6429,18 +6505,18 @@ function rcube_webmail()
// for reordering column array (Konqueror workaround)
// and for setting some message list global variables
- this.set_message_coltypes = function(coltypes, repl, smart_col)
+ this.set_message_coltypes = function(listcols, repl, smart_col)
{
var list = this.message_list,
thead = list ? list.thead : null,
- cell, col, n, len, th, tr;
+ repl, cell, col, n, len, tr;
- this.env.coltypes = coltypes;
+ this.env.listcols = listcols;
// replace old column headers
if (thead) {
if (repl) {
- th = document.createElement('thead');
+ thead.innerHTML = '';
tr = document.createElement('tr');
for (c=0, len=repl.length; c < len; c++) {
@@ -6450,20 +6526,13 @@ function rcube_webmail()
if (repl[c].className) cell.className = repl[c].className;
tr.appendChild(cell);
}
- th.appendChild(tr);
- thead.parentNode.replaceChild(th, thead);
- list.thead = thead = th;
+ thead.appendChild(tr);
}
- for (n=0, len=this.env.coltypes.length; n<len; n++) {
- col = this.env.coltypes[n];
+ for (n=0, len=this.env.listcols.length; n<len; n++) {
+ col = this.env.listcols[n];
if ((cell = thead.rows[0].cells[n]) && (col == 'from' || col == 'to' || col == 'fromto')) {
- cell.id = 'rcm'+col;
- $('span,a', cell).text(this.get_label(col == 'fromto' ? smart_col : col));
- // if we have links for sorting, it's a bit more complicated...
- $('a', cell).click(function(){
- return rcmail.command('sort', this.id.replace(/^rcm/, ''), this);
- });
+ $(cell).attr('rel', col).find('span,a').text(this.get_label(col == 'fromto' ? smart_col : col));
}
}
}
@@ -6472,18 +6541,23 @@ function rcube_webmail()
this.env.flagged_col = null;
this.env.status_col = null;
- if ((n = $.inArray('subject', this.env.coltypes)) >= 0) {
+ if (this.env.coltypes.folder)
+ this.env.coltypes.folder.hidden = !(this.env.search_request || this.env.search_id) || this.env.search_scope == 'base';
+
+ if ((n = $.inArray('subject', this.env.listcols)) >= 0) {
this.env.subject_col = n;
if (list)
list.subject_col = n;
}
- if ((n = $.inArray('flag', this.env.coltypes)) >= 0)
+ if ((n = $.inArray('flag', this.env.listcols)) >= 0)
this.env.flagged_col = n;
- if ((n = $.inArray('status', this.env.coltypes)) >= 0)
+ if ((n = $.inArray('status', this.env.listcols)) >= 0)
this.env.status_col = n;
- if (list)
+ if (list) {
+ list.hide_column('folder', (this.env.coltypes.folder && this.env.coltypes.folder.hidden) || $.inArray('folder', this.env.listcols) < 0);
list.init_header();
+ }
};
// replace content of row count display
@@ -6612,8 +6686,9 @@ function rcube_webmail()
// fetch headers only once
if (!this.gui_objects.all_headers_box.innerHTML) {
- var lock = this.display_message(this.get_label('loading'), 'loading');
- this.http_post('headers', {_uid: this.env.uid}, lock);
+ this.http_post('headers', {_uid: this.env.uid, _mbox: this.env.mailbox},
+ this.display_message(this.get_label('loading'), 'loading')
+ );
}
};
@@ -6742,15 +6817,14 @@ function rcube_webmail()
this.html2plain = function(htmlText, id)
{
- var rcmail = this,
- url = '?_task=utils&_action=html2text',
+ var url = '?_task=utils&_action=html2text',
lock = this.set_busy(true, 'converting');
this.log('HTTP POST: ' + url);
$.ajax({ type: 'POST', url: url, data: htmlText, contentType: 'application/octet-stream',
- error: function(o, status, err) { rcmail.http_error(o, status, err, lock); },
- success: function(data) { rcmail.set_busy(false, null, lock); $('#'+id).val(data); rcmail.log(data); }
+ error: function(o, status, err) { ref.http_error(o, status, err, lock); },
+ success: function(data) { ref.set_busy(false, null, lock); $('#'+id).val(data); ref.log(data); }
});
};
@@ -6781,13 +6855,13 @@ function rcube_webmail()
if (action)
query._action = action;
- else
+ else if (this.env.action)
query._action = this.env.action;
var base = this.env.comm_path, k, param = {};
// overwrite task name
- if (query._action.match(/([a-z0-9_-]+)\/([a-z0-9-_.]+)/)) {
+ if (action && action.match(/([a-z0-9_-]+)\/([a-z0-9-_.]+)/)) {
query._action = RegExp.$2;
base = base.replace(/\_task=[a-z0-9_-]+/, '_task='+RegExp.$1);
}
@@ -6798,7 +6872,7 @@ function rcube_webmail()
param[k] = query[k];
}
- return base + '&' + $.param(param) + querystring;
+ return base + (base.indexOf('?') > -1 ? '&' : '?') + $.param(param) + querystring;
};
this.redirect = function(url, lock)
@@ -6822,7 +6896,7 @@ function rcube_webmail()
this.goto_url = function(action, query, lock)
{
- this.redirect(this.url(action, query));
+ this.redirect(this.url(action, query), lock);
};
this.location_href = function(url, target, frame)
@@ -7019,10 +7093,13 @@ function rcube_webmail()
this.env.qsearch = null;
case 'list':
if (this.task == 'mail') {
+ var is_multifolder = this.is_multifolder_listing();
this.enable_command('show', 'select-all', 'select-none', this.env.messagecount > 0);
- this.enable_command('expunge', this.env.exists);
- this.enable_command('purge', this.purge_mailbox_test());
- this.enable_command('expand-all', 'expand-unread', 'collapse-all', this.env.threading && this.env.messagecount);
+ this.enable_command('expunge', this.env.exists && !is_multifolder);
+ this.enable_command('purge', this.purge_mailbox_test() && !is_multifolder);
+ this.enable_command('import-messages', !is_multifolder);
+ this.enable_command('expand-all', 'expand-unread', 'collapse-all', this.env.threading && this.env.messagecount && !is_multifolder);
+ this.enable_command('set-listmode', this.env.threads && !is_multifolder);
if ((response.action == 'list' || response.action == 'search') && this.message_list) {
this.msglist_select(this.message_list);
@@ -7069,7 +7146,7 @@ function rcube_webmail()
else if (status == 'timeout')
this.display_message(this.get_label('requesttimedout'), 'error');
else if (request.status == 0 && status != 'abort')
- this.display_message(this.get_label('servererror') + ' (No connection)', 'error');
+ this.display_message(this.get_label('connerror'), 'error');
// redirect to url specified in location header if not empty
var location_url = request.getResponseHeader("Location");
@@ -7112,6 +7189,130 @@ function rcube_webmail()
clearTimeout(this.submit_timer);
};
+ /**
+ Send multi-threaded parallel HTTP requests to the server for a list if items.
+ The string '%' in either a GET query or POST parameters will be replaced with the respective item value.
+ This is the argument object expected: {
+ items: ['foo','bar','gna'], // list of items to send requests for
+ action: 'task/some-action', // Roudncube action to call
+ query: { q:'%s' }, // GET query parameters
+ postdata: { source:'%s' }, // POST data (sends a POST request if present)
+ threads: 3, // max. number of concurrent requests
+ onresponse: function(data){ }, // Callback function called for every response received from server
+ whendone: function(alldata){ } // Callback function called when all requests have been sent
+ }
+ */
+ this.multi_thread_http_request = function(prop)
+ {
+ var i, item, reqid = new Date().getTime(),
+ threads = prop.threads || 1;
+
+ prop.reqid = reqid;
+ prop.running = 0;
+ prop.requests = [];
+ prop.result = [];
+ prop._items = $.extend([], prop.items); // copy items
+
+ if (!prop.lock)
+ prop.lock = this.display_message(this.get_label('loading'), 'loading');
+
+ // add the request arguments to the jobs pool
+ this.http_request_jobs[reqid] = prop;
+
+ // start n threads
+ for (i=0; i < threads; i++) {
+ item = prop._items.shift();
+ if (item === undefined)
+ break;
+
+ prop.running++;
+ prop.requests.push(this.multi_thread_send_request(prop, item));
+ }
+
+ return reqid;
+ };
+
+ // helper method to send an HTTP request with the given iterator value
+ this.multi_thread_send_request = function(prop, item)
+ {
+ var postdata, query;
+
+ // replace %s in post data
+ if (prop.postdata) {
+ postdata = {};
+ for (var k in prop.postdata) {
+ postdata[k] = String(prop.postdata[k]).replace('%s', item);
+ }
+ postdata._reqid = prop.reqid;
+ }
+ // replace %s in query
+ else if (typeof prop.query == 'string') {
+ query = prop.query.replace('%s', item);
+ query += '&_reqid=' + prop.reqid;
+ }
+ else if (typeof prop.query == 'object' && prop.query) {
+ query = {};
+ for (var k in prop.query) {
+ query[k] = String(prop.query[k]).replace('%s', item);
+ }
+ query._reqid = prop.reqid;
+ }
+
+ // send HTTP GET or POST request
+ return postdata ? this.http_post(prop.action, postdata) : this.http_request(prop.action, query);
+ };
+
+ // callback function for multi-threaded http responses
+ this.multi_thread_http_response = function(data, reqid)
+ {
+ var prop = this.http_request_jobs[reqid];
+ if (!prop || prop.running <= 0 || prop.cancelled)
+ return;
+
+ prop.running--;
+
+ // trigger response callback
+ if (prop.onresponse && typeof prop.onresponse == 'function') {
+ prop.onresponse(data);
+ }
+
+ prop.result = $.extend(prop.result, data);
+
+ // send next request if prop.items is not yet empty
+ var item = prop._items.shift();
+ if (item !== undefined) {
+ prop.running++;
+ prop.requests.push(this.multi_thread_send_request(prop, item));
+ }
+ // trigger whendone callback and mark this request as done
+ else if (prop.running == 0) {
+ if (prop.whendone && typeof prop.whendone == 'function') {
+ prop.whendone(prop.result);
+ }
+
+ this.set_busy(false, '', prop.lock);
+
+ // remove from this.http_request_jobs pool
+ delete this.http_request_jobs[reqid];
+ }
+ };
+
+ // abort a running multi-thread request with the given identifier
+ this.multi_thread_request_abort = function(reqid)
+ {
+ var prop = this.http_request_jobs[reqid];
+ if (prop) {
+ for (var i=0; prop.running > 0 && i < prop.requests.length; i++) {
+ if (prop.requests[i].abort)
+ prop.requests[i].abort();
+ }
+
+ prop.running = 0;
+ prop.cancelled = true;
+ this.set_busy(false, '', prop.lock);
+ }
+ };
+
// post the given form to a hidden iframe
this.async_upload_form = function(form, action, onload)
{
@@ -7327,7 +7528,7 @@ function rcube_webmail()
this.env.lastrefresh = new Date();
// plugins should bind to 'requestrefresh' event to add own params
- this.http_request('refresh', params, lock);
+ this.http_post('refresh', params, lock);
};
// returns check-recent request parameters
@@ -7389,6 +7590,13 @@ function rcube_webmail()
return this.env.cid ? this.env.cid : (this.contact_list ? this.contact_list.get_single_selection() : null);
};
+ // get the IMP mailbox of the message with the given UID
+ this.get_message_mailbox = function(uid)
+ {
+ var msg = this.env.messages ? this.env.messages[uid] : {};
+ return msg.mbox || this.env.mailbox;
+ }
+
// gets cursor position
this.get_caret_pos = function(obj)
{
@@ -7650,7 +7858,6 @@ function rcube_webmail()
// wrapper for localStorage.getItem(key)
this.local_storage_get_item = function(key, deflt, encrypted)
{
-
// TODO: add encryption
var item = localStorage.getItem(this.get_local_storage_prefix() + key);
return item !== null ? JSON.parse(item) : (deflt || null);
@@ -7677,12 +7884,12 @@ rcube_webmail.long_subject_title = function(elem, indent)
{
if (!elem.title) {
var $elem = $(elem);
- if ($elem.width() + indent * 15 > $elem.parent().width())
+ if ($elem.width() + (indent || 0) * 15 > $elem.parent().width())
elem.title = $elem.text();
}
};
-rcube_webmail.long_subject_title_ex = function(elem, indent)
+rcube_webmail.long_subject_title_ex = function(elem)
{
if (!elem.title) {
var $elem = $(elem),
@@ -7694,7 +7901,7 @@ rcube_webmail.long_subject_title_ex = function(elem, indent)
w = tmp.width();
tmp.remove();
- if (w + indent * 15 > $elem.width())
+ if (w + $('span.branch', $elem).width() * 15 > $elem.width())
elem.title = txt;
}
};