| | |
| | | |
| | | function rcube_webmail() |
| | | { |
| | | this.env = {}; |
| | | this.env = { recipients_separator:',', recipients_delimiter:', ' }; |
| | | this.labels = {}; |
| | | this.buttons = {}; |
| | | this.buttons_sel = {}; |
| | |
| | | // initialize webmail client |
| | | this.init = function() |
| | | { |
| | | var p = this; |
| | | var n, p = this; |
| | | this.task = this.env.task; |
| | | |
| | | // check browser |
| | |
| | | } |
| | | |
| | | // find all registered gui containers |
| | | for (var n in this.gui_containers) |
| | | for (n in this.gui_containers) |
| | | this.gui_containers[n] = $('#'+this.gui_containers[n]); |
| | | |
| | | // find all registered gui objects |
| | | for (var n in this.gui_objects) |
| | | for (n in this.gui_objects) |
| | | this.gui_objects[n] = rcube_find_object(this.gui_objects[n]); |
| | | |
| | | // init registered buttons |
| | |
| | | } |
| | | |
| | | // enable general commands |
| | | this.enable_command('logout', 'mail', 'addressbook', 'settings', 'save-pref', 'compose', 'undo', true); |
| | | this.enable_command('logout', 'mail', 'addressbook', 'settings', 'save-pref', 'compose', 'undo', 'about', true); |
| | | |
| | | if (this.env.permaurl) |
| | | this.enable_command('permaurl', true); |
| | |
| | | 'moveto', 'copy', 'delete', 'open', 'mark', 'edit', 'viewsource', 'download', |
| | | 'print', 'load-attachment', 'load-headers', 'forward-attachment']; |
| | | |
| | | if (this.env.action=='show' || this.env.action=='preview') { |
| | | if (this.env.action == 'show' || this.env.action == 'preview') { |
| | | this.enable_command(this.env.message_commands, this.env.uid); |
| | | this.enable_command('reply-list', this.env.list_post); |
| | | |
| | |
| | | if (this.gui_objects.folderlist) |
| | | this.env.contactfolders = $.extend($.extend({}, this.env.address_sources), this.env.contactgroups); |
| | | |
| | | this.enable_command('add', 'import', this.env.writable_source); |
| | | this.enable_command('list', 'listgroup', 'listsearch', 'advanced-search', true); |
| | | |
| | | if (this.gui_objects.contactslist) { |
| | | |
| | | this.contact_list = new rcube_list_widget(this.gui_objects.contactslist, |
| | |
| | | } |
| | | |
| | | this.update_group_commands(); |
| | | this.command('list'); |
| | | } |
| | | |
| | | this.set_page_buttons(); |
| | |
| | | if (this.env.action == 'add' || this.env.action == 'edit') |
| | | this.init_contact_form(); |
| | | } |
| | | |
| | | if (this.gui_objects.qsearchbox) { |
| | | this.enable_command('search', 'reset-search', 'moveto', true); |
| | | } |
| | | |
| | | if (this.contact_list && this.contact_list.rowcount > 0) |
| | | this.enable_command('export', true); |
| | | |
| | | this.enable_command('add', 'import', this.env.writable_source); |
| | | this.enable_command('list', 'listgroup', 'listsearch', 'advanced-search', true); |
| | | |
| | | // load contacts of selected source |
| | | if (!this.env.action) |
| | | this.command('list', this.env.source); |
| | | break; |
| | | |
| | | |
| | | case 'settings': |
| | | this.enable_command('preferences', 'identities', 'save', 'folders', true); |
| | |
| | | $('#rcmloginpwd').focus(); |
| | | |
| | | // detect client timezone |
| | | $('#rcmlogintz').val(new Date().getTimezoneOffset() / -60); |
| | | var dt = new Date(), |
| | | tz = dt.getTimezoneOffset() / -60, |
| | | stdtz = dt.getStdTimezoneOffset() / -60; |
| | | |
| | | $('#rcmlogintz').val(stdtz); |
| | | $('#rcmlogindst').val(tz > stdtz ? 1 : 0); |
| | | |
| | | // display 'loading' message on form submit, lock submit button |
| | | $('form').submit(function () { |
| | |
| | | // execute a specific command on the web client |
| | | this.command = function(command, props, obj) |
| | | { |
| | | var ret, uid, cid, url, flag; |
| | | |
| | | if (obj && obj.blur) |
| | | obj.blur(); |
| | | |
| | |
| | | } |
| | | |
| | | // check input before leaving compose step |
| | | if (this.task=='mail' && this.env.action=='compose' && $.inArray(command, this.env.compose_commands)<0) { |
| | | if (this.task == 'mail' && this.env.action == 'compose' && $.inArray(command, this.env.compose_commands)<0) { |
| | | if (this.cmp_hash != this.compose_field_hash() && !confirm(this.get_label('notsentwarning'))) |
| | | return false; |
| | | } |
| | | |
| | | // process external commands |
| | | if (typeof this.command_handlers[command] === 'function') { |
| | | var ret = this.command_handlers[command](props, obj); |
| | | ret = this.command_handlers[command](props, obj); |
| | | return ret !== undefined ? ret : (obj ? false : true); |
| | | } |
| | | else if (typeof this.command_handlers[command] === 'string') { |
| | | var ret = window[this.command_handlers[command]](props, obj); |
| | | ret = window[this.command_handlers[command]](props, obj); |
| | | return ret !== undefined ? ret : (obj ? false : true); |
| | | } |
| | | |
| | | // trigger plugin hooks |
| | | this.triggerEvent('actionbefore', {props:props, action:command}); |
| | | var ret = this.triggerEvent('before'+command, props); |
| | | ret = this.triggerEvent('before'+command, props); |
| | | if (ret !== undefined) { |
| | | // abort if one the handlers returned false |
| | | // abort if one of the handlers returned false |
| | | if (ret === false) |
| | | return false; |
| | | else |
| | | props = ret; |
| | | } |
| | | |
| | | ret = undefined; |
| | | |
| | | // process internal command |
| | | switch (command) { |
| | |
| | | this.switch_task(command); |
| | | break; |
| | | |
| | | case 'about': |
| | | location.href = '?_task=settings&_action=about'; |
| | | break; |
| | | |
| | | case 'permaurl': |
| | | if (obj && obj.href && obj.target) |
| | | return true; |
| | |
| | | return false; |
| | | |
| | | case 'open': |
| | | var uid; |
| | | if (uid = this.get_single_uid()) { |
| | | obj.href = '?_task='+this.env.task+'&_action=show&_mbox='+urlencode(this.env.mailbox)+'&_uid='+uid; |
| | | return true; |
| | |
| | | // common commands used in multiple tasks |
| | | case 'show': |
| | | if (this.task == 'mail') { |
| | | var uid = this.get_single_uid(); |
| | | uid = this.get_single_uid(); |
| | | if (uid && (!this.env.uid || uid != this.env.uid)) { |
| | | if (this.env.mailbox == this.env.drafts_mailbox) |
| | | this.goto_url('compose', '_draft_uid='+uid+'&_mbox='+urlencode(this.env.mailbox), true); |
| | |
| | | } |
| | | } |
| | | else if (this.task == 'addressbook') { |
| | | var cid = props ? props : this.get_single_cid(); |
| | | cid = props ? props : this.get_single_cid(); |
| | | if (cid && !(this.env.action == 'show' && cid == this.env.cid)) |
| | | this.load_contact(cid, 'show'); |
| | | } |
| | |
| | | break; |
| | | |
| | | case 'edit': |
| | | var cid; |
| | | if (this.task=='addressbook' && (cid = this.get_single_cid())) |
| | | this.load_contact(cid, 'edit'); |
| | | else if (this.task=='settings' && props) |
| | | this.load_identity(props, 'edit-identity'); |
| | | else if (this.task=='mail' && (cid = this.get_single_uid())) { |
| | | var url = (this.env.mailbox == this.env.drafts_mailbox) ? '_draft_uid=' : '_uid='; |
| | | url = (this.env.mailbox == this.env.drafts_mailbox) ? '_draft_uid=' : '_uid='; |
| | | this.goto_url('compose', url+cid+'&_mbox='+urlencode(this.env.mailbox), true); |
| | | } |
| | | break; |
| | |
| | | if (props && !props._row) |
| | | break; |
| | | |
| | | var uid, flag = 'read'; |
| | | flag = 'read'; |
| | | |
| | | if (props._row.uid) { |
| | | uid = props._row.uid; |
| | |
| | | if (props && !props._row) |
| | | break; |
| | | |
| | | var uid, flag = 'flagged'; |
| | | flag = 'flagged'; |
| | | |
| | | if (props._row.uid) { |
| | | uid = props._row.uid; |
| | |
| | | break; |
| | | |
| | | case 'compose': |
| | | var url = this.url('mail/compose'); |
| | | url = this.url('mail/compose'); |
| | | |
| | | if (this.task == 'mail') { |
| | | url += '&_mbox='+urlencode(this.env.mailbox); |
| | | |
| | | if (this.env.mailbox == this.env.drafts_mailbox) { |
| | | var uid; |
| | | if (uid = this.get_single_uid()) |
| | | url += '&_draft_uid='+uid; |
| | | } |
| | | else if (props) |
| | | if (props) |
| | | url += '&_to='+urlencode(props); |
| | | } |
| | | // modify url if we're in addressbook |
| | |
| | | } |
| | | |
| | | if (a_cids.length) |
| | | this.http_post('mailto', {_cid: a_cids.join(','), _source: this.env.source}, true); |
| | | this.http_post('mailto', { _cid: a_cids.join(','), _source: this.env.source}, true); |
| | | else if (this.env.group) |
| | | this.http_post('mailto', { _gid: this.env.group, _source: this.env.source}, true); |
| | | |
| | | break; |
| | | } |
| | |
| | | case 'reply-all': |
| | | case 'reply-list': |
| | | case 'reply': |
| | | var uid; |
| | | if (uid = this.get_single_uid()) { |
| | | var url = '_reply_uid='+uid+'&_mbox='+urlencode(this.env.mailbox); |
| | | url = '_reply_uid='+uid+'&_mbox='+urlencode(this.env.mailbox); |
| | | if (command == 'reply-all') |
| | | // do reply-list, when list is detected and popup menu wasn't used |
| | | url += '&_all=' + (!props && this.commands['reply-list'] ? 'list' : 'all'); |
| | |
| | | |
| | | case 'forward-attachment': |
| | | case 'forward': |
| | | var uid, url; |
| | | if (uid = this.get_single_uid()) { |
| | | url = '_forward_uid='+uid+'&_mbox='+urlencode(this.env.mailbox); |
| | | if (command == 'forward-attachment' || (!props && this.env.forward_attachment)) |
| | |
| | | break; |
| | | |
| | | case 'print': |
| | | var uid; |
| | | if (uid = this.get_single_uid()) { |
| | | ref.printwin = window.open(this.env.comm_path+'&_action=print&_uid='+uid+'&_mbox='+urlencode(this.env.mailbox)+(this.env.safemode ? '&_safe=1' : '')); |
| | | if (this.printwin) { |
| | |
| | | break; |
| | | |
| | | case 'viewsource': |
| | | var uid; |
| | | if (uid = this.get_single_uid()) { |
| | | ref.sourcewin = window.open(this.env.comm_path+'&_action=viewsource&_uid='+uid+'&_mbox='+urlencode(this.env.mailbox)); |
| | | if (this.sourcewin) |
| | |
| | | break; |
| | | |
| | | case 'download': |
| | | var uid; |
| | | if (uid = this.get_single_uid()) |
| | | this.goto_url('viewsource', '&_uid='+uid+'&_mbox='+urlencode(this.env.mailbox)+'&_save=1'); |
| | | break; |
| | |
| | | // unified command call (command name == function name) |
| | | default: |
| | | var func = command.replace(/-/g, '_'); |
| | | if (this[func] && typeof this[func] === 'function') |
| | | this[func](props); |
| | | if (this[func] && typeof this[func] === 'function') { |
| | | ret = this[func](props); |
| | | } |
| | | break; |
| | | } |
| | | |
| | | this.triggerEvent('after'+command, props); |
| | | if (this.triggerEvent('after'+command, props) === false) |
| | | ret = false; |
| | | this.triggerEvent('actionafter', {props:props, action:command}); |
| | | |
| | | return obj ? false : true; |
| | | return ret === false ? false : obj ? false : true; |
| | | }; |
| | | |
| | | // set command(s) enabled or disabled |
| | | this.enable_command = function() |
| | | { |
| | | var args = Array.prototype.slice.call(arguments), |
| | | var i, n, args = Array.prototype.slice.call(arguments), |
| | | enable = args.pop(), cmd; |
| | | |
| | | for (var n=0; n<args.length; n++) { |
| | | for (n=0; n<args.length; n++) { |
| | | cmd = args[n]; |
| | | // argument of type array |
| | | if (typeof cmd === 'string') { |
| | |
| | | } |
| | | // push array elements into commands array |
| | | else { |
| | | for (var i in cmd) |
| | | for (i in cmd) |
| | | args.push(cmd[i]); |
| | | } |
| | | } |
| | |
| | | this.initialBodyScrollTop = bw.ie ? 0 : window.pageYOffset; |
| | | this.initialListScrollTop = this.gui_objects.folderlist.parentNode.scrollTop; |
| | | |
| | | var li, pos, list, height; |
| | | list = $(this.gui_objects.folderlist); |
| | | pos = list.offset(); |
| | | var k, li, height, |
| | | list = $(this.gui_objects.folderlist); |
| | | pos = list.offset(); |
| | | |
| | | this.env.folderlist_coords = { x1:pos.left, y1:pos.top, x2:pos.left + list.width(), y2:pos.top + list.height() }; |
| | | |
| | | this.env.folder_coords = []; |
| | | for (var k in model) { |
| | | for (k in model) { |
| | | if (li = this.get_folder_li(k)) { |
| | | // only visible folders |
| | | if (height = li.firstChild.offsetHeight) { |
| | |
| | | this.drag_move = function(e) |
| | | { |
| | | if (this.gui_objects.folderlist && this.env.folder_coords) { |
| | | // offsets to compensate for scrolling while dragging a message |
| | | var boffset = bw.ie ? -document.documentElement.scrollTop : this.initialBodyScrollTop; |
| | | var moffset = this.initialListScrollTop-this.gui_objects.folderlist.parentNode.scrollTop; |
| | | var toffset = -moffset-boffset; |
| | | var li, div, pos, mouse, check, oldclass, |
| | | layerclass = 'draglayernormal'; |
| | | var k, li, div, check, oldclass, |
| | | layerclass = 'draglayernormal', |
| | | mouse = rcube_event.get_mouse_pos(e), |
| | | pos = this.env.folderlist_coords, |
| | | // offsets to compensate for scrolling while dragging a message |
| | | boffset = bw.ie ? -document.documentElement.scrollTop : this.initialBodyScrollTop, |
| | | moffset = this.initialListScrollTop-this.gui_objects.folderlist.parentNode.scrollTop; |
| | | |
| | | if (this.contact_list && this.contact_list.draglayer) |
| | | oldclass = this.contact_list.draglayer.attr('class'); |
| | | |
| | | mouse = rcube_event.get_mouse_pos(e); |
| | | pos = this.env.folderlist_coords; |
| | | mouse.y += toffset; |
| | | mouse.y += -moffset-boffset; |
| | | |
| | | // if mouse pointer is outside of folderlist |
| | | if (mouse.x < pos.x1 || mouse.x >= pos.x2 || mouse.y < pos.y1 || mouse.y >= pos.y2) { |
| | |
| | | } |
| | | |
| | | // over the folders |
| | | for (var k in this.env.folder_coords) { |
| | | for (k in this.env.folder_coords) { |
| | | pos = this.env.folder_coords[k]; |
| | | if (mouse.x >= pos.x1 && mouse.x < pos.x2 && mouse.y >= pos.y1 && mouse.y < pos.y2){ |
| | | if ((check = this.check_droptarget(k))) { |
| | | if ((check = this.check_droptarget(k))) { |
| | | li = this.get_folder_li(k); |
| | | div = $(li.getElementsByTagName('div')[0]); |
| | | |
| | |
| | | |
| | | this.folder_auto_expand = k; |
| | | this.folder_auto_timer = window.setTimeout(function() { |
| | | rcmail.command('collapse-folder', rcmail.folder_auto_expand); |
| | | rcmail.drag_start(null); |
| | | }, 1000); |
| | | rcmail.command('collapse-folder', rcmail.folder_auto_expand); |
| | | rcmail.drag_start(null); |
| | | }, 1000); |
| | | } else if (this.folder_auto_timer) { |
| | | window.clearTimeout(this.folder_auto_timer); |
| | | this.folder_auto_timer = null; |
| | |
| | | this.doc_mouse_up = function(e) |
| | | { |
| | | var model, list, li, id; |
| | | |
| | | // ignore event if jquery UI dialog is open |
| | | if ($(rcube_event.get_target(e)).closest('.ui-dialog, .ui-widget-overlay').length) |
| | | return; |
| | | |
| | | if (list = this.message_list) { |
| | | if (!rcube_mouse_is_over(e, list.list.parentNode)) |
| | |
| | | flags: flags.extra_flags |
| | | }); |
| | | |
| | | var c, html, tree = expando = '', |
| | | var c, n, col, html, tree = '', expando = '', |
| | | list = this.message_list, |
| | | rows = list.rows, |
| | | tbody = this.gui_objects.messagelist.tBodies[0], |
| | | rowcount = tbody.rows.length, |
| | | even = rowcount%2, |
| | | message = this.env.messages[uid], |
| | | css_class = 'message' |
| | | + (even ? ' even' : ' odd') |
| | | + (!flags.seen ? ' unread' : '') |
| | | + (flags.deleted ? ' deleted' : '') |
| | | + (flags.flagged ? ' flagged' : '') |
| | | + (flags.unread_children && flags.seen && !this.env.autoexpand_threads ? ' unroot' : '') |
| | | + (message.selected ? ' selected' : ''), |
| | | // for performance use DOM instead of jQuery here |
| | | row = document.createElement('tr'), |
| | | col = document.createElement('td'); |
| | | row = document.createElement('tr'); |
| | | |
| | | row.id = 'rcmrow'+uid; |
| | | row.className = css_class; |
| | |
| | | |
| | | // threads |
| | | if (this.env.threading) { |
| | | // This assumes that div width is hardcoded to 15px, |
| | | var width = message.depth * 15; |
| | | if (message.depth) { |
| | | // This assumes that div width is hardcoded to 15px, |
| | | tree += '<span id="rcmtab' + uid + '" class="branch" style="width:' + (message.depth * 15) + 'px;"> </span>'; |
| | | |
| | | if ((rows[message.parent_uid] && rows[message.parent_uid].expanded === false) |
| | | || ((this.env.autoexpand_threads == 0 || this.env.autoexpand_threads == 2) && |
| | | (!rows[message.parent_uid] || !rows[message.parent_uid].expanded)) |
| | |
| | | if (message.expanded === undefined && (this.env.autoexpand_threads == 1 || (this.env.autoexpand_threads == 2 && message.unread_children))) { |
| | | message.expanded = true; |
| | | } |
| | | } |
| | | |
| | | if (width) |
| | | tree += '<span id="rcmtab' + uid + '" class="branch" style="width:' + width + 'px;"> </span>'; |
| | | |
| | | if (message.has_children && !message.depth) |
| | | expando = '<div id="rcmexpando' + uid + '" class="' + (message.expanded ? 'expanded' : 'collapsed') + '"> </div>'; |
| | | } |
| | | } |
| | | |
| | | tree += '<span id="msgicn'+uid+'" class="'+css_class+'"> </span>'; |
| | |
| | | } |
| | | |
| | | // add each submitted col |
| | | for (var n in this.env.coltypes) { |
| | | for (n in this.env.coltypes) { |
| | | c = this.env.coltypes[n]; |
| | | col = document.createElement('td'); |
| | | col.className = String(c).toLowerCase(); |
| | |
| | | // list messages of a specific mailbox using filter |
| | | this.filter_mailbox = function(filter) |
| | | { |
| | | var search, lock = this.set_busy(true, 'searching'); |
| | | |
| | | if (this.gui_objects.qsearchbox) |
| | | search = this.gui_objects.qsearchbox.value; |
| | | var lock = this.set_busy(true, 'searching'); |
| | | |
| | | this.clear_message_list(); |
| | | |
| | | // reset vars |
| | | this.env.current_page = 1; |
| | | this.http_request('search', '_filter='+filter |
| | | + (search ? '&_q='+urlencode(search) : '') |
| | | + (this.env.mailbox ? '&_mbox='+urlencode(this.env.mailbox) : ''), lock); |
| | | this.http_request('search', this.search_params(false, filter), lock); |
| | | }; |
| | | |
| | | // list messages of a specific mailbox |
| | |
| | | |
| | | this.init_address_input_events = function(obj, props) |
| | | { |
| | | this.env.recipients_delimiter = this.env.recipients_separator + ' '; |
| | | |
| | | obj[bw.ie || bw.safari || bw.chrome ? 'keydown' : 'keypress'](function(e) { return ref.ksearch_keydown(e, this, props); }) |
| | | .attr('autocomplete', 'off'); |
| | | }; |
| | |
| | | |
| | | this.remove_from_attachment_list = function(name) |
| | | { |
| | | if (this.env.attachments[name]) |
| | | delete this.env.attachments[name]; |
| | | |
| | | if (!this.gui_objects.attachmentlist) |
| | | return false; |
| | | |
| | | var list = this.gui_objects.attachmentlist.getElementsByTagName("li"); |
| | | for (i=0; i<list.length; i++) |
| | | if (list[i].id == name) |
| | | this.gui_objects.attachmentlist.removeChild(list[i]); |
| | | delete this.env.attachments[name]; |
| | | $('#'+name).remove(); |
| | | }; |
| | | |
| | | this.remove_attachment = function(name) |
| | |
| | | this.qsearch = function(value) |
| | | { |
| | | if (value != '') { |
| | | var n, r, addurl = '', mods_arr = [], |
| | | mods = this.env.search_mods, |
| | | mbox = this.env.mailbox, |
| | | lock = this.set_busy(true, 'searching'); |
| | | var n, lock = this.set_busy(true, 'searching'); |
| | | |
| | | if (this.message_list) { |
| | | if (this.message_list) |
| | | this.clear_message_list(); |
| | | if (mods) |
| | | mods = mods[mbox] ? mods[mbox] : mods['*']; |
| | | } else if (this.contact_list) { |
| | | else if (this.contact_list) |
| | | this.list_contacts_clear(); |
| | | } |
| | | |
| | | // reset vars |
| | | this.env.current_page = 1; |
| | | r = this.http_request('search', this.search_params(value) |
| | | + (this.env.source ? '&_source='+urlencode(this.env.source) : '') |
| | | + (this.env.group ? '&_gid='+urlencode(this.env.group) : ''), lock); |
| | | |
| | | this.env.qsearch = {lock: lock, request: r}; |
| | | } |
| | | }; |
| | | |
| | | // build URL params for search |
| | | this.search_params = function(search, filter) |
| | | { |
| | | var n, url = [], mods_arr = [], |
| | | mods = this.env.search_mods, |
| | | mbox = this.env.mailbox; |
| | | |
| | | if (!filter && this.gui_objects.search_filter) |
| | | filter = this.gui_objects.search_filter.value; |
| | | |
| | | if (!search && this.gui_objects.qsearchbox) |
| | | search = this.gui_objects.qsearchbox.value; |
| | | |
| | | if (filter) |
| | | url.push('_filter=' + urlencode(filter)); |
| | | |
| | | if (search) { |
| | | url.push('_q='+urlencode(search)); |
| | | |
| | | if (mods && this.message_list) |
| | | mods = mods[mbox] ? mods[mbox] : mods['*']; |
| | | |
| | | if (mods) { |
| | | for (n in mods) |
| | | mods_arr.push(n); |
| | | addurl += '&_headers='+mods_arr.join(','); |
| | | url.push('_headers='+mods_arr.join(',')); |
| | | } |
| | | |
| | | if (this.gui_objects.search_filter) |
| | | addurl += '&_filter=' + this.gui_objects.search_filter.value; |
| | | |
| | | // reset vars |
| | | this.env.current_page = 1; |
| | | r = this.http_request('search', '_q='+urlencode(value) |
| | | + (mbox ? '&_mbox='+urlencode(mbox) : '') |
| | | + (this.env.source ? '&_source='+urlencode(this.env.source) : '') |
| | | + (this.env.group ? '&_gid='+urlencode(this.env.group) : '') |
| | | + (addurl ? addurl : ''), lock); |
| | | |
| | | this.env.qsearch = {lock: lock, request: r}; |
| | | } |
| | | |
| | | if (mbox) |
| | | url.push('_mbox='+urlencode(mbox)); |
| | | |
| | | return url.join('&'); |
| | | }; |
| | | |
| | | // reset quick-search form |
| | |
| | | |
| | | // insert all members of a group |
| | | if (typeof this.env.contacts[id] === 'object' && this.env.contacts[id].id) { |
| | | insert += this.env.contacts[id].name + ', '; |
| | | insert += this.env.contacts[id].name + this.env.recipients_delimiter; |
| | | this.group2expand = $.extend({}, this.env.contacts[id]); |
| | | this.group2expand.input = this.ksearch_input; |
| | | this.http_request('mail/group-expand', '_source='+urlencode(this.env.contacts[id].source)+'&_gid='+urlencode(this.env.contacts[id].id), false); |
| | | } |
| | | else if (typeof this.env.contacts[id] === 'string') { |
| | | insert = this.env.contacts[id] + ', '; |
| | | insert = this.env.contacts[id] + this.env.recipients_delimiter; |
| | | trigger = true; |
| | | } |
| | | |
| | |
| | | |
| | | // get string from current cursor pos to last comma |
| | | var cpos = this.get_caret_pos(this.ksearch_input), |
| | | p = inp_value.lastIndexOf(',', cpos-1), |
| | | p = inp_value.lastIndexOf(this.env.recipients_separator, cpos-1), |
| | | q = inp_value.substring(p+1, cpos), |
| | | min = this.env.autocomplete_min_length; |
| | | min = this.env.autocomplete_min_length, |
| | | ac = this.ksearch_data; |
| | | |
| | | // trim query string |
| | | q = $.trim(q); |
| | |
| | | if (!q.length) |
| | | return; |
| | | |
| | | // ...new search value contains old one and previous search result was empty |
| | | if (old_value && old_value.length && this.env.contacts && !this.env.contacts.length && q.indexOf(old_value) == 0) |
| | | // ...new search value contains old one and previous search was not finished or its result was empty |
| | | if (old_value && old_value.length && q.indexOf(old_value) == 0 && (!ac || !ac.num) && this.env.contacts && !this.env.contacts.length) |
| | | return; |
| | | |
| | | var i, lock, source, xhr, reqid = new Date().getTime(), |
| | |
| | | sources = props && props.sources ? props.sources : [], |
| | | action = props && props.action ? props.action : 'mail/autocomplete'; |
| | | |
| | | this.ksearch_data = {id: reqid, sources: sources.slice(), action: action, locks: [], requests: []}; |
| | | this.ksearch_data = {id: reqid, sources: sources.slice(), action: action, |
| | | locks: [], requests: [], num: sources.length}; |
| | | |
| | | for (i=0; i<threads; i++) { |
| | | source = this.ksearch_data.sources.shift(); |
| | |
| | | return; |
| | | |
| | | // display search results |
| | | var ul, li, text, init, |
| | | var i, len, ul, li, text, init, |
| | | value = this.ksearch_value, |
| | | data = this.ksearch_data, |
| | | maxlen = this.env.autocomplete_max ? this.env.autocomplete_max : 15; |
| | |
| | | } |
| | | |
| | | // add each result line to list |
| | | if (results && results.length) { |
| | | for (i=0; i < results.length && maxlen > 0; i++) { |
| | | if (results && (len = results.length)) { |
| | | for (i=0; i < len && maxlen > 0; i++) { |
| | | text = typeof results[i] === 'object' ? results[i].name : results[i]; |
| | | li = document.createElement('LI'); |
| | | li.innerHTML = text.replace(new RegExp('('+RegExp.escape(value)+')', 'ig'), '##$1%%').replace(/</g, '<').replace(/>/g, '>').replace(/##([^%]+)%%/g, '<b>$1</b>'); |
| | |
| | | } |
| | | } |
| | | |
| | | if (results && results.length) |
| | | if (len) |
| | | this.env.contacts = this.env.contacts.concat(results); |
| | | |
| | | // run next parallel search |
| | | if (data.id == reqid) { |
| | | data.num--; |
| | | if (maxlen > 0 && data.sources.length) { |
| | | var lock, xhr, source = data.sources.shift(); |
| | | if (source) { |
| | |
| | | } |
| | | } |
| | | |
| | | this.enable_command('compose', list.selection.length > 0); |
| | | this.enable_command('compose', this.env.group || list.selection.length > 0); |
| | | this.enable_command('edit', id && writable); |
| | | this.enable_command('delete', list.selection.length && writable); |
| | | |
| | |
| | | { |
| | | this.contact_list.clear(true); |
| | | this.show_contentframe(false); |
| | | this.enable_command('delete', 'compose', false); |
| | | this.enable_command('delete', false); |
| | | this.enable_command('compose', this.env.group ? true : false); |
| | | }; |
| | | |
| | | // load contact record |
| | |
| | | |
| | | this.delete_contacts = function() |
| | | { |
| | | var selection = this.contact_list.get_selection(), |
| | | undelete = this.env.address_sources[this.env.source].undelete; |
| | | |
| | | // exit if no mailbox specified or if selection is empty |
| | | var selection = this.contact_list.get_selection(); |
| | | var undelete = this.env.address_sources[this.env.source].undelete; |
| | | if (!(selection.length || this.env.cid) || (!undelete && !confirm(this.get_label('deletecontactconfirm')))) |
| | | return; |
| | | |
| | |
| | | qs += '&_search='+this.env.search_request; |
| | | |
| | | // send request to server |
| | | this.http_post('delete', '_cid='+urlencode(a_cids.join(','))+'&_source='+urlencode(this.env.source)+'&_from='+(this.env.action ? this.env.action : '')+qs); |
| | | this.http_post('delete', '_cid='+urlencode(a_cids.join(',')) |
| | | +'&_source='+urlencode(this.env.source) |
| | | +'&_from='+(this.env.action ? this.env.action : '')+qs, |
| | | this.display_message(this.get_label('contactdeleting'), 'loading')); |
| | | |
| | | return true; |
| | | }; |
| | |
| | | // add row to contacts list |
| | | this.add_contact_row = function(cid, cols, select) |
| | | { |
| | | if (!this.gui_objects.contactslist || !this.gui_objects.contactslist.tBodies[0]) |
| | | if (!this.gui_objects.contactslist) |
| | | return false; |
| | | |
| | | var tbody = this.gui_objects.contactslist.tBodies[0], |
| | | rowcount = tbody.rows.length, |
| | | even = rowcount%2, |
| | | var c, list = this.contact_list, |
| | | row = document.createElement('tr'); |
| | | |
| | | row.id = 'rcmrow'+String(cid).replace(this.identifier_expr, '_'); |
| | | row.className = 'contact '+(even ? 'even' : 'odd'); |
| | | row.className = 'contact'; |
| | | |
| | | if (this.contact_list.in_selection(cid)) |
| | | if (list.in_selection(cid)) |
| | | row.className += ' selected'; |
| | | |
| | | // add each submitted col |
| | | for (var c in cols) { |
| | | for (c in cols) { |
| | | col = document.createElement('td'); |
| | | col.className = String(c).toLowerCase(); |
| | | col.innerHTML = cols[c]; |
| | | row.appendChild(col); |
| | | } |
| | | |
| | | this.contact_list.insert_row(row); |
| | | list.insert_row(row); |
| | | |
| | | this.enable_command('export', (this.contact_list.rowcount > 0)); |
| | | this.enable_command('export', list.rowcount > 0); |
| | | }; |
| | | |
| | | this.init_contact_form = function() |
| | |
| | | ref.insert_edit_field($(this).val(), $(this).attr('rel'), this); |
| | | this.selectedIndex = 0; |
| | | }); |
| | | |
| | | // enable date pickers on date fields |
| | | if ($.datepicker && this.env.date_format) { |
| | | $.datepicker.setDefaults({ |
| | | dateFormat: this.env.date_format, |
| | | changeMonth: true, |
| | | changeYear: true, |
| | | yearRange: '-100:+10', |
| | | showOtherMonths: true, |
| | | selectOtherMonths: true, |
| | | monthNamesShort: this.env.month_names, |
| | | onSelect: function(dateText) { $(this).focus().val(dateText) } |
| | | }); |
| | | $('input.datepicker').datepicker(); |
| | | } |
| | | |
| | | $("input[type='text']:visible").first().focus(); |
| | | }; |
| | |
| | | |
| | | elem.focus(function(){ ref.focus_textfield(this); }) |
| | | .blur(function(){ ref.blur_textfield(this); }) |
| | | .each(function(){ this._placeholder = this.title = ref.env.coltypes[col].label; ref.blur_textfield(this); }); |
| | | .each(function(){ this._placeholder = this.title = (ref.env.coltypes[col].label || ''); ref.blur_textfield(this); }); |
| | | }; |
| | | |
| | | this.insert_edit_field = function(col, section, menu) |
| | |
| | | .appendTo(cell); |
| | | |
| | | this.init_edit_field(col, input); |
| | | |
| | | if (colprop.type == 'date' && $.datepicker) |
| | | input.datepicker(); |
| | | } |
| | | else if (colprop.type == 'composite') { |
| | | var childcol, cp, first, templ, cols = [], suffices = []; |
| | |
| | | // set button to a specific state |
| | | this.set_button = function(command, state) |
| | | { |
| | | var button, obj, a_buttons = this.buttons[command]; |
| | | var n, button, obj, a_buttons = this.buttons[command], |
| | | len = a_buttons ? a_buttons.length : 0; |
| | | |
| | | if (!a_buttons || !a_buttons.length) |
| | | return false; |
| | | |
| | | for (var n=0; n<a_buttons.length; n++) { |
| | | for (n=0; n<len; n++) { |
| | | button = a_buttons[n]; |
| | | obj = document.getElementById(button.id); |
| | | |
| | |
| | | // display a specific alttext |
| | | this.set_alttext = function(command, label) |
| | | { |
| | | if (!this.buttons[command] || !this.buttons[command].length) |
| | | return; |
| | | var n, button, obj, link, a_buttons = this.buttons[command], |
| | | len = a_buttons ? a_buttons.length : 0; |
| | | |
| | | var button, obj, link; |
| | | for (var n=0; n<this.buttons[command].length; n++) { |
| | | button = this.buttons[command][n]; |
| | | for (n=0; n<len; n++) { |
| | | button = a_buttons[n]; |
| | | obj = document.getElementById(button.id); |
| | | |
| | | if (button.type=='image' && obj) { |
| | | if (button.type == 'image' && obj) { |
| | | obj.setAttribute('alt', this.get_label(label)); |
| | | if ((link = obj.parentNode) && link.tagName.toLowerCase() == 'a') |
| | | link.setAttribute('title', this.get_label(label)); |
| | |
| | | // mouse over button |
| | | this.button_over = function(command, id) |
| | | { |
| | | var button, elm, a_buttons = this.buttons[command]; |
| | | var n, button, obj, a_buttons = this.buttons[command], |
| | | len = a_buttons ? a_buttons.length : 0; |
| | | |
| | | if (!a_buttons || !a_buttons.length) |
| | | return false; |
| | | |
| | | for (var n=0; n<a_buttons.length; n++) { |
| | | for (n=0; n<len; n++) { |
| | | button = a_buttons[n]; |
| | | if (button.id == id && button.status == 'act') { |
| | | elm = document.getElementById(button.id); |
| | | if (elm && button.over) { |
| | | obj = document.getElementById(button.id); |
| | | if (obj && button.over) { |
| | | if (button.type == 'image') |
| | | elm.src = button.over; |
| | | obj.src = button.over; |
| | | else |
| | | elm.className = button.over; |
| | | obj.className = button.over; |
| | | } |
| | | } |
| | | } |
| | |
| | | // mouse down on button |
| | | this.button_sel = function(command, id) |
| | | { |
| | | var button, elm, a_buttons = this.buttons[command]; |
| | | var n, button, obj, a_buttons = this.buttons[command], |
| | | len = a_buttons ? a_buttons.length : 0; |
| | | |
| | | if (!a_buttons || !a_buttons.length) |
| | | return; |
| | | |
| | | for (var n=0; n<a_buttons.length; n++) { |
| | | for (n=0; n<len; n++) { |
| | | button = a_buttons[n]; |
| | | if (button.id == id && button.status == 'act') { |
| | | elm = document.getElementById(button.id); |
| | | if (elm && button.sel) { |
| | | obj = document.getElementById(button.id); |
| | | if (obj && button.sel) { |
| | | if (button.type == 'image') |
| | | elm.src = button.sel; |
| | | obj.src = button.sel; |
| | | else |
| | | elm.className = button.sel; |
| | | obj.className = button.sel; |
| | | } |
| | | this.buttons_sel[id] = command; |
| | | } |
| | |
| | | // mouse out of button |
| | | this.button_out = function(command, id) |
| | | { |
| | | var button, elm, a_buttons = this.buttons[command]; |
| | | var n, button, obj, a_buttons = this.buttons[command], |
| | | len = a_buttons ? a_buttons.length : 0; |
| | | |
| | | if (!a_buttons || !a_buttons.length) |
| | | return; |
| | | |
| | | for (var n=0; n<a_buttons.length; n++) { |
| | | for (n=0; n<len; n++) { |
| | | button = a_buttons[n]; |
| | | if (button.id == id && button.status == 'act') { |
| | | elm = document.getElementById(button.id); |
| | | if (elm && button.act) { |
| | | obj = document.getElementById(button.id); |
| | | if (obj && button.act) { |
| | | if (button.type == 'image') |
| | | elm.src = button.act; |
| | | obj.src = button.act; |
| | | else |
| | | elm.className = button.act; |
| | | obj.className = button.act; |
| | | } |
| | | } |
| | | } |
| | | }; |
| | | |
| | | |
| | | this.focus_textfield = function(elem) |
| | | { |
| | |
| | | |
| | | this.toggle_prefer_html = function(checkbox) |
| | | { |
| | | var elem; |
| | | if (elem = document.getElementById('rcmfd_addrbook_show_images')) |
| | | elem.disabled = !checkbox.checked; |
| | | $('#rcmfd_addrbook_show_images').prop('disabled', !checkbox.checked); |
| | | }; |
| | | |
| | | this.toggle_preview_pane = function(checkbox) |
| | | { |
| | | var elem; |
| | | if (elem = document.getElementById('rcmfd_preview_pane_mark_read')) |
| | | elem.disabled = !checkbox.checked; |
| | | $('#rcmfd_preview_pane_mark_read').prop('disabled', !checkbox.checked); |
| | | }; |
| | | |
| | | // display fetched raw headers |
| | |
| | | |
| | | $.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); $(document.getElementById(id)).val(data); rcmail.log(data); } |
| | | success: function(data) { rcmail.set_busy(false, null, lock); $('#'+id).val(data); rcmail.log(data); } |
| | | }); |
| | | }; |
| | | |
| | | this.plain2html = function(plainText, id) |
| | | { |
| | | var lock = this.set_busy(true, 'converting'); |
| | | $(document.getElementById(id)).val('<pre>'+plainText+'</pre>'); |
| | | $('#'+id).val(plainText ? '<pre>'+plainText+'</pre>' : ''); |
| | | this.set_busy(false, null, lock); |
| | | }; |
| | | |