| | |
| | | | 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. | |
| | |
| | | this.task = this.env.task; |
| | | |
| | | // check browser |
| | | if (!bw.dom || !bw.xmlhttp_test() || (bw.mz && bw.vendver < 1.9)) { |
| | | if (!bw.dom || !bw.xmlhttp_test() || (bw.mz && bw.vendver < 1.9) || (bw.ie && bw.vendver < 7)) { |
| | | this.goto_url('error', '_code=0x199'); |
| | | return; |
| | | } |
| | |
| | | .addEventListener('listupdate', function(o) { p.triggerEvent('listupdate', o); }) |
| | | .init(); |
| | | |
| | | // TODO: this should go into the list-widget code |
| | | $(this.message_list.thead).on('click', 'a.sortcol', function(e){ |
| | | return rcmail.command('sort', $(this).attr('rel'), this); |
| | | }); |
| | | |
| | | document.onmouseup = function(e){ return p.doc_mouse_up(e); }; |
| | | this.gui_objects.messagelist.parentNode.onmousedown = function(e){ return p.click_on_list(e); }; |
| | | |
| | | this.enable_command('toggle_status', 'toggle_flag', 'sort', true); |
| | | this.enable_command('set-listmode', this.env.threads && !this.env.search_request); |
| | | this.enable_command('set-listmode', this.env.threads && !this.is_multifolder_listing()); |
| | | |
| | | // load messages |
| | | this.command('list'); |
| | |
| | | $('#rcmloginpwd').focus(); |
| | | |
| | | // detect client timezone |
| | | if (window.jstz && !bw.ie6) { |
| | | if (window.jstz) { |
| | | var timezone = jstz.determine(); |
| | | if (timezone.name()) |
| | | $('#rcmlogintz').val(timezone.name()); |
| | |
| | | break; |
| | | |
| | | case 'list': |
| | | // re-send for the selected folder |
| | | if (props && props != '' && this.env.search_request) { |
| | | // 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 = 'base'; |
| | | this.env.search_scope = 'sub'; |
| | | this.qsearch(this.gui_objects.qsearchbox.value); |
| | | this.select_folder(this.env.mailbox, '', true); |
| | | break; |
| | |
| | | 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); |
| | |
| | | { |
| | | 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; |
| | |
| | | } |
| | | |
| | | // 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'+row.id+'" class="'+css_class+'"> </span>'; |
| | | } |
| | | else if (c == 'attachment') { |
| | | if (/application\/|multipart\/(m|signed)/.test(flags.ctype)) |
| | | if (flags.attachmentClass) |
| | | html = '<span class="'+flags.attachmentClass+'"> </span>'; |
| | | else if (/application\/|multipart\/(m|signed)/.test(flags.ctype)) |
| | | html = '<span class="attachment"> </span>'; |
| | | else if (/multipart\/report/.test(flags.ctype)) |
| | | html = '<span class="report"> </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') { |
| | |
| | | |
| | | 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); |
| | |
| | | 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 |
| | |
| | | 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; |
| | | |
| | |
| | | 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) { |
| | |
| | | }; |
| | | |
| | | // 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 |
| | |
| | | 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}); |
| | |
| | | // @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) { |
| | |
| | | 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++) { |
| | |
| | | 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'; |
| | |
| | | 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]; |
| | |
| | | // 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 |
| | |
| | | $("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 |
| | |
| | | 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) { |
| | |
| | | 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))) { |
| | |
| | | |
| | | 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) { |
| | | this.qsearch(this.gui_objects.qsearchbox.value); |
| | | if (scope == 'base') |
| | | 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) |
| | | { |
| | |
| | | |
| | | // 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++) { |
| | |
| | | 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)); |
| | | } |
| | | } |
| | | } |
| | |
| | | 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) { |
| | | list.hide_column('folder', !(this.env.search_request || this.env.search_id) || this.env.search_scope == 'base'); |
| | | list.hide_column('folder', (this.env.coltypes.folder && this.env.coltypes.folder.hidden) || $.inArray('folder', this.env.listcols) < 0); |
| | | list.init_header(); |
| | | } |
| | | }; |
| | |
| | | |
| | | 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); |
| | | } |
| | |
| | | |
| | | 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) |
| | |
| | | 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('set-listmode', this.env.threads && !this.is_multifolder_listing()); |
| | | |
| | | if ((response.action == 'list' || response.action == 'search') && this.message_list) { |
| | | this.msglist_select(this.message_list); |
| | |
| | | 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 |
| | |
| | | } |
| | | }; |
| | | |
| | | rcube_webmail.long_subject_title_ex = function(elem, indent) |
| | | rcube_webmail.long_subject_title_ex = function(elem) |
| | | { |
| | | if (!elem.title) { |
| | | var $elem = $(elem), |
| | |
| | | w = tmp.width(); |
| | | |
| | | tmp.remove(); |
| | | if (w + indent * 15 > $elem.width()) |
| | | if (w + $('span.branch', $elem).width() * 15 > $elem.width()) |
| | | elem.title = txt; |
| | | } |
| | | }; |