| | |
| | | /* |
| | | +-----------------------------------------------------------------------+ |
| | | | Roundcube Webmail Client Script | |
| | | | | |
| | | | This file is part of the Roundcube Webmail client | |
| | | | 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. | |
| | | | See the README file for a full license statement. | |
| | | | | |
| | | +-----------------------------------------------------------------------+ |
| | | | Authors: Thomas Bruederli <roundcube@gmail.com> | |
| | | | Aleksander 'A.L.E.C' Machniak <alec@alec.pl> | |
| | | | Charles McNulty <charles@charlesmcnulty.com> | |
| | | +-----------------------------------------------------------------------+ |
| | | | Requires: jquery.js, common.js, list.js | |
| | | +-----------------------------------------------------------------------+ |
| | | */ |
| | | /** |
| | | * Roundcube Webmail Client Script |
| | | * |
| | | * This file is part of the Roundcube Webmail client |
| | | * |
| | | * @licstart The following is the entire license notice for the |
| | | * JavaScript code in this file. |
| | | * |
| | | * Copyright (C) 2005-2014, The Roundcube Dev Team |
| | | * Copyright (C) 2011-2014, Kolab Systems AG |
| | | * |
| | | * The JavaScript code in this page is free software: you can |
| | | * redistribute it and/or modify it under the terms of the GNU |
| | | * General Public License (GNU GPL) as published by the Free Software |
| | | * Foundation, either version 3 of the License, or (at your option) |
| | | * any later version. The code is distributed WITHOUT ANY WARRANTY; |
| | | * without even the implied warranty of MERCHANTABILITY or FITNESS |
| | | * FOR A PARTICULAR PURPOSE. See the GNU GPL for more details. |
| | | * |
| | | * As additional permission under GNU GPL version 3 section 7, you |
| | | * may distribute non-source (e.g., minimized or compacted) forms of |
| | | * that code without the copy of the GNU GPL normally required by |
| | | * section 4, provided you include this license notice and a URL |
| | | * through which recipients can access the Corresponding Source. |
| | | * |
| | | * @licend The above is the entire license notice |
| | | * for the JavaScript code in this file. |
| | | * |
| | | * @author Thomas Bruederli <roundcube@gmail.com> |
| | | * @author Aleksander 'A.L.E.C' Machniak <alec@alec.pl> |
| | | * @author Charles McNulty <charles@charlesmcnulty.com> |
| | | * |
| | | * @requires jquery.js, common.js, list.js |
| | | */ |
| | | |
| | | 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; |
| | | } |
| | |
| | | |
| | | // enable general commands |
| | | this.enable_command('close', 'logout', 'mail', 'addressbook', 'settings', 'save-pref', |
| | | 'compose', 'undo', 'about', 'switch-task', 'menu-open', 'menu-save', true); |
| | | 'compose', 'undo', 'about', 'switch-task', 'menu-open', 'menu-close', 'menu-save', true); |
| | | |
| | | // set active task button |
| | | this.set_button(this.task, 'sel'); |
| | | |
| | | if (this.env.permaurl) |
| | | this.enable_command('permaurl', 'extwin', true); |
| | |
| | | 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(); |
| | | |
| | | // 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); |
| | | return ref.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); }; |
| | | document.onmouseup = function(e){ return ref.doc_mouse_up(e); }; |
| | | this.gui_objects.messagelist.parentNode.onclick = function(e){ return ref.click_on_list(e || window.event); }; |
| | | |
| | | this.enable_command('toggle_status', 'toggle_flag', 'sort', true); |
| | | this.enable_command('set-listmode', this.env.threads && !this.is_multifolder_listing()); |
| | |
| | | } |
| | | } |
| | | |
| | | 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(); |
| | |
| | | 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(); |
| | |
| | | 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'); |
| | |
| | | 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(); |
| | | |
| | |
| | | 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(); |
| | | } |
| | |
| | | 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() |
| | |
| | | $('#rcmloginpwd').focus(); |
| | | |
| | | // detect client timezone |
| | | if (window.jstz && !bw.ie6) { |
| | | if (window.jstz) { |
| | | var timezone = jstz.determine(); |
| | | if (timezone.name()) |
| | | $('#rcmlogintz').val(timezone.name()); |
| | |
| | | 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) |
| | |
| | | // remove copy from local storage if compose screen is left intentionally |
| | | this.remove_compose_data(this.env.compose_id); |
| | | } |
| | | |
| | | this.last_command = command; |
| | | |
| | | // process external commands |
| | | if (typeof this.command_handlers[command] === 'function') { |
| | |
| | | } |
| | | |
| | | case 'menu-save': |
| | | this.triggerEvent(command, {props:props}); |
| | | case 'menu-close': |
| | | this.triggerEvent(command, {props:props, originalEvent:event}); |
| | | return false; |
| | | |
| | | case 'open': |
| | |
| | | // 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; |
| | |
| | | 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; |
| | |
| | | } |
| | | } |
| | | }; |
| | | |
| | | this.command_enabled = function(cmd) |
| | | { |
| | | return this.commands[cmd]; |
| | | } |
| | | |
| | | // lock/unlock interface |
| | | this.set_busy = function(a, message, id) |
| | |
| | | this.gui_objects.qsearchbox.blur(); |
| | | |
| | | if (this.message_list) |
| | | this.message_list.focus(); |
| | | this.message_list.focus(e); |
| | | else if (this.contact_list) |
| | | this.contact_list.focus(); |
| | | this.contact_list.focus(e); |
| | | |
| | | return true; |
| | | }; |
| | |
| | | |
| | | this.init_message_row = function(row) |
| | | { |
| | | var i, fn = {}, self = this, uid = 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]) |
| | |
| | | |
| | | // 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 |
| | |
| | | |
| | | // set eventhandler to flag icon |
| | | if (this.env.flagged_col != null && (row.flagicon = document.getElementById('flagicn'+row.id))) { |
| | | fn.flagicon = function(e) { self.command('toggle_flag', uid); }; |
| | | 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.id))) { |
| | | fn.expando = function(e) { self.expand_message_row(e, uid); }; |
| | | fn.expando = function(e) { ref.expand_message_row(e, uid); }; |
| | | } |
| | | |
| | | // attach events |
| | |
| | | |
| | | // 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+'='+urlencode(uid)+'"'+ |
| | | ' onclick="return rcube_event.cancel(event)" onmouseover="rcube_webmail.long_subject_title(this,'+(message.depth+1)+')"><span>'+cols.subject+'</span></a>'; |
| | | var action = flags.mbox == this.env.drafts_mailbox ? 'compose' : 'show', |
| | | uid_param = flags.mbox == this.env.drafts_mailbox ? '_draft_uid' : '_uid', |
| | | query = { _mbox: flags.mbox }; |
| | | query[uid_param] = uid; |
| | | cols.subject = '<a href="' + this.url(action, query) + '" onclick="return rcube_event.keyboard_only(event)"' + |
| | | ' onmouseover="rcube_webmail.long_subject_title(this,'+(message.depth+1)+')" tabindex="-1"><span>'+cols.subject+'</span></a>'; |
| | | } |
| | | |
| | | // add each submitted col |
| | | for (n in this.env.listcols) { |
| | | c = this.env.listcols[n]; |
| | | col = { className: String(c).toLowerCase() }; |
| | | col = {className: String(c).toLowerCase(), events:{}}; |
| | | |
| | | if (this.env.coltypes[c] && this.env.coltypes[c].hidden) { |
| | | col.className += ' hidden'; |
| | |
| | | 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') { |
| | |
| | | html = '<span class="prio'+flags.prio+'"> </span>'; |
| | | else |
| | | html = ' '; |
| | | } |
| | | else if (c == 'folder') { |
| | | html = '<span onmouseover="rcube_webmail.long_subject_title(this)">' + cols[c] + '<span>'; |
| | | } |
| | | else |
| | | html = cols[c]; |
| | |
| | | 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 |
| | |
| | | |
| | | // reset vars |
| | | this.env.current_page = 1; |
| | | this.env.search_filter = filter; |
| | | this.http_request('search', this.search_params(false, filter), lock); |
| | | }; |
| | | |
| | |
| | | url._page = page; |
| | | |
| | | this.http_request('list', url, lock); |
| | | this.update_state({ _mbox: mbox, _page: (page && page > 1 ? page : null) }); |
| | | }; |
| | | |
| | | // removes messages that doesn't exists from list selection array |
| | |
| | | // 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()) { |
| | |
| | | $('<a>').addClass('insertresponse active') |
| | | .attr('href', '#') |
| | | .attr('rel', key) |
| | | .attr('tabindex', '0') |
| | | .html(this.quote_html(response.name)) |
| | | .appendTo(li) |
| | | .mousedown(function(e){ |
| | |
| | | $("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) { |
| | |
| | | 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'); |
| | |
| | | this.upload_file = function(form, action) |
| | | { |
| | | if (!form) |
| | | return false; |
| | | return; |
| | | |
| | | // count files and size on capable browser |
| | | var size = 0, numfiles = 0; |
| | |
| | | this.gui_objects.attachmentform = form; |
| | | return true; |
| | | } |
| | | |
| | | return false; |
| | | }; |
| | | |
| | | // add file name to attachment list |
| | |
| | | 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.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 |
| | |
| | | |
| | | // re-send search query with new scope |
| | | if (scope != old && this.env.search_request) { |
| | | this.qsearch(this.gui_objects.qsearchbox.value); |
| | | if (scope == 'base') |
| | | 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); |
| | | } |
| | | }; |
| | |
| | | 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 |
| | |
| | | |
| | | this.init_contact_form = function() |
| | | { |
| | | var ref = this, col; |
| | | var col; |
| | | |
| | | if (this.env.coltypes) { |
| | | this.set_photo_actions($('#ff_photo').val()); |
| | |
| | | |
| | | 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) |
| | |
| | | init_button(cmd, this.buttons[cmd][i]); |
| | | } |
| | | } |
| | | |
| | | // set active task button |
| | | this.set_button(this.task, 'sel'); |
| | | }; |
| | | |
| | | // set button to a specific state |
| | |
| | | button = a_buttons[n]; |
| | | obj = document.getElementById(button.id); |
| | | |
| | | if (!obj) |
| | | if (!obj || button.status == state) |
| | | continue; |
| | | |
| | | // get default/passive setting of the button |
| | |
| | | obj.disabled = state == 'pas'; |
| | | } |
| | | else if (button.type == 'uibutton') { |
| | | button.status = state; |
| | | $(obj).button('option', 'disabled', state == 'pas'); |
| | | } |
| | | else { |
| | | $(obj) |
| | | .attr('tabindex', state == 'pas' || state == 'sel' ? '-1' : '0') |
| | | .attr('aria-disabled', state == 'pas' || state == 'sel' ? 'true' : 'false'); |
| | | } |
| | | } |
| | | }; |
| | |
| | | |
| | | 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(); |
| | | |
| | |
| | | this.messages[key].labels = [{'id': id, 'msg': msg}]; |
| | | } |
| | | else { |
| | | obj.click(function() { return ref.hide_message(obj); }); |
| | | obj.click(function() { return ref.hide_message(obj); }) |
| | | .attr('role', 'alert'); |
| | | } |
| | | |
| | | this.triggerEvent('message', { message:msg, type:type, timeout:timeout, object:obj }); |
| | |
| | | |
| | | // 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') |
| | | ); |
| | | } |
| | | }; |
| | | |
| | |
| | | |
| | | 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); } |
| | | }); |
| | | }; |
| | | |
| | |
| | | |
| | | 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); |
| | | } |
| | |
| | | param[k] = query[k]; |
| | | } |
| | | |
| | | return base + '&' + $.param(param) + querystring; |
| | | return base + (base.indexOf('?') > -1 ? '&' : '?') + $.param(param) + querystring; |
| | | }; |
| | | |
| | | this.redirect = function(url, lock) |
| | |
| | | |
| | | // reset keep-alive interval |
| | | this.start_keepalive(); |
| | | }; |
| | | |
| | | // update browser location to remember current view |
| | | this.update_state = function(query) |
| | | { |
| | | if (window.history.replaceState) |
| | | window.history.replaceState({}, document.title, rcmail.url('', query)); |
| | | }; |
| | | |
| | | // send a http request to the server |
| | |
| | | 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('set-listmode', this.env.threads && !this.is_multifolder_listing()); |
| | | 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.message_list.focus(); |
| | | this.msglist_select(this.message_list); |
| | | this.triggerEvent('listupdate', { folder:this.env.mailbox, rowcount:this.message_list.rowcount }); |
| | | } |
| | |
| | | */ |
| | | this.multi_thread_http_request = function(prop) |
| | | { |
| | | var reqid = new Date().getTime(); |
| | | var i, item, reqid = new Date().getTime(), |
| | | threads = prop.threads || 1; |
| | | |
| | | prop.reqid = reqid; |
| | | prop.running = 0; |
| | |
| | | this.http_request_jobs[reqid] = prop; |
| | | |
| | | // start n threads |
| | | var item, threads = prop.threads || 1; |
| | | for (var i=0; i < threads; i++) { |
| | | for (i=0; i < threads; i++) { |
| | | item = prop._items.shift(); |
| | | if (item === undefined) |
| | | break; |
| | |
| | | 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 |
| | |
| | | // 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); |
| | |
| | | { |
| | | 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), |
| | |
| | | w = tmp.width(); |
| | | |
| | | tmp.remove(); |
| | | if (w + indent * 15 > $elem.width()) |
| | | if (w + $('span.branch', $elem).width() * 15 > $elem.width()) |
| | | elem.title = txt; |
| | | } |
| | | }; |