From 1e7c877a66c9e309b027e36feafbff9ebd419355 Mon Sep 17 00:00:00 2001 From: Aleksander Machniak <alec@alec.pl> Date: Mon, 09 Mar 2015 12:36:38 -0400 Subject: [PATCH] Reset search filter on folder selection and search reset --- program/js/app.js | 335 +++++++++++++++++++++++++++++++++++++++---------------- 1 files changed, 236 insertions(+), 99 deletions(-) diff --git a/program/js/app.js b/program/js/app.js index e0a6d26..a178a3e 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; @@ -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' }) }); } @@ -651,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 @@ -771,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(); @@ -1052,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') { @@ -1115,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 @@ -1152,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'); @@ -1176,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()) { @@ -1213,16 +1221,17 @@ // reset quicksearch case 'reset-search': - var n, s = this.env.search_request || this.env.qsearch; + var n, s = this.env.search_request || this.env.qsearch, + ss = this.gui_objects.qsearchbox && this.gui_objects.qsearchbox.value != ''; - this.reset_qsearch(); + this.reset_qsearch(true); this.select_all_mode = false; if (s && this.env.action == 'compose') { if (this.contact_list) this.list_contacts_clear(); } - else if (s && this.env.mailbox) { + else if (s && ss && this.env.mailbox) { this.list_mailbox(this.env.mailbox, 1); } else if (s && this.task == 'addressbook') { @@ -1406,8 +1415,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); }; @@ -1417,7 +1428,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) @@ -1594,7 +1608,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)+'&'; @@ -1610,7 +1625,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); @@ -1948,7 +1964,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); @@ -2252,7 +2268,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); } } @@ -2362,6 +2378,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(); @@ -2395,16 +2414,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 @@ -2478,6 +2498,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 @@ -3465,15 +3495,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 = []; @@ -3486,6 +3536,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(){ @@ -3772,14 +3826,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); @@ -3965,7 +4018,6 @@ this.local_storage_remove_item('compose.index'); }; - this.change_identity = function(obj, show_sig) { @@ -4284,14 +4336,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; @@ -4335,29 +4401,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; }; @@ -4704,6 +4778,7 @@ 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 @@ -4712,7 +4787,7 @@ 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 @@ -4747,11 +4822,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; }; @@ -4764,6 +4840,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; @@ -4861,8 +4940,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) @@ -4902,7 +4981,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; @@ -5153,10 +5232,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(); } @@ -5787,6 +5866,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], @@ -5807,7 +5889,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) @@ -6554,14 +6636,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(), @@ -6713,7 +6797,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; @@ -7212,22 +7296,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); @@ -7236,33 +7330,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); @@ -7271,7 +7371,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); } }); @@ -7340,7 +7440,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': @@ -7880,12 +7980,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) {} }; @@ -8039,7 +8151,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() @@ -8052,7 +8164,7 @@ if (plugin && plugin.enabledPlugin) return 1; - if (window.ActiveXObject) { + if ('ActiveXObject' in window) { try { if (plugin = new ActiveXObject("AcroPDF.PDF")) return 1; @@ -8085,7 +8197,7 @@ if (plugin && plugin.enabledPlugin) return 1; - if (window.ActiveXObject) { + if ('ActiveXObject' in window) { try { if (plugin = new ActiveXObject("ShockwaveFlash.ShockwaveFlash")) return 1; @@ -8094,6 +8206,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 @@ -8113,15 +8234,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) @@ -8151,6 +8273,14 @@ return false; } }; + + this.print_dialog = function() + { + if (bw.safari) + setTimeout('window.print()', 10); + else + window.print(); + }; } // end object rcube_webmail @@ -8160,7 +8290,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); } }; @@ -8177,10 +8307,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