From d61d668b64c44fc046095b807834c4836a8c05c5 Mon Sep 17 00:00:00 2001 From: Aleksander Machniak <alec@alec.pl> Date: Wed, 08 Apr 2015 02:57:21 -0400 Subject: [PATCH] Remove useless code --- program/js/app.js | 452 +++++++++++++++++++++++++++++++++++++++++--------------- 1 files changed, 331 insertions(+), 121 deletions(-) diff --git a/program/js/app.js b/program/js/app.js index 9dca320..1da2a81 100644 --- a/program/js/app.js +++ b/program/js/app.js @@ -58,7 +58,6 @@ request_timeout: 180, // seconds draft_autosave: 0, // seconds comm_path: './', - blankpage: 'program/resources/blank.gif', recipients_separator: ',', recipients_delimiter: ', ', popup_width: 1150, @@ -162,6 +161,9 @@ this.goto_url('error', '_code=0x199'); return; } + + if (!this.env.blankpage) + this.env.blankpage = this.assets_path('program/resources/blank.gif'); // find all registered gui containers for (n in this.gui_containers) @@ -324,10 +326,7 @@ this.enable_command('download', 'print', true); // show printing dialog else if (this.env.action == 'print' && this.env.uid) { - if (bw.safari) - setTimeout('window.print()', 10); - else - window.print(); + this.print_dialog(); } // get unread count for each mailbox @@ -437,6 +436,9 @@ this.enable_command('save', true); if (this.env.action == 'add' || this.env.action == 'edit' || this.env.action == 'search') this.init_contact_form(); + } + else if (this.env.action == 'print') { + this.print_dialog(); } break; @@ -556,7 +558,7 @@ // show message if (this.pending_message) - this.display_message(this.pending_message[0], this.pending_message[1], this.pending_message[2]); + this.display_message.apply(this, this.pending_message); // init treelist widget if (this.gui_objects.folderlist && window.rcube_treelist_widget) { @@ -572,6 +574,7 @@ this.treelist .addEventListener('collapse', function(node) { ref.folder_collapsed(node) }) .addEventListener('expand', function(node) { ref.folder_collapsed(node) }) + .addEventListener('beforeselect', function(node) { return !ref.busy; }) .addEventListener('select', function(node) { ref.triggerEvent('selectfolder', { folder:node.id, prefix:'rcmli' }) }); } @@ -630,8 +633,9 @@ if (obj && obj.blur && !(event && rcube_event.is_keyboard(event))) obj.blur(); - // do nothing if interface is locked by other command (with exception for searching reset) - if (this.busy && !(command == 'reset-search' && this.last_command == 'search')) + // do nothing if interface is locked by another command + // with exception for searching reset and menu + if (this.busy && !(command == 'reset-search' && this.last_command == 'search') && !command.match(/^menu-/)) return false; // let the browser handle this click (shift/ctrl usually opens the link in a new window/tab) @@ -650,7 +654,7 @@ // check input before leaving compose step if (this.task == 'mail' && this.env.action == 'compose' && $.inArray(command, this.env.compose_commands) < 0 && !this.env.server_error) { - if (this.cmp_hash != this.compose_field_hash() && !confirm(this.get_label('notsentwarning'))) + if (!this.env.is_sent && this.cmp_hash != this.compose_field_hash() && !confirm(this.get_label('notsentwarning'))) return false; // remove copy from local storage if compose screen is left intentionally @@ -770,7 +774,7 @@ case 'list': if (props && props != '') { - this.reset_qsearch(); + this.reset_qsearch(true); } if (this.env.action == 'compose' && this.env.extwin) { window.close(); @@ -890,7 +894,7 @@ else { // reload form if (props == 'reload') { - form.action += '?_reload=1'; + form.action += '&_reload=1'; } else if (this.task == 'settings' && (this.env.identities_level % 2) == 0 && (input = $("input[name='_email']", form)) && input.length && !rcube_check_email(input.val()) @@ -1051,12 +1055,9 @@ url = {}; if (this.task == 'mail') { - url._mbox = this.env.mailbox; + url = {_mbox: this.env.mailbox, _search: this.env.search_request}; if (props) url._to = props; - // also send search request so we can go back to search result after message is sent - if (this.env.search_request) - url._search = this.env.search_request; } // modify url if we're in addressbook else if (this.task == 'addressbook') { @@ -1114,7 +1115,7 @@ break; case 'send': - if (!props.nocheck && !this.check_compose_input(command)) + if (!props.nocheck && !this.env.is_sent && !this.check_compose_input(command)) break; // Reset the auto-save timer @@ -1151,7 +1152,7 @@ case 'reply-list': case 'reply': if (uid = this.get_single_uid()) { - url = {_reply_uid: uid, _mbox: this.get_message_mailbox(uid)}; + url = {_reply_uid: uid, _mbox: this.get_message_mailbox(uid), _search: this.env.search_request}; 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'); @@ -1175,7 +1176,15 @@ break; case 'print': - if (this.env.action == 'get') { + if (this.task == 'addressbook') { + if (uid = this.contact_list.get_single_selection()) { + url = '&_action=print&_cid=' + uid; + if (this.env.source) + url += '&_source=' + urlencode(this.env.source); + this.open_window(this.env.comm_path + url, true, true); + } + } + else if (this.env.action == 'get') { this.gui_objects.messagepartframe.contentWindow.print(); } else if (uid = this.get_single_uid()) { @@ -1214,7 +1223,7 @@ case 'reset-search': var n, s = this.env.search_request || this.env.qsearch; - this.reset_qsearch(); + this.reset_qsearch(true); this.select_all_mode = false; if (s && this.env.action == 'compose') { @@ -1405,8 +1414,10 @@ if (task == 'mail') url += '&_mbox=INBOX'; - else if (task == 'logout' && !this.env.server_error) + else if (task == 'logout' && !this.env.server_error) { + url += '&_token=' + this.env.request_token; this.clear_compose_data(); + } this.redirect(url); }; @@ -1416,7 +1427,10 @@ if (!url) url = this.env.comm_path; - return url.replace(/_task=[a-z0-9_-]+/i, '_task='+task); + if (url.match(/[?&]_task=[a-zA-Z0-9_-]+/)) + return url.replace(/_task=[a-zA-Z0-9_-]+/, '_task=' + task); + else + return url.replace(/\?.*$/, '') + '?_task=' + task; }; this.reload = function(delay) @@ -1593,7 +1607,8 @@ this.folder_collapsed = function(node) { - var prefname = this.env.task == 'addressbook' ? 'collapsed_abooks' : 'collapsed_folders'; + var prefname = this.env.task == 'addressbook' ? 'collapsed_abooks' : 'collapsed_folders', + old = this.env[prefname]; if (node.collapsed) { this.env[prefname] = this.env[prefname] + '&'+urlencode(node.id)+'&'; @@ -1609,7 +1624,8 @@ } if (!this.drag_active) { - this.command('save-pref', { name: prefname, value: this.env[prefname] }); + if (old !== this.env[prefname]) + this.command('save-pref', { name: prefname, value: this.env[prefname] }); if (this.env.unread_counts) this.set_unread_count_display(node.id, false); @@ -1947,7 +1963,7 @@ // attach events $.each(fn, function(i, f) { row[i].onclick = function(e) { f(e); return rcube_event.cancel(e); }; - if (bw.touch) { + if (bw.touch && row[i].addEventListener) { row[i].addEventListener('touchend', function(e) { if (e.changedTouches.length == 1) { f(e); @@ -2027,7 +2043,7 @@ } if (flags.forwarded) { status_class += ' forwarded'; - status_label += this.get_label('replied') + ' '; + status_label += this.get_label('forwarded') + ' '; } // update selection @@ -2251,7 +2267,7 @@ if (preview && this.message_list && this.message_list.rows[id] && this.message_list.rows[id].unread && this.env.preview_pane_mark_read > 0) { this.preview_read_timer = setTimeout(function() { ref.set_unread_message(id, ref.env.mailbox); - ref.http_post('mark', {_uid: id, _flag: 'read', _quiet: 1}); + ref.http_post('mark', {_uid: id, _flag: 'read', _mbox: ref.env.mailbox, _quiet: 1}); }, this.env.preview_pane_mark_read * 1000); } } @@ -2361,6 +2377,9 @@ // list messages of a specific mailbox using filter this.filter_mailbox = function(filter) { + if (this.filter_disabled) + return; + var lock = this.set_busy(true, 'searching'); this.clear_message_list(); @@ -2394,16 +2413,17 @@ if (sort) url._sort = sort; - // also send search request to get the right messages - if (this.env.search_request) - url._search = this.env.search_request; - - // set page=1 if changeing to another mailbox + // folder change, reset page, search scope, etc. if (this.env.mailbox != mbox) { page = 1; this.env.current_page = page; + this.env.search_scope = 'base'; this.select_all_mode = false; + this.reset_search_filter(); } + // also send search request to get the right messages + else if (this.env.search_request) + url._search = this.env.search_request; if (!update_only) { // unselect selected messages and clear the list and message data @@ -2477,6 +2497,16 @@ selection.push(selected[i]); this.message_list.selection = selection; + + // reset preview frame, if currently previewed message is not selected (has been removed) + try { + var win = this.get_frame_window(this.env.contentframe), + id = win.rcmail.env.uid; + + if (id && $.inArray(id, selection) < 0) + this.show_contentframe(false); + } + catch (e) {}; }; // expand all threads with unread children @@ -3319,7 +3349,7 @@ if (!this.gui_objects.messageform) return false; - var i, input_from = $("[name='_from']"), + var i, elem, pos, input_from = $("[name='_from']"), input_to = $("[name='_to']"), input_subject = $("input[name='_subject']"), input_message = $("[name='_message']").get(0), @@ -3353,11 +3383,18 @@ } if (!html_mode) { - this.set_caret_pos(input_message, this.env.top_posting ? 0 : $(input_message).val().length); + pos = this.env.top_posting ? 0 : input_message.value.length; + this.set_caret_pos(input_message, pos); + // add signature according to selected identity // if we have HTML editor, signature is added in callback if (input_from.prop('type') == 'select-one') { this.change_identity(input_from[0]); + } + + // scroll to the bottom of the textarea (#1490114) + if (pos) { + $(input_message).scrollTop(input_message.scrollHeight); } } @@ -3366,11 +3403,14 @@ this.compose_restore_dialog(0, html_mode) if (input_to.val() == '') - input_to.focus(); + elem = input_to; else if (input_subject.val() == '') - input_subject.focus(); + elem = input_subject; else if (input_message) - input_message.focus(); + elem = input_message; + + // focus first empty element (need to be visible on IE8) + $(elem).filter(':visible').focus(); this.env.compose_focus_elem = document.activeElement; @@ -3419,6 +3459,7 @@ this.get_label('restoremessage'), [{ text: this.get_label('restore'), + 'class': 'mainaction', click: function(){ ref.restore_compose_form(key, html_mode); ref.remove_compose_data(key); // remove old copy @@ -3428,6 +3469,7 @@ }, { text: this.get_label('delete'), + 'class': 'delete', click: function(){ ref.remove_compose_data(key); $(this).dialog('close'); @@ -3455,15 +3497,35 @@ .attr({ 'autocomplete': 'off', 'aria-autocomplete': 'list', 'aria-expanded': 'false', 'role': 'combobox' }); }; - this.submit_messageform = function(draft) + this.submit_messageform = function(draft, saveonly) { var form = this.gui_objects.messageform; if (!form) return; + // the message has been sent but not saved, ask the user what to do + if (!saveonly && this.env.is_sent) { + return this.show_popup_dialog(this.get_label('messageissent'), '', + [{ + text: this.get_label('save'), + 'class': 'mainaction', + click: function() { + ref.submit_messageform(false, true); + $(this).dialog('close'); + } + }, + { + text: this.get_label('cancel'), + click: function() { + $(this).dialog('close'); + } + }] + ); + } + // all checks passed, send message - var msgid = this.set_busy(true, draft ? 'savingmessage' : 'sendingmessage'), + var msgid = this.set_busy(true, draft || saveonly ? 'savingmessage' : 'sendingmessage'), lang = this.spellcheck_lang(), files = []; @@ -3476,6 +3538,10 @@ form.action = this.add_url(form.action, '_unlock', msgid); form.action = this.add_url(form.action, '_lang', lang); form.action = this.add_url(form.action, '_framed', 1); + + if (saveonly) { + form.action = this.add_url(form.action, '_saveonly', 1); + } // register timer to notify about connection timeout this.submit_timer = setTimeout(function(){ @@ -3652,7 +3718,7 @@ this.save_response = function() { // show dialog to enter a name and to modify the text to be saved - var buttons = {}, text = this.editor.get_content(true, true), + var buttons = {}, text = this.editor.get_content({selection: true, format: 'text', nosig: true}), html = '<form class="propform">' + '<div class="prop block"><label>' + this.get_label('responsename') + '</label>' + '<input type="text" name="name" id="ffresponsename" size="40" /></div>' + @@ -3680,7 +3746,7 @@ $(this).dialog('close'); }; - this.show_popup_dialog(html, this.gettext('newresponse'), buttons); + this.show_popup_dialog(html, this.gettext('newresponse'), buttons, {button_classes: ['mainaction']}); $('#ffresponsetext').val(text); $('#ffresponsename').select(); @@ -3762,14 +3828,13 @@ this.set_draft_id = function(id) { - var rc; - if (id && id != this.env.draft_id) { - if (rc = this.opener()) { - // refresh the drafts folder in opener window - if (rc.env.task == 'mail' && rc.env.action == '' && rc.env.mailbox == this.env.drafts_mailbox) - rc.command('checkmail'); - } + var filter = {task: 'mail', action: ''}, + rc = this.opener(false, filter) || this.opener(true, filter); + + // refresh the drafts folder in the opener window + if (rc && rc.env.mailbox == this.env.drafts_mailbox) + rc.command('checkmail'); this.env.draft_id = id; $("input[name='_draft_saveid']").val(id); @@ -3840,7 +3905,7 @@ if (val = $('[name="_' + hash_fields[i] + '"]').val()) str += val + ':'; - str += this.editor.get_content(); + str += this.editor.get_content({refresh: false}); if (this.env.attachments) for (id in this.env.attachments) @@ -3955,7 +4020,6 @@ this.local_storage_remove_item('compose.index'); }; - this.change_identity = function(obj, show_sig) { @@ -4274,14 +4338,28 @@ return url; }; + // reset search filter + this.reset_search_filter = function() + { + this.filter_disabled = true; + if (this.gui_objects.search_filter) + $(this.gui_objects.search_filter).val('ALL').change(); + this.filter_disabled = false; + }; + // reset quick-search form - this.reset_qsearch = function() + this.reset_qsearch = function(all) { if (this.gui_objects.qsearchbox) this.gui_objects.qsearchbox.value = ''; if (this.env.qsearch) this.abort_request(this.env.qsearch); + + if (all) { + this.env.search_scope = 'base'; + this.reset_search_filter(); + } this.env.qsearch = null; this.env.search_request = null; @@ -4325,29 +4403,37 @@ (this.env.search_request && (this.env.search_scope || 'base') != 'base'); }; - this.sent_successfully = function(type, msg, folders) + // action executed after mail is sent + this.sent_successfully = function(type, msg, folders, save_error) { this.display_message(msg, type); this.compose_skip_unsavedcheck = true; if (this.env.extwin) { - this.lock_form(this.gui_objects.messageform); + if (!save_error) + this.lock_form(this.gui_objects.messageform); - var rc = this.opener(); + var filter = {task: 'mail', action: ''}, + rc = this.opener(false, filter) || this.opener(true, filter); + if (rc) { rc.display_message(msg, type); // refresh the folder where sent message was saved or replied message comes from - if (folders && rc.env.task == 'mail' && rc.env.action == '' && $.inArray(rc.env.mailbox, folders) >= 0) { + if (folders && $.inArray(rc.env.mailbox, folders) >= 0) { rc.command('checkmail'); } } - setTimeout(function() { window.close(); }, 1000); + if (!save_error) + setTimeout(function() { window.close(); }, 1000); } - else { + else if (!save_error) { // before redirect we need to wait some time for Chrome (#1486177) setTimeout(function() { ref.list_mailbox(); }, 500); } + + if (save_error) + this.env.is_sent = true; }; @@ -4694,15 +4780,16 @@ clearTimeout(this.preview_timer); var n, id, sid, contact, writable = false, + selected = list.selection.length, 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 - if (id = list.get_single_selection()) + if (this.env.contentframe && (id = list.get_single_selection())) this.preview_timer = setTimeout(function(){ ref.load_contact(id, 'show'); }, 200); else if (this.env.contentframe) this.show_contentframe(false); - if (list.selection.length) { + if (selected) { list.draggable = false; // no source = search result, we'll need to detect if any of @@ -4737,11 +4824,12 @@ // if a group is currently selected, and there is at least one contact selected // thend we can enable the group-remove-selected command - this.enable_command('group-remove-selected', this.env.group && list.selection.length > 0 && writable); - this.enable_command('compose', this.env.group || list.selection.length > 0); - this.enable_command('export-selected', 'copy', list.selection.length > 0); + this.enable_command('group-remove-selected', this.env.group && selected && writable); + this.enable_command('compose', this.env.group || selected); + this.enable_command('print', selected == 1); + this.enable_command('export-selected', 'copy', selected > 0); this.enable_command('edit', id && writable); - this.enable_command('delete', 'move', list.selection.length > 0 && writable); + this.enable_command('delete', 'move', selected && writable); return false; }; @@ -4754,6 +4842,9 @@ if (!src) src = this.env.source; + + if (refresh) + group = this.env.group; if (page && this.current_page == page && src == this.env.source && group == this.env.group) return false; @@ -4851,8 +4942,8 @@ this.contact_list.data = {}; this.contact_list.clear(true); this.show_contentframe(false); - this.enable_command('delete', 'move', 'copy', false); - this.enable_command('compose', this.env.group ? true : false); + this.enable_command('delete', 'move', 'copy', 'print', false); + this.enable_command('compose', this.env.group); }; this.set_group_prop = function(prop) @@ -4892,7 +4983,7 @@ this.contact_list.clear_selection(); this.enable_command('compose', rec && rec.email); - this.enable_command('export-selected', rec && rec._type != 'group'); + this.enable_command('export-selected', 'print', rec && rec._type != 'group'); } else if (framed) return false; @@ -5143,10 +5234,10 @@ dateFormat: this.env.date_format, changeMonth: true, changeYear: true, - yearRange: '-100:+10', + yearRange: '-120:+10', showOtherMonths: true, - selectOtherMonths: true, - onSelect: function(dateText) { $(this).focus().val(dateText) } + selectOtherMonths: true +// onSelect: function(dateText) { $(this).focus().val(dateText); } }); $('input.datepicker').datepicker(); } @@ -5166,6 +5257,7 @@ this.show_popup_dialog(content, this.get_label('newgroup'), [{ text: this.get_label('save'), + 'class': 'mainaction', click: function() { var name; @@ -5193,6 +5285,7 @@ this.show_popup_dialog(content, this.get_label('grouprename'), [{ text: this.get_label('save'), + 'class': 'mainaction', click: function() { var name; @@ -5556,6 +5649,7 @@ this.show_popup_dialog(content, this.get_label('searchsave'), [{ text: this.get_label('save'), + 'class': 'mainaction', click: function() { var name; @@ -5774,6 +5868,9 @@ // on the list when dragging starts (and stops), this is slow, but // I didn't find a method to check droptarget on over event accept: function(node) { + if (!$(node).is('.mailbox')) + return false; + var source_folder = ref.folder_id2name($(node).attr('id')), dest_folder = ref.folder_id2name(this.id), source = ref.env.subscriptionrows[source_folder], @@ -5794,7 +5891,7 @@ this.folder_id2name = function(id) { - return ref.html_identifier_decode(id.replace(/^rcmli/, '')); + return id ? ref.html_identifier_decode(id.replace(/^rcmli/, '')) : null; }; this.subscription_select = function(id) @@ -6340,7 +6437,7 @@ }; // display a system message, list of types in common.css (below #message definition) - this.display_message = function(msg, type, timeout) + this.display_message = function(msg, type, timeout, key) { // pass command to parent window if (this.is_framed()) @@ -6349,18 +6446,34 @@ if (!this.gui_objects.message) { // save message in order to display after page loaded if (type != 'loading') - this.pending_message = [msg, type, timeout]; + this.pending_message = [msg, type, timeout, key]; return 1; } - type = type ? type : 'notice'; + if (!type) + type = 'notice'; - var key = this.html_identifier(msg), - date = new Date(), + if (!key) + key = this.html_identifier(msg); + + var date = new Date(), id = type + date.getTime(); - if (!timeout) - timeout = this.message_time * (type == 'error' || type == 'warning' ? 2 : 1); + if (!timeout) { + switch (type) { + case 'error': + case 'warning': + timeout = this.message_time * 2; + break; + + case 'uploading': + timeout = 0; + break; + + default: + timeout = this.message_time; + } + } if (type == 'loading') { key = 'loading'; @@ -6393,7 +6506,7 @@ if (type == 'loading') { this.messages[key].labels = [{'id': id, 'msg': msg}]; } - else { + else if (type != 'uploading') { obj.click(function() { return ref.hide_message(obj); }) .attr('role', 'alert'); } @@ -6402,6 +6515,7 @@ if (timeout > 0) setTimeout(function() { ref.hide_message(id, type != 'loading'); }, timeout); + return id; }; @@ -6480,6 +6594,35 @@ this.messages = {}; }; + // display uploading message with progress indicator + // data should contain: name, total, current, percent, text + this.display_progress = function(data) + { + if (!data || !data.name) + return; + + var msg = this.messages['progress' + data.name]; + + if (!data.label) + data.label = this.get_label('uploadingmany'); + + if (!msg) { + if (!data.percent || data.percent < 100) + this.display_message(data.label, 'uploading', 0, 'progress' + data.name); + return; + } + + if (!data.total || data.percent >= 100) { + this.hide_message(msg.obj); + return; + } + + if (data.text) + data.label += ' ' + data.text; + + msg.obj.text(data.label); + }; + // open a jquery UI dialog with the given content this.show_popup_dialog = function(content, title, buttons, options) { @@ -6495,14 +6638,16 @@ else popup.html(content); - popup.dialog($.extend({ + options = $.extend({ title: title, buttons: buttons, modal: true, resizable: true, width: 500, close: function(event, ui) { $(this).remove(); } - }, options || {})); + }, options || {}); + + popup.dialog(options); // resize and center popup var win = $(window), w = win.width(), h = win.height(), @@ -6511,6 +6656,11 @@ popup.dialog('option', { height: Math.min(h - 40, height + 75 + (buttons ? 50 : 0)), width: Math.min(w - 20, width + 36) + }); + + // assign special classes to dialog buttons + $.each(options.button_classes || [], function(i, v) { + if (v) $($('.ui-dialog-buttonpane button.ui-button', popup.parent()).get(i)).addClass(v); }); return popup; @@ -6577,6 +6727,9 @@ repl, cell, col, n, len, tr; this.env.listcols = listcols; + + if (!this.env.coltypes) + this.env.coltypes = {}; // replace old column headers if (thead) { @@ -6649,7 +6802,7 @@ this.set_quota = function(content) { if (this.gui_objects.quotadisplay && content && content.type == 'text') - $(this.gui_objects.quotadisplay).html(content.percent+'%').attr('title', content.title); + $(this.gui_objects.quotadisplay).text((content.percent||0) + '%').attr('title', content.title); this.triggerEvent('setquota', content); this.env.quota_content = content; @@ -7148,22 +7301,32 @@ }; // send a http request to the server - this.http_request = function(action, query, lock) + this.http_request = function(action, data, lock) { - var url = this.url(action, query); + if (typeof data !== 'object') + data = rcube_parse_query(data); + + data._remote = 1; + data._unlock = lock ? lock : 0; // trigger plugin hook - var result = this.triggerEvent('request'+action, query); + var result = this.triggerEvent('request' + action, data); - if (result !== undefined) { - // abort if one the handlers returned false - if (result === false) - return false; - else - url = this.url(action, result); + // abort if one of the handlers returned false + if (result === false) { + if (data._unlock) + this.set_busy(false, null, data._unlock); + return false; + } + else if (result !== undefined) { + data = result; + if (data._action) { + action = data._action; + delete data._action; + } } - url += '&_remote=1'; + var url = this.url(action, data); // send request this.log('HTTP GET: ' + url); @@ -7172,33 +7335,39 @@ this.start_keepalive(); return $.ajax({ - type: 'GET', url: url, data: { _unlock:(lock?lock:0) }, dataType: 'json', - success: function(data){ ref.http_response(data); }, + type: 'GET', url: url, dataType: 'json', + success: function(data) { ref.http_response(data); }, error: function(o, status, err) { ref.http_error(o, status, err, lock, action); } }); }; // send a http POST request to the server - this.http_post = function(action, postdata, lock) + this.http_post = function(action, data, lock) { - var url = this.url(action); + if (typeof data !== 'object') + data = rcube_parse_query(data); - if (postdata && typeof postdata === 'object') { - postdata._remote = 1; - postdata._unlock = (lock ? lock : 0); - } - else - postdata += (postdata ? '&' : '') + '_remote=1' + (lock ? '&_unlock='+lock : ''); + data._remote = 1; + data._unlock = lock ? lock : 0; // trigger plugin hook - var result = this.triggerEvent('request'+action, postdata); - if (result !== undefined) { - // abort if one of the handlers returned false - if (result === false) - return false; - else - postdata = result; + var result = this.triggerEvent('request'+action, data); + + // abort if one of the handlers returned false + if (result === false) { + if (data._unlock) + this.set_busy(false, null, data._unlock); + return false; } + else if (result !== undefined) { + data = result; + if (data._action) { + action = data._action; + delete data._action; + } + } + + var url = this.url(action); // send request this.log('HTTP POST: ' + url); @@ -7207,7 +7376,7 @@ this.start_keepalive(); return $.ajax({ - type: 'POST', url: url, data: postdata, dataType: 'json', + type: 'POST', url: url, data: data, dataType: 'json', success: function(data){ ref.http_response(data); }, error: function(o, status, err) { ref.http_error(o, status, err, lock, action); } }); @@ -7276,7 +7445,7 @@ this.enable_command('compose', (uid && this.contact_list.rows[uid])); this.enable_command('delete', 'edit', writable); this.enable_command('export', (this.contact_list && this.contact_list.rowcount > 0)); - this.enable_command('export-selected', false); + this.enable_command('export-selected', 'print', false); } case 'move': @@ -7816,12 +7985,24 @@ }; // get window.opener.rcmail if available - this.opener = function() + this.opener = function(deep, filter) { + var i, win = window.opener; + // catch Error: Permission denied to access property rcmail try { - if (window.opener && !opener.closed && opener.rcmail) - return opener.rcmail; + if (win && !win.closed) { + // try parent of the opener window, e.g. preview frame + if (deep && (!win.rcmail || win.rcmail.env.framed) && win.parent && win.parent.rcmail) + win = win.parent; + + if (win.rcmail && filter) + for (i in filter) + if (win.rcmail.env[i] != filter[i]) + return; + + return win.rcmail; + } } catch (e) {} }; @@ -7830,13 +8011,17 @@ // and return the message uid this.get_single_uid = function() { - return this.env.uid ? this.env.uid : (this.message_list ? this.message_list.get_single_selection() : null); + var uid = this.env.uid || (this.message_list ? this.message_list.get_single_selection() : null); + var result = ref.triggerEvent('get_single_uid', { uid: uid }); + return result || uid; }; // same as above but for contacts this.get_single_cid = function() { - return this.env.cid ? this.env.cid : (this.contact_list ? this.contact_list.get_single_selection() : null); + var cid = this.env.cid || (this.contact_list ? this.contact_list.get_single_selection() : null); + var result = ref.triggerEvent('get_single_cid', { cid: cid }); + return result || cid; }; // get the IMP mailbox of the message with the given UID @@ -7971,7 +8156,7 @@ img.onload = function() { ref.env.browser_capabilities.tif = 1; }; img.onerror = function() { ref.env.browser_capabilities.tif = 0; }; - img.src = 'program/resources/blank.tif'; + img.src = this.assets_path('program/resources/blank.tif'); }; this.pdf_support_check = function() @@ -7984,7 +8169,7 @@ if (plugin && plugin.enabledPlugin) return 1; - if (window.ActiveXObject) { + if ('ActiveXObject' in window) { try { if (plugin = new ActiveXObject("AcroPDF.PDF")) return 1; @@ -8017,7 +8202,7 @@ if (plugin && plugin.enabledPlugin) return 1; - if (window.ActiveXObject) { + if ('ActiveXObject' in window) { try { if (plugin = new ActiveXObject("ShockwaveFlash.ShockwaveFlash")) return 1; @@ -8026,6 +8211,15 @@ } return 0; + }; + + this.assets_path = function(path) + { + if (this.env.assets_path && !path.startsWith(this.env.assets_path)) { + path = this.env.assets_path + path; + } + + return path; }; // Cookie setter @@ -8045,15 +8239,16 @@ // wrapper for localStorage.getItem(key) this.local_storage_get_item = function(key, deflt, encrypted) { - var item; + var item, result; // TODO: add encryption try { item = localStorage.getItem(this.get_local_storage_prefix() + key); + result = JSON.parse(item); } catch (e) { } - return item !== null ? JSON.parse(item) : (deflt || null); + return result || deflt || null; }; // wrapper for localStorage.setItem(key, data) @@ -8083,6 +8278,14 @@ return false; } }; + + this.print_dialog = function() + { + if (bw.safari) + setTimeout('window.print()', 10); + else + window.print(); + }; } // end object rcube_webmail @@ -8092,7 +8295,7 @@ if (!elem.title) { var $elem = $(elem); if ($elem.width() + (indent || 0) * 15 > $elem.parent().width()) - elem.title = $elem.text(); + elem.title = rcube_webmail.subject_text(elem); } }; @@ -8109,10 +8312,17 @@ tmp.remove(); if (w + $('span.branch', $elem).width() * 15 > $elem.width()) - elem.title = txt; + elem.title = rcube_webmail.subject_text(elem); } }; +rcube_webmail.subject_text = function(elem) +{ + var t = $(elem).clone(); + t.find('.skip-on-drag').remove(); + return t.text(); +}; + rcube_webmail.prototype.get_cookie = getCookie; // copy event engine prototype -- Gitblit v1.9.1