| | |
| | | this.contact_list |
| | | .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'); }) |
| | | .addEventListener('dblclick', function(o) { ref.compose_add_recipient(); }) |
| | | .addEventListener('keypress', function(o) { |
| | | if (o.key_pressed == o.ENTER_KEY) { |
| | | if (!ref.compose_add_recipient('to')) { |
| | | if (!ref.compose_add_recipient()) { |
| | | // execute link action on <enter> if not a recipient entry |
| | | if (o.last_selected && String(o.last_selected).charAt(0) == 'G') { |
| | | $(o.rows[o.last_selected].obj).find('a').first().click(); |
| | |
| | | } |
| | | }) |
| | | .init(); |
| | | |
| | | // remember last focused address field |
| | | $('#_to,#_cc,#_bcc').focus(function() { ref.env.focused_field = this; }); |
| | | } |
| | | |
| | | if (this.gui_objects.addressbookslist) { |
| | |
| | | |
| | | this.update_group_commands(); |
| | | this.command('list'); |
| | | } |
| | | |
| | | if (this.gui_objects.savedsearchlist) { |
| | | this.savedsearchlist = new rcube_treelist_widget(this.gui_objects.savedsearchlist, { |
| | | id_prefix: 'rcmli', |
| | | id_encode: this.html_identifier_encode, |
| | | id_decode: this.html_identifier_decode |
| | | }); |
| | | |
| | | this.savedsearchlist.addEventListener('select', function(node) { |
| | | ref.triggerEvent('selectfolder', { folder:node.id, prefix:'rcmli' }); }); |
| | | } |
| | | |
| | | this.set_page_buttons(); |
| | |
| | | // init treelist widget |
| | | if (this.gui_objects.folderlist && window.rcube_treelist_widget) { |
| | | this.treelist = new rcube_treelist_widget(this.gui_objects.folderlist, { |
| | | selectable: true, |
| | | id_prefix: 'rcmli', |
| | | id_encode: this.html_identifier_encode, |
| | | id_decode: this.html_identifier_decode, |
| | |
| | | { |
| | | var ret, uid, cid, url, flag, aborted = false; |
| | | |
| | | if (obj && obj.blur && !(event || rcube_event.is_keyboard(event))) |
| | | 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) |
| | |
| | | |
| | | // process external commands |
| | | if (typeof this.command_handlers[command] === 'function') { |
| | | ret = this.command_handlers[command](props, obj); |
| | | ret = this.command_handlers[command](props, obj, event); |
| | | return ret !== undefined ? ret : (obj ? false : true); |
| | | } |
| | | else if (typeof this.command_handlers[command] === 'string') { |
| | | ret = window[this.command_handlers[command]](props, obj); |
| | | ret = window[this.command_handlers[command]](props, obj, event); |
| | | return ret !== undefined ? ret : (obj ? false : true); |
| | | } |
| | | |
| | |
| | | return (this.env.mailboxes[id] |
| | | && !this.env.mailboxes[id].virtual |
| | | && (this.env.mailboxes[id].id != this.env.mailbox || this.is_multifolder_listing())) ? 1 : 0; |
| | | |
| | | case 'settings': |
| | | return id != this.env.mailbox ? 1 : 0; |
| | | |
| | | case 'addressbook': |
| | | var target; |
| | |
| | | |
| | | this.compose_add_recipient = function(field) |
| | | { |
| | | // find last focused field name |
| | | if (!field) { |
| | | field = $(this.env.focused_field).filter(':visible'); |
| | | field = field.length ? field.attr('id').replace('_', '') : 'to'; |
| | | } |
| | | |
| | | var recipients = [], input = $('#_'+field), delim = this.env.recipients_delimiter; |
| | | |
| | | if (this.contact_list && this.contact_list.selection.length) { |
| | |
| | | // submit delete request |
| | | if (key && confirm(this.get_label('deleteresponseconfirm'))) { |
| | | this.http_post('settings/delete-response', { _key: key }, false); |
| | | return true; |
| | | } |
| | | |
| | | return false; |
| | | }; |
| | | |
| | | // updates spellchecker buttons on state change |
| | |
| | | if (upload_id) |
| | | this.triggerEvent('fileuploaded', {name: name, attachment: att, id: upload_id}); |
| | | |
| | | if (!this.env.attachments) |
| | | this.env.attachments = {}; |
| | | |
| | | if (upload_id && this.env.attachments[upload_id]) |
| | | delete this.env.attachments[upload_id]; |
| | | |
| | | this.env.attachments[name] = att; |
| | | |
| | | if (!this.gui_objects.attachmentlist) |
| | | return false; |
| | | |
| | |
| | | |
| | | if (!att.complete && att.frame) |
| | | att.html = '<a title="'+this.get_label('cancel')+'" onclick="return rcmail.cancel_attachment_upload(\''+name+'\', \''+att.frame+'\');" href="#cancelupload" class="cancelupload">' |
| | | + (this.env.cancelicon ? '<img src="'+this.env.cancelicon+'" alt="" />' : this.get_label('cancel')) + '</a>' + att.html; |
| | | + (this.env.cancelicon ? '<img src="'+this.env.cancelicon+'" alt="'+this.get_label('cancel')+'" />' : this.get_label('cancel')) + '</a>' + att.html; |
| | | |
| | | var indicator, li = $('<li>'); |
| | | |
| | |
| | | li.appendTo(this.gui_objects.attachmentlist); |
| | | } |
| | | |
| | | if (upload_id && this.env.attachments[upload_id]) |
| | | delete this.env.attachments[upload_id]; |
| | | |
| | | this.env.attachments[name] = att; |
| | | // set tabindex attribute |
| | | var tabindex = $(this.gui_objects.attachmentlist).attr('data-tabindex') || '0'; |
| | | li.find('a').attr('tabindex', tabindex); |
| | | |
| | | return true; |
| | | }; |
| | |
| | | this.ksearch_pane = $('<div>').attr('id', 'rcmKSearchpane').attr('role', 'listbox') |
| | | .css({ position:'absolute', 'z-index':30000 }).append(ul).appendTo(document.body); |
| | | this.ksearch_pane.__ul = ul[0]; |
| | | |
| | | // register (delegate) event handlers |
| | | ul.on('mouseover', 'li', function(e){ ref.ksearch_select(e.target); }) |
| | | .on('mouseup', 'li', function(e){ ref.ksearch_click(e.target); }) |
| | | } |
| | | |
| | | ul = this.ksearch_pane.__ul; |
| | |
| | | // add each result line to list |
| | | if (results && (len = results.length)) { |
| | | for (i=0; i < len && maxlen > 0; i++) { |
| | | text = typeof results[i] === 'object' ? results[i].name : results[i]; |
| | | text = typeof results[i] === 'object' ? (results[i].display || results[i].name) : results[i]; |
| | | type = typeof results[i] === 'object' ? results[i].type : ''; |
| | | id = i + this.env.contacts.length; |
| | | $('<li>').attr('id', 'rcmkSearchItem' + id) |
| | |
| | | .html(this.quote_html(text.replace(new RegExp('('+RegExp.escape(value)+')', 'ig'), '##$1%%')).replace(/##([^%]+)%%/g, '<b>$1</b>')) |
| | | .addClass(type || '') |
| | | .appendTo(ul) |
| | | .mouseover(function() { ref.ksearch_select(this); }) |
| | | .mouseup(function() { ref.ksearch_click(this); }) |
| | | .get(0)._rcm_id = id; |
| | | maxlen -= 1; |
| | | } |
| | |
| | | $(this.gui_objects.addresslist_title).html(this.get_label('contacts')); |
| | | } |
| | | |
| | | this.select_folder(folder, '', true); |
| | | if (!this.env.search_id) |
| | | this.select_folder(folder, '', true); |
| | | |
| | | // load contacts remotely |
| | | if (this.gui_objects.contactslist) { |
| | |
| | | |
| | | // find list (UL) element |
| | | if (type == 'contactsearch') |
| | | ul = this.gui_objects.folderlist; |
| | | ul = this.gui_objects.savedsearchlist; |
| | | else |
| | | ul = $('ul.groups', this.get_folder_li(this.env.source,'',true)); |
| | | |
| | |
| | | .html(prop.name); |
| | | |
| | | this.env.contactfolders[key] = this.env.contactgroups[key] = prop; |
| | | this.treelist.insert({ id:key, html:link, classes:['contactgroup'] }, prop.source, true); |
| | | this.treelist.insert({ id:key, html:link, classes:['contactgroup'] }, prop.source, 'contactgroup'); |
| | | |
| | | this.triggerEvent('group_insert', { id:prop.id, source:prop.source, name:prop.name, li:this.treelist.get_item(key) }); |
| | | }; |
| | |
| | | .html(name), |
| | | prop = { name:name, id:id }; |
| | | |
| | | this.treelist.insert({ id:key, html:link, classes:['contactsearch'] }, null, 'contactsearch'); |
| | | this.savedsearchlist.insert({ id:key, html:link, classes:['contactsearch'] }, null, 'contactsearch'); |
| | | this.select_folder(key,'',true); |
| | | this.enable_command('search-delete', true); |
| | | this.env.search_id = id; |
| | |
| | | this.remove_search_item = function(id) |
| | | { |
| | | var li, key = 'S'+id; |
| | | if (this.treelist.remove(key)) { |
| | | if (this.savedsearchlist.remove(key)) { |
| | | this.triggerEvent('search_delete', { id:id, li:li }); |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | this.reset_qsearch(); |
| | | this.select_folder('S'+id, '', true); |
| | | |
| | | if (this.savedsearchlist) { |
| | | this.treelist.select(''); |
| | | this.savedsearchlist.select('S'+id); |
| | | } |
| | | else |
| | | this.select_folder('S'+id, '', true); |
| | | |
| | | // reset vars |
| | | this.env.current_page = 1; |
| | |
| | | id = this.env.iid ? this.env.iid : selection[0]; |
| | | |
| | | // submit request with appended token |
| | | if (confirm(this.get_label('deleteidentityconfirm'))) |
| | | this.goto_url('delete-identity', { _iid: id, _token: this.env.request_token }, true); |
| | | |
| | | return true; |
| | | if (id && confirm(this.get_label('deleteidentityconfirm'))) |
| | | this.http_post('settings/delete-identity', { _iid: id }, true); |
| | | }; |
| | | |
| | | this.update_identity_row = function(id, name, add) |
| | |
| | | frame.location.href = this.env.blankpage; |
| | | } |
| | | } |
| | | |
| | | this.enable_command('delete', false); |
| | | }; |
| | | |
| | | this.remove_identity = function(id) |
| | | { |
| | | var frame, list = this.identity_list, |
| | | rid = this.html_identifier(id); |
| | | |
| | | if (list && id) { |
| | | list.remove_row(rid); |
| | | if (this.env.contentframe && (frame = this.get_frame_window(this.env.contentframe))) { |
| | | frame.location.href = this.env.blankpage; |
| | | } |
| | | } |
| | | |
| | | this.enable_command('delete', false); |
| | | }; |
| | | |
| | | |
| | |
| | | |
| | | this.last_sub_rx = RegExp('['+delim+']?[^'+delim+']+$'); |
| | | |
| | | this.subscription_list = new rcube_list_widget(this.gui_objects.subscriptionlist, |
| | | {multiselect:false, draggable:true, keyboard:true, toggleselect:true}); |
| | | this.subscription_list = new rcube_treelist_widget(this.gui_objects.subscriptionlist, { |
| | | selectable: true |
| | | }); |
| | | |
| | | this.subscription_list |
| | | .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() { ref.focus_subscription(row.id); }; |
| | | row.obj.onmouseout = function() { ref.unfocus_subscription(row.id); }; |
| | | }) |
| | | .init() |
| | | .focus(); |
| | | .addEventListener('select', function(node) { ref.subscription_select(node.id); }) |
| | | .draggable({cancel: '#mailboxroot'}) |
| | | .droppable({ |
| | | // @todo: find better way, accept callback is executed for every folder |
| | | // 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) { |
| | | var source = ref.env.subscriptionrows[$(node).attr('id')], |
| | | dest = ref.env.subscriptionrows[this.id], |
| | | source_name = source[0], |
| | | dest_name = dest[0]; |
| | | |
| | | $('#mailboxroot') |
| | | .mouseover(function(){ ref.focus_subscription(this.id); }) |
| | | .mouseout(function(){ ref.unfocus_subscription(this.id); }) |
| | | }; |
| | | |
| | | this.focus_subscription = function(id) |
| | | { |
| | | var row, folder; |
| | | |
| | | if (this.drag_active && this.env.mailbox && (row = document.getElementById(id))) |
| | | if (this.env.subscriptionrows[id] && |
| | | (folder = this.env.subscriptionrows[id][0]) !== null |
| | | ) { |
| | | if (this.check_droptarget(folder) && |
| | | !this.env.subscriptionrows[this.get_folder_row_id(this.env.mailbox)][2] && |
| | | folder != this.env.mailbox.replace(this.last_sub_rx, '') && |
| | | !folder.startsWith(this.env.mailbox + this.env.delimiter) |
| | | ) { |
| | | this.env.dstfolder = folder; |
| | | $(row).addClass('droptarget'); |
| | | return !source[2] |
| | | && dest_name != source_name.replace(ref.last_sub_rx, '') |
| | | && !dest_name.startsWith(source_name + ref.env.delimiter); |
| | | }, |
| | | drop: function(e, ui) { |
| | | ref.subscription_move_folder(ui.draggable.attr('id'), this.id); |
| | | } |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | this.unfocus_subscription = function(id) |
| | | this.subscription_select = function(id) |
| | | { |
| | | var row = $('#'+id); |
| | | var folder; |
| | | |
| | | this.env.dstfolder = null; |
| | | |
| | | if (row.length && this.env.subscriptionrows[id]) |
| | | row.removeClass('droptarget'); |
| | | else |
| | | $(this.subscription_list.frame).removeClass('droptarget'); |
| | | }; |
| | | |
| | | this.subscription_select = function(list) |
| | | { |
| | | var id, folder; |
| | | |
| | | if (list && (id = list.get_single_selection()) && |
| | | (folder = this.env.subscriptionrows['rcmrow'+id]) |
| | | ) { |
| | | if (id && id != 'mailboxroot' && (folder = this.env.subscriptionrows[id])) { |
| | | this.env.mailbox = folder[0]; |
| | | this.show_folder(folder[0]); |
| | | this.enable_command('delete-folder', !folder[2]); |
| | |
| | | } |
| | | }; |
| | | |
| | | this.subscription_move_folder = function(list) |
| | | this.subscription_move_folder = function(from, to) |
| | | { |
| | | if (this.env.mailbox && this.env.dstfolder !== null && |
| | | this.env.dstfolder != this.env.mailbox && |
| | | this.env.dstfolder != this.env.mailbox.replace(this.last_sub_rx, '') |
| | | ) { |
| | | var path = this.env.mailbox.split(this.env.delimiter), |
| | | basename = path.pop(), |
| | | newname = this.env.dstfolder === '' ? basename : this.env.dstfolder + this.env.delimiter + basename; |
| | | var source = this.env.subscriptionrows[from][0]; |
| | | dest = this.env.subscriptionrows[to][0]; |
| | | |
| | | if (newname != this.env.mailbox) { |
| | | this.http_post('rename-folder', {_folder_oldname: this.env.mailbox, _folder_newname: newname}, this.set_busy(true, 'foldermoving')); |
| | | this.subscription_list.draglayer.hide(); |
| | | if (source && dest !== null && source != dest && dest != source.replace(this.last_sub_rx, '')) { |
| | | var path = source.split(this.env.delimiter), |
| | | basename = path.pop(), |
| | | newname = dest === '' ? basename : dest + this.env.delimiter + basename; |
| | | |
| | | if (newname != source) { |
| | | this.http_post('rename-folder', {_folder_oldname: source, _folder_newname: newname}, |
| | | this.set_busy(true, 'foldermoving')); |
| | | } |
| | | } |
| | | |
| | | this.drag_active = false; |
| | | this.unfocus_subscription(this.get_folder_row_id(this.env.dstfolder)); |
| | | }; |
| | | |
| | | // tell server to create and subscribe a new mailbox |
| | |
| | | folder = this.env.subscriptionrows[id][0]; |
| | | |
| | | if (folder && confirm(this.get_label('deletefolderconfirm'))) { |
| | | var lock = this.set_busy(true, 'folderdeleting'); |
| | | this.http_post('delete-folder', {_mbox: folder}, lock); |
| | | this.http_post('delete-folder', {_mbox: folder}, this.set_busy(true, 'folderdeleting')); |
| | | } |
| | | }; |
| | | |
| | |
| | | |
| | | var row, n, tmp, tmp_name, rowid, collator, |
| | | folders = [], list = [], slist = [], |
| | | tbody = this.gui_objects.subscriptionlist.tBodies[0], |
| | | refrow = $('tr', tbody).get(1), |
| | | id = 'rcmrow'+((new Date).getTime()); |
| | | list_element = $(this.gui_objects.subscriptionlist), |
| | | refrow = $('li', list_element).get(1), |
| | | id = 'rcmli'+((new Date).getTime()); |
| | | |
| | | if (!refrow) { |
| | | // Refresh page if we don't have a table row to clone |
| | |
| | | row.attr({id: id, 'class': class_name}); |
| | | |
| | | // set folder name |
| | | row.find('td:first').html(display_name); |
| | | $('.name', row).html(display_name); |
| | | |
| | | // update subscription checkbox |
| | | $('input[name="_subscribed[]"]', row).val(name) |
| | |
| | | |
| | | // add row to the table |
| | | if (rowid) |
| | | $('#'+rowid).after(row); |
| | | $('#' + rowid).after(row); |
| | | else |
| | | row.appendTo(tbody); |
| | | list_element.append(row); |
| | | |
| | | // update list widget |
| | | this.subscription_list.clear_selection(); |
| | | this.subscription_list.select(); |
| | | |
| | | if (!skip_init) |
| | | this.init_subscription_list(); |
| | | |
| | |
| | | if (!this.gui_objects.subscriptionlist) { |
| | | if (this.is_framed) |
| | | return parent.rcmail.replace_folder_row(oldfolder, newfolder, display_name, is_protected, class_name); |
| | | |
| | | return false; |
| | | } |
| | | |
| | | var i, n, len, name, dispname, oldrow, tmprow, row, level, |
| | | tbody = this.gui_objects.subscriptionlist.tBodies[0], |
| | | folders = this.env.subscriptionrows, |
| | | id = this.get_folder_row_id(oldfolder), |
| | | prefix_len = oldfolder.length, |
| | |
| | | // no renaming, only update class_name |
| | | if (oldfolder == newfolder) { |
| | | $('#'+id).attr('class', class_name || ''); |
| | | this.subscription_list.focus(); |
| | | return; |
| | | } |
| | | |
| | |
| | | for (i=level; i<0; i++) |
| | | dispname = ' ' + dispname; |
| | | } |
| | | row.find('td:first').html(dispname); |
| | | $('.name', row).html(dispname); |
| | | this.env.subscriptionrows[id][1] = dispname; |
| | | } |
| | | } |
| | |
| | | |
| | | this._remove_folder_row = function(id) |
| | | { |
| | | this.subscription_list.remove_row(id.replace(/^rcmrow/, '')); |
| | | $('#'+id).remove(); |
| | | this.subscription_list.remove(id.replace(/^rcmli/, '')); |
| | | $('#' + id).remove(); |
| | | delete this.env.subscriptionrows[id]; |
| | | }; |
| | | |
| | |
| | | // mark a mailbox as selected and set environment variable |
| | | this.select_folder = function(name, prefix, encode) |
| | | { |
| | | if (this.savedsearchlist) { |
| | | this.savedsearchlist.select(''); |
| | | } |
| | | |
| | | if (this.treelist) { |
| | | this.treelist.select(name); |
| | | } |
| | |
| | | |
| | | $(form).attr({ |
| | | target: frame_name, |
| | | action: this.url(action, { _id:this.env.compose_id||'', _uploadid:ts }), |
| | | action: this.url(action, {_id: this.env.compose_id || '', _uploadid: ts, _from: this.env.action}), |
| | | method: 'POST'}) |
| | | .attr(form.encoding ? 'encoding' : 'enctype', 'multipart/form-data') |
| | | .submit(); |
| | |
| | | $.ajax({ |
| | | type: 'POST', |
| | | dataType: 'json', |
| | | url: ref.url(ref.env.filedrop.action||'upload', { _id:ref.env.compose_id||ref.env.cid||'', _uploadid:ts, _remote:1 }), |
| | | url: ref.url(ref.env.filedrop.action || 'upload', {_id: ref.env.compose_id||ref.env.cid||'', _uploadid: ts, _remote: 1, _from: ref.env.action}), |
| | | contentType: formdata ? false : 'multipart/form-data; boundary=' + boundary, |
| | | processData: false, |
| | | timeout: 0, // disable default timeout set in ajaxSetup() |