X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=program%2Fjs%2Fapp.js;h=c871cc66356370d9bb6541afcc1e6d2ede3dae96;hb=76507f7c63a660742e76889ad6e3919f3dde3bb0;hp=19dbc351740735eb2e05f218337f71ecd3d63766;hpb=d326b0c67bb536d2296004c927e89ab8c4a548b5;p=roundcube.git diff --git a/program/js/app.js b/program/js/app.js index 19dbc35..c871cc6 100644 --- a/program/js/app.js +++ b/program/js/app.js @@ -1,3779 +1,213 @@ -/* - +-----------------------------------------------------------------------+ - | RoundCube Webmail Client Script | - | | - | This file is part of the RoundCube Webmail client | - | Copyright (C) 2005-2008, RoundCube Dev, - Switzerland | - | Licensed under the GNU GPL | - | | - +-----------------------------------------------------------------------+ - | Authors: Thomas Bruederli | - | Charles McNulty | - +-----------------------------------------------------------------------+ - | Requires: common.js, list.js | - +-----------------------------------------------------------------------+ - - $Id: app.js 1170 2008-03-03 09:06:53Z thomasb $ -*/ - - -var rcube_webmail_client; - -function rcube_webmail() - { - this.env = new Object(); - this.labels = new Object(); - this.buttons = new Object(); - this.gui_objects = new Object(); - this.commands = new Object(); - this.onloads = new Array(); - - // create protected reference to myself - rcube_webmail_client = this; - this.ref = 'rcube_webmail_client'; - var ref = this; - - // webmail client settings - this.dblclick_time = 500; - this.message_time = 3000; - - this.identifier_expr = new RegExp('[^0-9a-z\-_]', 'gi'); - - // mimetypes supported by the browser (default settings) - this.mimetypes = new Array('text/plain', 'text/html', 'text/xml', - 'image/jpeg', 'image/gif', 'image/png', - 'application/x-javascript', 'application/pdf', - 'application/x-shockwave-flash'); - - // default environment vars - this.env.keep_alive = 60; // seconds - this.env.request_timeout = 180; // seconds - this.env.draft_autosave = 0; // seconds - this.env.comm_path = './'; - this.env.bin_path = './bin/'; - this.env.blankpage = 'program/blank.gif'; - - - // set environment variable(s) - this.set_env = function(p, value) - { - if (p != null && typeof(p) == 'object' && !value) - for (var n in p) - this.env[n] = p[n]; - else - this.env[p] = value; - }; - - - // add a localized label to the client environment - this.add_label = function(key, value) - { - this.labels[key] = value; - }; - - - // add a button to the button list - this.register_button = function(command, id, type, act, sel, over) - { - if (!this.buttons[command]) - this.buttons[command] = new Array(); - - var button_prop = {id:id, type:type}; - if (act) button_prop.act = act; - if (sel) button_prop.sel = sel; - if (over) button_prop.over = over; - - this.buttons[command][this.buttons[command].length] = button_prop; - }; - - // register a specific gui object - this.gui_object = function(name, id) - { - this.gui_objects[name] = id; - }; - - // execute the given script on load - this.add_onload = function(f) - { - this.onloads[this.onloads.length] = f; - }; - - // initialize webmail client - this.init = function() - { - var p = this; - this.task = this.env.task; - - // check browser - if (!bw.dom || !bw.xmlhttp_test()) - { - this.goto_url('error', '_code=0x199'); - return; - } - - // find all registered gui objects - for (var n in this.gui_objects) - this.gui_objects[n] = rcube_find_object(this.gui_objects[n]); - - // tell parent window that this frame is loaded - if (this.env.framed && parent.rcmail && parent.rcmail.set_busy) - parent.rcmail.set_busy(false); - - // enable general commands - this.enable_command('logout', 'mail', 'addressbook', 'settings', true); - - switch (this.task) - { - case 'mail': - if (this.gui_objects.messagelist) - { - this.message_list = new rcube_list_widget(this.gui_objects.messagelist, {multiselect:true, draggable:true, keyboard:true, dblclick_time:this.dblclick_time}); - this.message_list.row_init = function(o){ p.init_message_row(o); }; - this.message_list.addEventListener('dblclick', function(o){ p.msglist_dbl_click(o); }); - this.message_list.addEventListener('keypress', function(o){ p.msglist_keypress(o); }); - this.message_list.addEventListener('select', function(o){ p.msglist_select(o); }); - this.message_list.addEventListener('dragstart', function(o){ p.drag_active = true; }); - this.message_list.addEventListener('dragend', function(o){ p.drag_active = false; }); - - this.message_list.init(); - this.enable_command('toggle_status', true); - - if (this.gui_objects.mailcontframe) - { - this.gui_objects.mailcontframe.onmousedown = function(e){ return p.click_on_list(e); }; - document.onmouseup = function(e){ return p.doc_mouse_up(e); }; - } - else - this.message_list.focus(); - } - - if (this.env.coltypes) - this.set_message_coltypes(this.env.coltypes); - - // enable mail commands - this.enable_command('list', 'checkmail', 'compose', 'add-contact', 'search', 'reset-search', true); - - if (this.env.search_text != null && document.getElementById('quicksearchbox') != null) - document.getElementById('quicksearchbox').value = this.env.search_text; - - if (this.env.action=='show' || this.env.action=='preview') - { - this.enable_command('show', 'reply', 'reply-all', 'forward', 'moveto', 'delete', 'mark', 'viewsource', 'print', 'load-attachment', true); - if (this.env.next_uid) - { - this.enable_command('nextmessage', true); - this.enable_command('lastmessage', true); - } - if (this.env.prev_uid) - { - this.enable_command('previousmessage', true); - this.enable_command('firstmessage', true); - } - } - - if (this.env.trash_mailbox && this.env.mailbox != this.env.trash_mailbox) - this.set_alttext('delete', 'movemessagetotrash'); - - // make preview/message frame visible - if (this.env.action == 'preview' && this.env.framed && parent.rcmail) - { - this.enable_command('compose', 'add-contact', false); - parent.rcmail.show_contentframe(true); - parent.rcmail.mark_message('read', this.env.uid); - } - - if ((this.env.action=='show' || this.env.action=='preview') && this.env.blockedobjects) - { - if (this.gui_objects.remoteobjectsmsg) - this.gui_objects.remoteobjectsmsg.style.display = 'block'; - this.enable_command('load-images', true); - } - - if (this.env.action=='compose') - { - this.enable_command('add-attachment', 'send-attachment', 'remove-attachment', 'send', true); - if (this.env.spellcheck) - { - this.env.spellcheck.spelling_state_observer = function(s){ ref.set_spellcheck_state(s); }; - this.set_spellcheck_state('ready'); - } - if (this.env.drafts_mailbox) - this.enable_command('savedraft', true); - } - - if (this.env.messagecount) - this.enable_command('select-all', 'select-none', 'sort', 'expunge', true); - - if (this.env.messagecount && (this.env.mailbox==this.env.trash_mailbox || this.env.mailbox==this.env.junk_mailbox)) - this.enable_command('purge', true); - - this.set_page_buttons(); - - // focus main window - if (this.env.framed && window.parent) - window.parent.focus(); - else - window.focus(); - - // init message compose form - if (this.env.action=='compose') - this.init_messageform(); - - // show printing dialog - if (this.env.action=='print') - window.print(); - - // get unread count for each mailbox - if (this.gui_objects.mailboxlist) - { - this.gui_objects.folderlist = this.gui_objects.mailboxlist; - this.http_request('getunread', ''); - } - - // ask user to send MDN - if (this.env.mdn_request && this.env.uid) - { - var mdnurl = '_uid='+this.env.uid+'&_mbox='+urlencode(this.env.mailbox); - if (confirm(this.get_label('mdnrequest'))) - this.http_post('sendmdn', mdnurl); - else - this.http_post('mark', mdnurl+'&_flag=mdnsent'); - } - - break; - - - case 'addressbook': - if (this.gui_objects.contactslist) - { - this.contact_list = new rcube_list_widget(this.gui_objects.contactslist, {multiselect:true, draggable:true, keyboard:true}); - this.contact_list.addEventListener('keypress', function(o){ p.contactlist_keypress(o); }); - this.contact_list.addEventListener('select', function(o){ p.contactlist_select(o); }); - this.contact_list.addEventListener('dragstart', function(o){ p.drag_active = true; }); - this.contact_list.addEventListener('dragend', function(o){ p.drag_active = false; }); - this.contact_list.init(); - - if (this.env.cid) - this.contact_list.highlight_row(this.env.cid); - - if (this.gui_objects.contactslist.parentNode) - { - this.gui_objects.contactslist.parentNode.onmousedown = function(e){ return p.click_on_list(e); }; - document.onmouseup = function(e){ return p.doc_mouse_up(e); }; - } - else - this.contact_list.focus(); - } - - this.set_page_buttons(); - - if (this.env.address_sources && !this.env.address_sources[this.env.source].readonly) - this.enable_command('add', true); - - if (this.env.cid) - this.enable_command('show', 'edit', true); - - if ((this.env.action=='add' || this.env.action=='edit') && this.gui_objects.editform) - this.enable_command('save', true); - else - this.enable_command('search', 'reset-search', 'moveto', true); - - this.enable_command('list', true); - break; - - - case 'settings': - this.enable_command('preferences', 'identities', 'save', 'folders', true); - - if (this.env.action=='identities' || this.env.action=='edit-identity' || this.env.action=='add-identity') - this.enable_command('edit', 'add', 'delete', true); - - if (this.env.action=='edit-identity' || this.env.action=='add-identity') - this.enable_command('save', true); - - if (this.env.action=='folders') - this.enable_command('subscribe', 'unsubscribe', 'create-folder', 'rename-folder', 'delete-folder', true); - - if (this.gui_objects.identitieslist) - { - this.identity_list = new rcube_list_widget(this.gui_objects.identitieslist, {multiselect:false, draggable:false, keyboard:false}); - this.identity_list.addEventListener('select', function(o){ p.identity_select(o); }); - this.identity_list.init(); - this.identity_list.focus(); - - if (this.env.iid) - this.identity_list.highlight_row(this.env.iid); - } - - if (this.gui_objects.subscriptionlist) - this.init_subscription_list(); - - break; - - case 'login': - var input_user = rcube_find_object('rcmloginuser'); - var input_pass = rcube_find_object('rcmloginpwd'); - if (input_user) - input_user.onkeypress = function(e){ return rcmail.login_user_keypress(e); }; - if (input_user && input_user.value=='') - input_user.focus(); - else if (input_pass) - input_pass.focus(); - - this.enable_command('login', true); - break; - - default: - break; - } - - - // enable basic commands - this.enable_command('logout', true); - - // flag object as complete - this.loaded = true; - - // show message - if (this.pending_message) - this.display_message(this.pending_message[0], this.pending_message[1]); - - // start keep-alive interval - this.start_keepalive(); - - - // execute all foreign onload scripts - for (var i=0; i=0) - { - if (props.mimetype == 'text/html') - qstring += '&_safe=1'; - this.attachment_win = window.open(this.env.comm_path+'&_action=get&'+qstring+'&_frame=1', 'rcubemailattachment'); - if (this.attachment_win) - { - setTimeout(function(){ ref.attachment_win.focus(); }, 10); - break; - } - } - - this.goto_url('get', qstring+'&_download=1', false); - break; - - case 'select-all': - this.message_list.select_all(props); - break; - - case 'select-none': - this.message_list.clear_selection(); - break; - - case 'nextmessage': - if (this.env.next_uid) - this.show_message(this.env.next_uid, false, this.env.action=='preview'); - break; - - case 'lastmessage': - if (this.env.last_uid) - this.show_message(this.env.last_uid); - break; - - case 'previousmessage': - if (this.env.prev_uid) - this.show_message(this.env.prev_uid, false, this.env.action=='preview'); - break; - - case 'firstmessage': - if (this.env.first_uid) - this.show_message(this.env.first_uid); - break; - - case 'checkmail': - this.check_for_recent(); - break; - - case 'compose': - var url = this.env.comm_path+'&_action=compose'; - - if (this.task=='mail' && this.env.mailbox==this.env.drafts_mailbox) - { - var uid; - if (uid = this.get_single_uid()) - url += '&_draft_uid='+uid+'&_mbox='+urlencode(this.env.mailbox); - } - // modify url if we're in addressbook - else if (this.task=='addressbook') - { - // switch to mail compose step directly - if (props && props.indexOf('@') > 0) - { - url = this.get_task_url('mail', url); - this.redirect(url + '&_to='+urlencode(props)); - break; - } - - // use contact_id passed as command parameter - var a_cids = new Array(); - if (props) - a_cids[a_cids.length] = props; - // get selected contacts - else if (this.contact_list) - { - var selection = this.contact_list.get_selection(); - for (var n=0; n 0 ? true : false)); - } - else - { - this.enable_command('show', 'reply', 'reply-all', 'forward', 'print', selected); - this.enable_command('delete', 'moveto', 'mark', (list.selection.length > 0 ? true : false)); - } - - // start timer for message preview (wait for double click) - if (selected && this.env.contentframe) - this.preview_timer = setTimeout(function(){ ref.msglist_get_preview(); }, this.dblclick_time + 10); - else if (this.env.contentframe) - this.show_contentframe(false); - }; - - - this.msglist_dbl_click = function(list) - { - if (this.preview_timer) - clearTimeout(this.preview_timer); - - var uid = list.get_single_selection(); - if (uid && this.env.mailbox == this.env.drafts_mailbox) - this.goto_url('compose', '_draft_uid='+uid+'&_mbox='+urlencode(this.env.mailbox), true); - else if (uid) - this.show_message(uid, false, false); - }; - - - this.msglist_keypress = function(list) - { - if (list.key_pressed == list.ENTER_KEY) - this.command('show'); - else if (list.key_pressed == list.DELETE_KEY) - this.command('delete'); - else - list.shiftkey = false; - }; - - - this.msglist_get_preview = function() - { - var uid = this.get_single_uid(); - if (uid && this.env.contentframe && !this.drag_active) - this.show_message(uid, false, true); - else if (this.env.contentframe) - this.show_contentframe(false); - }; - - - this.check_droptarget = function(id) - { - if (this.task == 'mail') - return (id != this.env.mailbox); - else if (this.task == 'addressbook') - return (id != this.env.source && this.env.address_sources[id] && !this.env.address_sources[id].readonly); - else if (this.task == 'settings') - return (id != this.env.folder); - }; - - - /*********************************************************/ - /********* (message) list functionality *********/ - /*********************************************************/ - - - // when user doble-clicks on a row - this.show_message = function(id, safe, preview) - { - var add_url = ''; - var action = preview ? 'preview': 'show'; - var target = window; - if (preview && this.env.contentframe && window.frames && window.frames[this.env.contentframe]) - { - target = window.frames[this.env.contentframe]; - add_url = '&_framed=1'; - } - - if (safe) - add_url = '&_safe=1'; - - // also send search request to get the right messages - if (this.env.search_request) - add_url += '&_search='+this.env.search_request; - - if (id) - { - var url = '&_action='+action+'&_uid='+id+'&_mbox='+urlencode(this.env.mailbox)+add_url; - if (action == 'preview' && String(target.location.href).indexOf(url) >= 0) - this.show_contentframe(true); - else - { - this.set_busy(true, 'loading'); - target.location.href = this.env.comm_path+url; - } - } - }; - - - this.show_contentframe = function(show) - { - var frm; - if (this.env.contentframe && (frm = rcube_find_object(this.env.contentframe))) - { - if (!show && window.frames[this.env.contentframe] && frames[this.env.contentframe].location.href.indexOf(this.env.blankpage)<0) - frames[this.env.contentframe].location.href = this.env.blankpage; - if (!bw.safari) - frm.style.display = show ? 'block' : 'none'; - } - - if (!show && this.busy) - this.set_busy(false); - }; - - - // list a specific page - this.list_page = function(page) - { - if (page=='next') - page = this.env.current_page+1; - if (page=='last') - page = this.env.pagecount; - if (page=='prev' && this.env.current_page>1) - page = this.env.current_page-1; - if (page=='first' && this.env.current_page>1) - page = 1; - - if (page > 0 && page <= this.env.pagecount) - { - this.env.current_page = page; - - if (this.task=='mail') - this.list_mailbox(this.env.mailbox, page); - else if (this.task=='addressbook') - this.list_contacts(this.env.source, page); - } - }; - - - // list messages of a specific mailbox - this.list_mailbox = function(mbox, page, sort) - { - this.last_selected = 0; - var add_url = ''; - var target = window; - - if (!mbox) - mbox = this.env.mailbox; - - // add sort to url if set - if (sort) - add_url += '&_sort=' + sort; - - // also send search request to get the right messages - if (this.env.search_request) - add_url += '&_search='+this.env.search_request; - - // set page=1 if changeing to another mailbox - if (!page && mbox != this.env.mailbox) - { - page = 1; - this.env.current_page = page; - if (this.message_list) - this.message_list.clear_selection(); - this.show_contentframe(false); - } - - if (mbox != this.env.mailbox || (mbox == this.env.mailbox && !page && !sort)) - add_url += '&_refresh=1'; - - this.select_folder(mbox, this.env.mailbox); - this.env.mailbox = mbox; - - // load message list remotely - if (this.gui_objects.messagelist) - { - this.list_mailbox_remote(mbox, page, add_url); - return; - } - - if (this.env.contentframe && window.frames && window.frames[this.env.contentframe]) - { - target = window.frames[this.env.contentframe]; - add_url += '&_framed=1'; - } - - // load message list to target frame/window - if (mbox) - { - this.set_busy(true, 'loading'); - target.location.href = this.env.comm_path+'&_mbox='+urlencode(mbox)+(page ? '&_page='+page : '')+add_url; - } - }; - - - // send remote request to load message list - this.list_mailbox_remote = function(mbox, page, add_url) - { - // clear message list first - this.message_list.clear(); - - // send request to server - var url = '_mbox='+urlencode(mbox)+(page ? '&_page='+page : ''); - this.set_busy(true, 'loading'); - this.http_request('list', url+add_url, true); - }; - - - this.expunge_mailbox = function(mbox) - { - var lock = false; - var add_url = ''; - - // lock interface if it's the active mailbox - if (mbox == this.env.mailbox) - { - lock = true; - this.set_busy(true, 'loading'); - add_url = '&_reload=1'; - } - - // send request to server - var url = '_mbox='+urlencode(mbox); - this.http_post('expunge', url+add_url, lock); - }; - - - this.purge_mailbox = function(mbox) - { - var lock = false; - var add_url = ''; - - if (!confirm(this.get_label('purgefolderconfirm'))) - return false; - - // lock interface if it's the active mailbox - if (mbox == this.env.mailbox) - { - lock = true; - this.set_busy(true, 'loading'); - add_url = '&_reload=1'; - } - - // send request to server - var url = '_mbox='+urlencode(mbox); - this.http_post('purge', url+add_url, lock); - return true; - }; - - - // move selected messages to the specified mailbox - this.move_messages = function(mbox) - { - // exit if current or no mailbox specified or if selection is empty - if (!mbox || mbox == this.env.mailbox || (!this.env.uid && (!this.message_list || !this.message_list.get_selection().length))) - return; - - var lock = false; - var add_url = '&_target_mbox='+urlencode(mbox)+'&_from='+(this.env.action ? this.env.action : ''); - - // show wait message - if (this.env.action=='show') - { - lock = true; - this.set_busy(true, 'movingmessage'); - } - else - this.show_contentframe(false); - - // Hide message command buttons until a message is selected - this.enable_command('reply', 'reply-all', 'forward', 'delete', 'mark', 'print', false); - - this._with_selected_messages('moveto', lock, add_url); - }; - - // delete selected messages from the current mailbox - this.delete_messages = function() - { - var selection = this.message_list ? this.message_list.get_selection() : new Array(); - - // exit if no mailbox specified or if selection is empty - if (!this.env.uid && !selection.length) - return; - - // if there is a trash mailbox defined and we're not currently in it: - if (this.env.trash_mailbox && String(this.env.mailbox).toLowerCase() != String(this.env.trash_mailbox).toLowerCase()) - { - // if shift was pressed delete it immediately - if (this.message_list && this.message_list.shiftkey) - { - if (confirm(this.get_label('deletemessagesconfirm'))) - this.permanently_remove_messages(); - } - else - this.move_messages(this.env.trash_mailbox); - } - // if there is a trash mailbox defined but we *are* in it: - else if (this.env.trash_mailbox && String(this.env.mailbox).toLowerCase() == String(this.env.trash_mailbox).toLowerCase()) - this.permanently_remove_messages(); - // if there isn't a defined trash mailbox and the config is set to flag for deletion - else if (!this.env.trash_mailbox && this.env.flag_for_deletion) - { - this.mark_message('delete'); - if(this.env.action=="show") - this.command('nextmessage','',this); - else if (selection.length == 1) - this.message_list.select_next(); - } - // if there isn't a defined trash mailbox and the config is set NOT to flag for deletion - else if (!this.env.trash_mailbox) - this.permanently_remove_messages(); - }; - - - // delete the selected messages permanently - this.permanently_remove_messages = function() - { - // exit if no mailbox specified or if selection is empty - if (!this.env.uid && (!this.message_list || !this.message_list.get_selection().length)) - return; - - this.show_contentframe(false); - this._with_selected_messages('delete', false, '&_from='+(this.env.action ? this.env.action : '')); - }; - - // Send a specifc request with UIDs of all selected messages - // @private - this._with_selected_messages = function(action, lock, add_url) - { - var a_uids = new Array(); - if (this.env.uid) - a_uids[a_uids.length] = this.env.uid; - else - { - var selection = this.message_list.get_selection(); - var id; - for (var n=0; n 0) - { - rows[uid].classname = rows[uid].classname.replace(/\s*deleted/, ''); - this.set_classname(rows[uid].obj, 'deleted', false); - } - if (rows[uid].unread && this.env.unreadicon) - icn_src = this.env.unreadicon; - else if (rows[uid].replied && this.env.repliedicon) - icn_src = this.env.repliedicon; - else if (this.env.messageicon) - icn_src = this.env.messageicon; - if (rows[uid].icon && icn_src) - rows[uid].icon.src = icn_src; - } - } - - this.http_post('mark', '_uid='+a_uids.join(',')+'&_flag=undelete'); - return true; - }; - - - this.flag_as_deleted = function(a_uids) - { - // if deleting message from "view message" don't bother with delete icon - if (this.env.action == "show") - return false; - - var rows = this.message_list.rows; - for (var i=0; i=0) - message = message.substring(0, p-1) + message.substring(p+sig.length, message.length); - } - - // add the new signature string - if (this.env.signatures && this.env.signatures[id]) - { - sig = this.env.signatures[id]['text']; - if (this.env.signatures[id]['is_html']) - { - sig = this.env.signatures[id]['plain_text']; - } - if (sig.indexOf('-- ')!=0) - sig = '-- \n'+sig; - message += '\n'+sig; - } - } - else - { - var eid = tinyMCE.getEditorId('_message'); - // editor is a TinyMCE_Control object - var editor = tinyMCE.getInstanceById(eid); - // if this is null, we should exit - if (editor == null) { - return false; - } - var msgDoc = editor.getDoc(); - var msgBody = msgDoc.body; - - if (this.env.signatures && this.env.signatures[id]) - { - // Append the signature as a span within the body - var sigElem = msgDoc.getElementById("_rc_sig"); - if (!sigElem) - { - sigElem = msgDoc.createElement("span"); - sigElem.setAttribute("id", "_rc_sig"); - msgBody.appendChild(sigElem); - } - if (this.env.signatures[id]['is_html']) - { - sigElem.innerHTML = this.env.signatures[id]['text']; - } - else - { - sigElem.innerHTML = '
' + this.env.signatures[id]['text'] + '
'; - } - } - } - - if (input_message) - input_message.value = message; - - this.env.identity = id; - return true; - }; - - - this.show_attachment_form = function(a) - { - if (!this.gui_objects.uploadbox) - return false; - - var elm, list; - if (elm = this.gui_objects.uploadbox) - { - if (a && (list = this.gui_objects.attachmentlist)) - { - var pos = rcube_get_object_pos(list); - var left = pos.x; - var top = pos.y + list.offsetHeight + 10; - - elm.style.top = top+'px'; - elm.style.left = left+'px'; - } - - elm.style.visibility = a ? 'visible' : 'hidden'; - } - - // clear upload form - try { - if (!a && this.gui_objects.attachmentform != this.gui_objects.messageform) - this.gui_objects.attachmentform.reset(); - } - catch(e){} // ignore errors - - return true; - }; - - - // upload attachment file - this.upload_file = function(form) - { - if (!form) - return false; - - // get file input fields - var send = false; - for (var n=0; n