/* +-----------------------------------------------------------------------+ | RoundCube Webmail Client Script | | | | This file is part of the RoundCube Webmail client | | Copyright (C) 2005, RoundCube Dev, - Switzerland | | Licensed under the GNU GPL | | | +-----------------------------------------------------------------------+ | Author: Thomas Bruederli | +-----------------------------------------------------------------------+ $Id$ */ // Constants var CONTROL_KEY = 1; var SHIFT_KEY = 2; var CONTROL_SHIFT_KEY = 3; 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(); // 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'); // 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('markread', true); } // enable mail commands this.enable_command('list', 'compose', 'add-contact', true); if (this.env.action=='show') { this.enable_command('show', 'reply', 'reply-all', 'forward', 'moveto', 'delete', 'viewsource', 'print', 'load-attachment', true); 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('add-attachment', 'send-attachment', 'send', 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': 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', 'delete-folder', true); 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.use_arrow_keys(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 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; }; this.click_on_list = function(e) { if (!e) e = window.event; this.in_message_list = true; e.cancelBubble = true; }; // reset last clicked if user clicks on anything other than the message table this.use_arrow_keys = function(e, msg_list_frame) { if (this.in_message_list != true) return true; var keyCode = document.layers ? e.which : document.all ? event.keyCode : document.getElementById ? e.keyCode : 0; var mod_key = this.get_modifier(e); var scroll_to = 0; var last_selected_row = this.list_rows[this.last_selected]; if (keyCode == 40) { // down arrow key pressed var new_row = last_selected_row.obj.nextSibling; while (new_row && new_row.nodeType != 1) { new_row = new_row.nextSibling; } if (!new_row) return false; scroll_to = (Number(new_row.offsetTop) + Number(new_row.offsetHeight)) - Number(msg_list_frame.offsetHeight); } else if (keyCode == 38) { // up arrow key pressed var new_row = last_selected_row.obj.previousSibling; while (new_row && new_row.nodeType != 1) { new_row = new_row.previousSibling; } if (!new_row) return false; scroll_to = new_row.offsetTop; } else {return true;} if (mod_key != CONTROL_KEY) this.select_row(new_row.uid,mod_key); if (((Number(new_row.offsetTop)) < (Number(msg_list_frame.scrollTop))) || ((Number(new_row.offsetTop) + Number(new_row.offsetHeight)) > (Number(msg_list_frame.scrollTop) + Number(msg_list_frame.offsetHeight)))) { msg_list_frame.scrollTop = scroll_to; } 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; n0 ? true : false); } else if (this.task=='addressbook') { this.enable_command('edit', /*'print',*/ selected); this.enable_command('delete', 'compose', this.selection.length>0 ? true : false); } }; // selects or unselects the proper row depending on the modifier key pressed this.select_row = function(id,mod_key) { 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; this.highlight_row(id, true); break; } case CONTROL_SHIFT_KEY: { this.shift_select(id,true); break; } default: { this.highlight_row(id, false); break; } } } this.last_selected = id; }; 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) { 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(); } 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); }; // move selected messages to the specified mailbox this.move_messages = function(mbox) { // exit if no mailbox specified or if selection is empty if (!mbox || !(this.selection.length || this.env.uid) || mbox==this.env.mailbox) return; 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) 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; }; 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(); }; // upload attachment file this.upload_file = function(form) { if (!form) return false; // get file input fields var send = false; for (var n=0; n