/* +-----------------------------------------------------------------------+ | RoundCube Webmail Client Script | | | | This file is part of the RoundCube Webmail client | | Copyright (C) 2005, RoundCube Dev, - Switzerland | | Licensed under the GNU GPL | | | +-----------------------------------------------------------------------+ | Authors: Thomas Bruederli | | Charles McNulty | +-----------------------------------------------------------------------+ $Id: app.js 249 2006-05-25 18:25:04Z thomasb $ */ // Constants var CONTROL_KEY = 1; var SHIFT_KEY = 2; var CONTROL_SHIFT_KEY = 3; var CARET_DEBUG = 0; var CARET_DEBUG2 = 0; 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.selection = new Array(); this.last_selected = 0; this.in_message_list = false; // create public reference to myself rcube_webmail_client = this; this.ref = 'rcube_webmail_client'; // webmail client settings this.dblclick_time = 600; this.message_time = 5000; this.request_timeout = 180000; this.kepp_alive_interval = 60000; this.mbox_expression = new RegExp('[^0-9a-z\-_]', 'gi'); this.env.blank_img = 'skins/default/images/blank.gif'; // 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'); // mimetypes Caret wants to open in a window. (Others will be 'Save as...') this.mimetypes = new Array('text/plain', 'text/html', 'text/xml', 'application/x-javascript', 'application/x-shockwave-flash'); // set environment variable this.set_env = function(name, value) { //if (!this.busy) this.env[name] = 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; }; // initialize webmail client this.init = function() { this.task = this.env.task; // check browser if (!bw.dom || !bw.xmlhttp_test()) { location.href = this.env.comm_path+'&_action=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': var msg_list_frame = this.gui_objects.mailcontframe; var msg_list = this.gui_objects.messagelist; if (msg_list) { msg_list_frame.onmousedown = function(e){return rcube_webmail_client.click_on_list(e);}; this.init_messagelist(msg_list); this.enable_command('toggle_status', true); } // enable mail commands this.enable_command('list', 'compose', 'add-contact', 'search', 'reset-search', true); if (this.env.action=='show') { this.enable_command('show', 'reply', 'reply-all', 'forward', 'moveto', 'delete', 'viewsource', 'print', 'load-attachment', true); this.enable_command('spam', ( (this.env.mailbox != "Spam") && (this.env.mailbox != "Drafts") && (this.env.mailbox != "Sent") ) ? true : false); // HACK Caret this.enable_command('nonspam', this.env.mailbox == "Spam" ? true : false); // HACK Caret if (this.env.next_uid) this.enable_command('nextmessage', true); if (this.env.prev_uid) this.enable_command('previousmessage', true); } if (this.env.action=='show' && 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('del_attachment', true); this.enable_command('add-attachment', 'send-attachment', 'send', true); if (this.env.spellcheck) this.enable_command('spellcheck', 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.enable_command('purge', true); this.set_page_buttons(); // focus this window 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.http_request('getunread', ''); break; case 'addressbook': var contacts_list = this.gui_objects.contactslist; var ldap_contacts_list = this.gui_objects.ldapcontactslist; if (contacts_list) this.init_contactslist(contacts_list); if (ldap_contacts_list) this.init_ldapsearchlist(ldap_contacts_list); this.set_page_buttons(); 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); this.enable_command('list', 'add', true); this.enable_command('ldappublicsearch', this.env.ldappublicsearch); break; case 'settings': if (CARET_DEBUG) alert("gui_objects Init zooi: "+ this.env.action); 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); this.enable_command('caretforward', 'caretautoreply', 'caretpass', 'caretfilter', true); if (this.env.action=='caretfilter' || this.env.action=='edit-caretfilter' || this.env.action=='add-caretfilter' ) this.enable_command('enable', 'disable', 'delete-caretfilter', 'edit-caretfilter', true); if (this.env.action=='caretfilter' || this.env.action=='edit-caretfilter' ) this.enable_command('add-caretfilter', true); if (this.env.action=='caretforward' || this.env.action=='save-caretforward' ) this.enable_command('forward-enable', 'forward-disable', 'caretforward-change', 'save-caretforward', true); if (this.env.action=='caretautoreply' || this.env.action=='save-caretautoreply' ) this.enable_command('autoreply-enable', 'autoreply-disable', 'caretautoreply-change', 'save-caretautoreply', true); if (this.env.action=='caretpass' ) this.enable_command('caretpass-change', true); if (this.env.action=='edit-caretfilter' || this.env.action=='add-caretfilter') { this.enable_command('save-caretfilter', true); /* Set focus on match field */ var input_match = rcube_find_object('_match'); if (input_match && input_match.value=='') input_match.focus(); } this.enable_command('caretfilter3', true); if (this.env.action=='show-caretfilter3' ) this.enable_command('edit-caretfilter3', true); if (this.env.action=='caretfilter3' || this.env.action=='edit-caretfilter3' || this.env.action=='add-caretfilter3' ) this.enable_command('enable', 'disable', 'delete-caretfilter3', 'edit-caretfilter3', true); if (this.env.action=='caretfilter3' || this.env.action=='edit-caretfilter3' ) this.enable_command('add-caretfilter3', true); if (this.env.action=='edit-caretfilter3' || this.env.action=='add-caretfilter3') { this.enable_command('save-caretfilter3', true); /* Set focus on match field */ var input_match = rcube_find_object('_match'); if (input_match && input_match.value=='') input_match.focus(); } // Dit spul disabled, dan werkt clicken op de regel niet meer.... var caretfilter3_list = this.gui_objects.caretfilter3list; if (caretfilter3_list) this.init_caretfilter3list(caretfilter3_list); var identities_list = this.gui_objects.identitieslist; if (identities_list) this.init_identitieslist(identities_list); break; case 'login': var input_user = rcube_find_object('_user'); var input_pass = rcube_find_object('_pass'); 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); // disable browser's contextmenus // document.oncontextmenu = function(){ return false; } // load body click event document.onmousedown = function(){ return rcube_webmail_client.reset_click(); }; document.onkeydown = function(e){ return rcube_webmail_client.key_pressed(e, msg_list_frame); }; // 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 interval for keep-alive/recent_check signal if (this.kepp_alive_interval && this.task=='mail' && this.gui_objects.messagelist) this.kepp_alive_int = setInterval(this.ref+'.check_for_recent()', this.kepp_alive_interval); else if (this.task!='login') this.kepp_alive_int = setInterval(this.ref+'.send_keep_alive()', this.kepp_alive_interval); }; // reset last clicked if user clicks on anything other than the message table this.reset_click = function() { this.in_message_list = false; for (var n=0; n (Number(msg_list_frame.scrollTop) + Number(msg_list_frame.offsetHeight)))) { msg_list_frame.scrollTop = scroll_to; } return false; }; this.use_delete_key = function(keyCode, mod_key, msg_list_frame){ this.command('delete','',this); return false; } // get all message rows from HTML table and init each row this.init_messagelist = function(msg_list) { if (msg_list && msg_list.tBodies[0]) { this.message_rows = new Array(); var row; for(var r=0; r=0) { this.attachment_win = window.open(url+'&_frame=1', 'rcubemailattachment'); if (this.attachment_win) { setTimeout(this.ref+'.attachment_win.focus()', 10); break; } } location.href = url; break; case 'select-all': this.select_all(props); break; case 'select-none': this.clear_selection(); break; case 'nextmessage': if (this.env.next_uid) this.show_message(this.env.next_uid); //location.href = this.env.comm_path+'&_action=show&_uid='+this.env.next_uid+'&_mbox='+this.env.mailbox; break; case 'previousmessage': if (this.env.prev_uid) this.show_message(this.env.prev_uid); //location.href = this.env.comm_path+'&_action=show&_uid='+this.env.prev_uid+'&_mbox='+this.env.mailbox; break; case 'compose': var url = this.env.comm_path+'&_action=compose'; // modify url if we're in addressbook if (this.task=='addressbook') { url = this.get_task_url('mail', url); var a_cids = new Array(); // use contact_id passed as command parameter if (props) a_cids[a_cids.length] = props; // get selected contacts else { if (!window.frames[this.env.contentframe].rcmail.selection.length) { for (var n=0; n 0 && this.env.mbox != 'Spam') { // enable learn-ham-button, make action copy ipv multi-moveto this.enable_command('nonspam', true); // HACK Caret // modify x_spam_status header, should only be triggered when Button is pushed ! // this.modify_spam_status(); } } this.list_rows[id].clicked = true; setTimeout(this.ref+'.list_rows['+id+'].clicked=false;', this.dblclick_time); return false; }; this.modify_spam_status = function() { var id; for (var n=0; n0 ? true : false); } else if ((this.task=='settings') && (this.env.action == 'caretfilter3')) { this.enable_command('edit-caretfilter3', selected); } }; // selects or unselects the proper row depending on the modifier key pressed this.select_row = function(id,mod_key,with_mouse) { if (!mod_key) { this.shift_start = id; this.highlight_row(id, false); } else { switch (mod_key) { case SHIFT_KEY: { this.shift_select(id,false); break; } case CONTROL_KEY: { this.shift_start = id; if (!with_mouse) this.highlight_row(id, true); break; } case CONTROL_SHIFT_KEY: { this.shift_select(id,true); break; } default: { this.highlight_row(id, false); break; } } } if (this.last_selected != 0) { this.set_classname(this.list_rows[this.last_selected].obj, 'focused', false);} this.last_selected = id; this.set_classname(this.list_rows[id].obj, 'focused', true); }; this.shift_select = function(id, control) { var from_rowIndex = this.list_rows[this.shift_start].obj.rowIndex; var to_rowIndex = this.list_rows[id].obj.rowIndex; var i = ((from_rowIndex < to_rowIndex)? from_rowIndex : to_rowIndex); var j = ((from_rowIndex > to_rowIndex)? from_rowIndex : to_rowIndex); // iterate through the entire message list for (var n in this.list_rows) { if ((this.list_rows[n].obj.rowIndex >= i) && (this.list_rows[n].obj.rowIndex <= j)) { if (!this.in_selection(n)) this.highlight_row(n, true); } else { if (this.in_selection(n) && !control) this.highlight_row(n, true); } } }; this.clear_selection = function() { for(var n=0; n1) page = this.env.current_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(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; // set page=1 if changeing to another mailbox if (!page && mbox != this.env.mailbox) { page = 1; add_url += '&_refresh=1'; this.env.current_page = page; this.clear_selection(); } // also send search request to get the right messages if (this.env.search_request) add_url += '&_search='+this.env.search_request; if (this.env.mailbox!=mbox) this.select_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='+escape(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.clear_message_list(); // send request to server var url = '_mbox='+escape(mbox)+(page ? '&_page='+page : ''); this.set_busy(true, 'loading'); this.http_request('list', url+add_url, true); }; this.clear_message_list = function() { var table = this.gui_objects.messagelist; var tbody = document.createElement('TBODY'); table.insertBefore(tbody, table.tBodies[0]); table.removeChild(table.tBodies[1]); this.message_rows = new Array(); this.list_rows = this.message_rows; }; 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='+escape(mbox); this.http_request('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='+escape(mbox); this.http_request('purge', url+add_url, lock); return true; }; // copy selected messages to the specified mailbox this.copy_messages = function(mbox, mbox2) { // exit if no mailbox specified or if selection is empty if (!mbox || !(this.selection.length || this.env.uid) || mbox==this.env.mailbox) return; var mbox2 = (mbox2 == null) ? "__EMPTY__" : mbox2; var a_uids = new Array(); if (this.env.uid) a_uids[a_uids.length] = this.env.uid; else { var id; for (var n=0; n 0) { this.message_rows[uid].classname = this.message_rows[uid].classname.replace(/\s*deleted/, ''); this.set_classname(this.message_rows[uid].obj, 'deleted', false); } if (this.message_rows[uid].unread && this.env.unreadicon) icn_src = this.env.unreadicon; else if (this.message_rows[uid].replied && this.env.repliedicon) icn_src = this.env.repliedicon; else if (this.env.messageicon) icn_src = this.env.messageicon; if (this.message_rows[uid].icon && icn_src) this.message_rows[uid].icon.src = icn_src; } } this.http_request('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; 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]; if (sig.indexOf('-- ')!=0) sig = '-- \n'+sig; message += '\n'+sig; } 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 if (!a && this.gui_objects.attachmentform && this.gui_objects.attachmentform!=this.gui_objects.messageform) this.gui_objects.attachmentform.reset(); 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