From 19577698176df4583cbaecba41c83371c3a368da Mon Sep 17 00:00:00 2001 From: Aleksander Machniak <alec@alec.pl> Date: Sat, 26 Jul 2014 04:16:02 -0400 Subject: [PATCH] Handle clicks on list parent element from the list widget --- program/js/app.js | 402 ++++++++++++++++++++++++++------------------------------ 1 files changed, 187 insertions(+), 215 deletions(-) diff --git a/program/js/app.js b/program/js/app.js index 895671a..e00479f 100644 --- a/program/js/app.js +++ b/program/js/app.js @@ -236,8 +236,6 @@ return ref.command('sort', $(this).attr('rel'), this); }); - 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()); @@ -405,8 +403,6 @@ .addEventListener('dragmove', function(e) { ref.drag_move(e); }) .addEventListener('dragend', function(e) { ref.drag_end(e); }) .init(); - - this.gui_objects.contactslist.parentNode.onmousedown = function(e){ return ref.click_on_list(e); }; $(this.gui_objects.qsearchbox).focusin(function() { ref.contact_list.blur(); }); @@ -1713,19 +1709,6 @@ return true; } - - this.click_on_list = function(e) - { - if (this.gui_objects.qsearchbox) - this.gui_objects.qsearchbox.blur(); - - if (this.message_list) - this.message_list.focus(e); - else if (this.contact_list) - this.contact_list.focus(e); - - return true; - }; this.msglist_select = function(list) { @@ -3374,63 +3357,7 @@ } // check for locally stored compose data - if (window.localStorage) { - var key, formdata, index = this.local_storage_get_item('compose.index', []); - - for (i = 0; i < index.length; i++) { - key = index[i]; - formdata = this.local_storage_get_item('compose.' + key, null, true); - if (!formdata) { - continue; - } - // restore saved copy of current compose_id - if (formdata.changed && key == this.env.compose_id) { - this.restore_compose_form(key, html_mode); - break; - } - // skip records from 'other' drafts - if (this.env.draft_id && formdata.draft_id && formdata.draft_id != this.env.draft_id) { - continue; - } - // skip records on reply - if (this.env.reply_msgid && formdata.reply_msgid != this.env.reply_msgid) { - continue; - } - // show dialog asking to restore the message - if (formdata.changed && formdata.session != this.env.session_id) { - this.show_popup_dialog( - this.get_label('restoresavedcomposedata') - .replace('$date', new Date(formdata.changed).toLocaleString()) - .replace('$subject', formdata._subject) - .replace(/\n/g, '<br/>'), - this.get_label('restoremessage'), - [{ - text: this.get_label('restore'), - click: function(){ - ref.restore_compose_form(key, html_mode); - ref.remove_compose_data(key); // remove old copy - ref.save_compose_form_local(); // save under current compose_id - $(this).dialog('close'); - } - }, - { - text: this.get_label('delete'), - click: function(){ - ref.remove_compose_data(key); - $(this).dialog('close'); - } - }, - { - text: this.get_label('ignore'), - click: function(){ - $(this).dialog('close'); - } - }] - ); - break; - } - } - } + this.compose_restore_dialog(0, html_mode) if (input_to.val() == '') input_to.focus(); @@ -3447,6 +3374,72 @@ // start the auto-save timer this.auto_save_start(); }; + + this.compose_restore_dialog = function(j, html_mode) + { + var i, key, formdata, index = this.local_storage_get_item('compose.index', []); + + var show_next = function(i) { + if (++i < index.length) + ref.compose_restore_dialog(i, html_mode) + } + + for (i = j || 0; i < index.length; i++) { + key = index[i]; + formdata = this.local_storage_get_item('compose.' + key, null, true); + if (!formdata) { + continue; + } + // restore saved copy of current compose_id + if (formdata.changed && key == this.env.compose_id) { + this.restore_compose_form(key, html_mode); + break; + } + // skip records from 'other' drafts + if (this.env.draft_id && formdata.draft_id && formdata.draft_id != this.env.draft_id) { + continue; + } + // skip records on reply + if (this.env.reply_msgid && formdata.reply_msgid != this.env.reply_msgid) { + continue; + } + // show dialog asking to restore the message + if (formdata.changed && formdata.session != this.env.session_id) { + this.show_popup_dialog( + this.get_label('restoresavedcomposedata') + .replace('$date', new Date(formdata.changed).toLocaleString()) + .replace('$subject', formdata._subject) + .replace(/\n/g, '<br/>'), + this.get_label('restoremessage'), + [{ + text: this.get_label('restore'), + click: function(){ + ref.restore_compose_form(key, html_mode); + ref.remove_compose_data(key); // remove old copy + ref.save_compose_form_local(); // save under current compose_id + $(this).dialog('close'); + } + }, + { + text: this.get_label('delete'), + click: function(){ + ref.remove_compose_data(key); + $(this).dialog('close'); + show_next(i); + } + }, + { + text: this.get_label('ignore'), + click: function(){ + $(this).dialog('close'); + show_next(i); + } + }] + ); + break; + } + } + } this.init_address_input_events = function(obj, props) { @@ -3888,15 +3881,16 @@ } }); - if (window.localStorage && !empty) { + if (!empty) { var index = this.local_storage_get_item('compose.index', []), key = this.env.compose_id; - if ($.inArray(key, index) < 0) { - index.push(key); - } - this.local_storage_set_item('compose.' + key, formdata, true); - this.local_storage_set_item('compose.index', index); + if ($.inArray(key, index) < 0) { + index.push(key); + } + + this.local_storage_set_item('compose.' + key, formdata, true); + this.local_storage_set_item('compose.index', index); } }; @@ -3928,27 +3922,24 @@ // remove stored compose data from localStorage this.remove_compose_data = function(key) { - if (window.localStorage) { - var index = this.local_storage_get_item('compose.index', []); + var index = this.local_storage_get_item('compose.index', []); - if ($.inArray(key, index) >= 0) { - this.local_storage_remove_item('compose.' + key); - this.local_storage_set_item('compose.index', $.grep(index, function(val,i) { return val != key; })); - } + if ($.inArray(key, index) >= 0) { + this.local_storage_remove_item('compose.' + key); + this.local_storage_set_item('compose.index', $.grep(index, function(val,i) { return val != key; })); } }; // clear all stored compose data of this user this.clear_compose_data = function() { - if (window.localStorage) { - var i, index = this.local_storage_get_item('compose.index', []); + var i, index = this.local_storage_get_item('compose.index', []); - for (i=0; i < index.length; i++) { - this.local_storage_remove_item('compose.' + index[i]); - } - this.local_storage_remove_item('compose.index'); + for (i=0; i < index.length; i++) { + this.local_storage_remove_item('compose.' + index[i]); } + + this.local_storage_remove_item('compose.index'); }; @@ -3969,18 +3960,16 @@ return; } - var i, rx, - id = obj.options[obj.selectedIndex].value, + var id = obj.options[obj.selectedIndex].value, sig = this.env.identity, delim = this.env.recipients_separator, - rx_delim = RegExp.escape(delim), - headers = ['replyto', 'bcc']; + rx_delim = RegExp.escape(delim); // update reply-to/bcc fields with addresses defined in identities - for (i in headers) { - var key = headers[i], - old_val = sig && this.env.identities[sig] ? this.env.identities[sig][key] : '', - new_val = id && this.env.identities[id] ? this.env.identities[id][key] : '', + $.each(['replyto', 'bcc'], function() { + var rx, key = this, + old_val = sig && ref.env.identities[sig] ? ref.env.identities[sig][key] : '', + new_val = id && ref.env.identities[id] ? ref.env.identities[id][key] : '', input = $('[name="_'+key+'"]'), input_val = input.val(); // remove old address(es) @@ -4007,7 +3996,7 @@ if (old_val || new_val) input.val(input_val).change(); - } + }); // enable manual signature insert if (this.env.signatures && this.env.signatures[id]) { @@ -5150,29 +5139,55 @@ .submit(function() { $('input.mainaction').click(); return false; }); }; + // group creation dialog this.group_create = function() { - this.add_input_row('contactgroup'); + var input = $('<input>').attr('type', 'text'), + content = $('<label>').text(this.get_label('namex')).append(input); + + this.show_popup_dialog(content, this.get_label('newgroup'), + [{ + text: this.get_label('save'), + click: function() { + var name; + + if (name = input.val()) { + ref.http_post('group-create', {_source: ref.env.source, _name: name}, + ref.set_busy(true, 'loading')); + } + + $(this).dialog('close'); + } + }] + ); }; + // group rename dialog this.group_rename = function() { - if (!this.env.group || !this.gui_objects.folderlist) + if (!this.env.group) return; - if (!this.name_input) { - this.enable_command('list', 'listgroup', false); - this.name_input = $('<input>').attr('type', 'text').val(this.env.contactgroups['G'+this.env.source+this.env.group].name); - this.name_input.bind('keydown', function(e) { return ref.add_input_keydown(e); }); - this.env.group_renaming = true; + var group_name = this.env.contactgroups['G' + this.env.source + this.env.group].name, + input = $('<input>').attr('type', 'text').val(group_name), + content = $('<label>').text(this.get_label('namex')).append(input); - var link, li = this.get_folder_li('G'+this.env.source+this.env.group,'',true); - if (li && (link = li.firstChild)) { - $(link).hide().before(this.name_input); - } - } + this.show_popup_dialog(content, this.get_label('grouprename'), + [{ + text: this.get_label('save'), + click: function() { + var name; - this.name_input.select().focus(); + if ((name = input.val()) && name != group_name) { + ref.http_post('group-rename', {_source: ref.env.source, _gid: ref.env.group, _name: name}, + ref.set_busy(true, 'loading')); + } + + $(this).dialog('close'); + } + }], + {open: function() { input.select(); }} + ); }; this.group_delete = function() @@ -5197,38 +5212,6 @@ this.list_contacts(prop.source, 0); }; - // @TODO: maybe it would be better to use popup instead of inserting input to the list? - this.add_input_row = function(type) - { - if (!this.gui_objects.folderlist) - return; - - if (!this.name_input) { - this.name_input = $('<input>').attr('type', 'text').data('tt', type); - this.name_input.bind('keydown', function(e) { return ref.add_input_keydown(e); }); - this.name_input_li = $('<li>').addClass(type).append(this.name_input); - - var ul, li; - - // find list (UL) element - if (type == 'contactsearch') - ul = this.gui_objects.savedsearchlist; - else - ul = $('ul.groups', this.get_folder_li(this.env.source,'',true)); - - // append to the list - li = $('li:last', ul); - if (li.length) - this.name_input_li.insertAfter(li); - else { - this.name_input_li.appendTo(ul); - ul.show(); // make sure the list is visible - } - } - - this.name_input.select().focus(); - }; - //remove selected contacts from current active group this.group_remove_selected = function() { @@ -5248,62 +5231,9 @@ } }; - // handler for keyboard events on the input field - this.add_input_keydown = function(e) - { - var key = rcube_event.get_keycode(e), - input = $(e.target), itype = input.data('tt'); - - // enter - if (key == 13) { - var newname = input.val(); - - if (newname) { - var lock = this.set_busy(true, 'loading'); - - if (itype == 'contactsearch') - this.http_post('search-create', {_search: this.env.search_request, _name: newname}, lock); - else if (this.env.group_renaming) - this.http_post('group-rename', {_source: this.env.source, _gid: this.env.group, _name: newname}, lock); - else - this.http_post('group-create', {_source: this.env.source, _name: newname}, lock); - } - return false; - } - // escape - else if (key == 27) - this.reset_add_input(); - - return true; - }; - - this.reset_add_input = function() - { - if (this.name_input) { - var li = this.name_input.parent(); - if (this.env.group_renaming) { - li.children().last().show(); - this.env.group_renaming = false; - } - else if ($('li', li.parent()).length == 1) - li.parent().hide(); - - this.name_input.remove(); - - if (this.name_input_li) - this.name_input_li.remove(); - - this.name_input = this.name_input_li = null; - } - - this.enable_command('list', 'listgroup', true); - }; - // callback for creating a new contact group this.insert_contact_group = function(prop) { - this.reset_add_input(); - prop.type = 'group'; var key = 'G'+prop.source+prop.id, @@ -5321,8 +5251,6 @@ // callback for renaming a contact group this.update_contact_group = function(prop) { - this.reset_add_input(); - var key = 'G'+prop.source+prop.id, newnode = {}; @@ -5586,8 +5514,6 @@ // callback for creating a new saved search record this.insert_saved_search = function(name, id) { - this.reset_add_input(); - var key = 'S'+id, link = $('<a>').attr('href', '#') .attr('rel', id) @@ -5603,10 +5529,27 @@ this.triggerEvent('abook_search_insert', prop); }; - // creates an input for saved search name + // creates a dialog for saved search this.search_create = function() { - this.add_input_row('contactsearch'); + var input = $('<input>').attr('type', 'text'), + content = $('<label>').text(this.get_label('namex')).append(input); + + this.show_popup_dialog(content, this.get_label('searchsave'), + [{ + text: this.get_label('save'), + click: function() { + var name; + + if (name = input.val()) { + ref.http_post('search-create', {_search: ref.env.search_request, _name: name}, + ref.set_busy(true, 'loading')); + } + + $(this).dialog('close'); + } + }] + ); }; this.search_delete = function() @@ -5884,6 +5827,9 @@ { if (!this.gui_objects.subscriptionlist) return false; + + // disable drag-n-drop temporarily + this.subscription_list.draggable('destroy').droppable('destroy'); var row, n, tmp, tmp_name, rowid, collator, pos, p, parent = '', folders = [], list = [], slist = [], @@ -6461,22 +6407,27 @@ }; // open a jquery UI dialog with the given content - this.show_popup_dialog = function(html, title, buttons, options) + this.show_popup_dialog = function(content, title, buttons, options) { // forward call to parent window if (this.is_framed()) { - return parent.rcmail.show_popup_dialog(html, title, buttons, options); + return parent.rcmail.show_popup_dialog(content, title, buttons, options); } - var popup = $('<div class="popup">') - .html(html) - .dialog($.extend({ + var popup = $('<div class="popup">'); + + if (typeof content == 'object') + popup.append(content); + else + popup.html(html); + + popup.dialog($.extend({ title: title, buttons: buttons, modal: true, resizable: true, width: 500, - close: function(event, ui) { $(this).remove() } + close: function(event, ui) { $(this).remove(); } }, options || {})); // resize and center popup @@ -8020,22 +7971,43 @@ // wrapper for localStorage.getItem(key) this.local_storage_get_item = function(key, deflt, encrypted) { + var item; + // TODO: add encryption - var item = localStorage.getItem(this.get_local_storage_prefix() + key); + try { + item = localStorage.getItem(this.get_local_storage_prefix() + key); + } + catch (e) { } + return item !== null ? JSON.parse(item) : (deflt || null); }; // wrapper for localStorage.setItem(key, data) this.local_storage_set_item = function(key, data, encrypted) { - // TODO: add encryption - return localStorage.setItem(this.get_local_storage_prefix() + key, JSON.stringify(data)); + // try/catch to handle no localStorage support, but also error + // in Safari-in-private-browsing-mode where localStorage exists + // but can't be used (#1489996) + try { + // TODO: add encryption + localStorage.setItem(this.get_local_storage_prefix() + key, JSON.stringify(data)); + return true; + } + catch (e) { + return false; + } }; // wrapper for localStorage.removeItem(key) this.local_storage_remove_item = function(key) { - return localStorage.removeItem(this.get_local_storage_prefix() + key); + try { + localStorage.removeItem(this.get_local_storage_prefix() + key); + return true; + } + catch (e) { + return false; + } }; } // end object rcube_webmail -- Gitblit v1.9.1