From 6b47de3f49e880f08fa4a9226e70d18129095306 Mon Sep 17 00:00:00 2001 From: thomascube Date: Sun, 24 Sep 2006 20:15:51 +0000 Subject: [PATCH] Partial client re-write with a common list class --- CHANGELOG | 8 + program/include/main.inc | 2 +- program/js/app.js | 1267 +++++++------------------ program/js/common.js | 123 ++- program/js/list.js | 704 ++++++++++++++ program/steps/addressbook/edit.inc | 2 +- program/steps/addressbook/func.inc | 1 + program/steps/addressbook/save.inc | 22 +- program/steps/mail/func.inc | 1 + program/steps/settings/identities.inc | 1 + skins/default/common.css | 12 + 11 files changed, 1202 insertions(+), 941 deletions(-) create mode 100644 program/js/list.js diff --git a/CHANGELOG b/CHANGELOG index 3319d38c1..4144b5a6d 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,14 @@ CHANGELOG RoundCube Webmail --------------------------- +2006/09/24 (thomasb) +---------- +- Partial client re-write with a common list class +- Re-enabled multi select of contacts (Bug #1484017) +- Enable contact editing right after creation (Bug #1459641) +- Updated Hungarian, Estonian and Traditional Chinese localization + + 2006/09/19 (thomasb) ---------- - Correct UTF-7 to UTF-8 conversion if mbstring is not available diff --git a/program/include/main.inc b/program/include/main.inc index c6e9857b0..b2e83b767 100644 --- a/program/include/main.inc +++ b/program/include/main.inc @@ -365,7 +365,7 @@ function load_gui() // add common javascripts $javascript = "var $JS_OBJECT_NAME = new rcube_webmail();\n"; - $javascript .= "$JS_OBJECT_NAME.set_env('comm_path', '$COMM_PATH');\n"; + $javascript .= sprintf("%s.set_env('comm_path', '%s');\n", $JS_OBJECT_NAME, str_replace('&', '&', $COMM_PATH)); if (isset($CONFIG['javascript_config'] )){ foreach ($CONFIG['javascript_config'] as $js_config_var){ diff --git a/program/js/app.js b/program/js/app.js index eedcd13e7..52050a9be 100644 --- a/program/js/app.js +++ b/program/js/app.js @@ -3,21 +3,19 @@ | RoundCube Webmail Client Script | | | | This file is part of the RoundCube Webmail client | - | Copyright (C) 2005, RoundCube Dev, - Switzerland | + | Copyright (C) 2005-2006, RoundCube Dev, - Switzerland | | Licensed under the GNU GPL | | | +-----------------------------------------------------------------------+ | Authors: Thomas Bruederli | | Charles McNulty | +-----------------------------------------------------------------------+ - + | Requires: common.js, list.js | + +-----------------------------------------------------------------------+ + $Id$ */ -// Constants -var CONTROL_KEY = 1; -var SHIFT_KEY = 2; -var CONTROL_SHIFT_KEY = 3; var rcube_webmail_client; @@ -28,9 +26,6 @@ function rcube_webmail() 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; @@ -93,12 +88,13 @@ function rcube_webmail() // initialize webmail client this.init = function() { + var p = this; this.task = this.env.task; // check browser if (!bw.dom || !bw.xmlhttp_test()) { - location.href = this.env.comm_path+'&_action=error&_code=0x199'; + this.goto_url('error', '_code=0x199'); return; } @@ -116,13 +112,26 @@ function rcube_webmail() switch (this.task) { case 'mail': - var msg_list_frame = this.gui_objects.mailcontframe; - var msg_list = this.gui_objects.messagelist; - if (msg_list) + if (this.gui_objects.messagelist) { - msg_list_frame.onmousedown = function(e){return rcube_webmail_client.click_on_list(e);}; - this.init_messagelist(msg_list); + 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(); } // enable mail commands @@ -183,26 +192,36 @@ function rcube_webmail() case 'addressbook': - var contacts_list = this.gui_objects.contactslist; - var ldap_contacts_list = this.gui_objects.ldapcontactslist; + if (this.gui_objects.contactslist) + { + this.contact_list = new rcube_list_widget(this.gui_objects.contactslist, {multiselect:true, draggable:false, 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.init(); - if (contacts_list) - this.init_contactslist(contacts_list); - - if (ldap_contacts_list) - this.init_ldapsearchlist(ldap_contacts_list); + 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.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); + // this.enable_command('ldappublicsearch', this.env.ldappublicsearch); break; @@ -218,10 +237,17 @@ function rcube_webmail() if (this.env.action=='folders') this.enable_command('subscribe', 'unsubscribe', 'create-folder', 'rename-folder', 'delete-folder', true); - - var identities_list = this.gui_objects.identitieslist; - if (identities_list) - this.init_identitieslist(identities_list); + + 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); + } break; @@ -244,13 +270,6 @@ function rcube_webmail() // 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; @@ -273,154 +292,25 @@ function rcube_webmail() } - // reset last clicked if user clicks on anything other than the message table - this.reset_click = function() - { - var id; - 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]) + // set eventhandler to message icon + if ((row.icon = row.obj.cells[0].childNodes[0]) && row.icon.nodeName=='IMG') { - - this.message_rows = new Array(); - - var row; - for(var r=0; r=0) { - this.attachment_win = window.open(url+'&_frame=1', 'rcubemailattachment'); + this.attachment_win = window.open(this.env.comm_path+'&_action=get'+url+'&_frame=1', 'rcubemailattachment'); if (this.attachment_win) { setTimeout(this.ref+'.attachment_win.focus()', 10); @@ -849,27 +640,25 @@ function rcube_webmail() } } - location.href = url; + this.goto_url('get', qstring+'&_download=1'); break; case 'select-all': - this.select_all(props); + this.message_list.select_all(props); break; case 'select-none': - this.clear_selection(); + this.message_list.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 'checkmail': @@ -894,14 +683,18 @@ function rcube_webmail() // use contact_id passed as command parameter if (props) a_cids[a_cids.length] = props; - // get selected contacts else { + var selection = this.contact_list.get_selection(); + for (var n=0; n0 ? true : false); } - else if (this.task=='addressbook') - { - if (this.contact_rows && this.selection.length==1) - { - this.load_contact(this.selection[0], 'show', true); - // change the text for the add contact button - var links = parent.document.getElementById('abooktoolbar').getElementsByTagName('A'); - for (i = 0; i < links.length; i++) - { - var onclickstring = new String(links[i].onclick); - if (onclickstring.search('\"add\"') != -1) - links[i].title = this.env.newcontact; - } - } - else if (this.contact_rows && this.contact_rows[id].clicked) - { - this.load_contact(id, 'show'); - return false; - } - else if (this.ldap_contact_rows && !this.ldap_contact_rows[id].clicked) - { - // clear selection - parent.rcmail.clear_selection(); - - // disable delete - parent.rcmail.set_button('delete', 'pas'); - - // change the text for the add contact button - var links = parent.document.getElementById('abooktoolbar').getElementsByTagName('A'); - for (i = 0; i < links.length; i++) - { - var onclickstring = new String(links[i].onclick); - if (onclickstring.search('\"add\"') != -1) - links[i].title = this.env.addcontact; - } - } - // handle double click event - else if (this.ldap_contact_rows && this.selection.length==1 && this.ldap_contact_rows[id].clicked) - this.command('compose', this.ldap_contact_rows[id].obj.cells[1].innerHTML); - else if (this.env.contentframe) - { - var elm = document.getElementById(this.env.contentframe); - elm.style.visibility = 'hidden'; - } - } - else if (this.task=='settings') + else { - if (this.selection.length==1) - this.command('edit', this.selection[0]); + this.enable_command('show', 'reply', 'reply-all', 'forward', 'print', selected); + this.enable_command('delete', 'moveto', list.selection.length>0 ? true : false); } - - this.list_rows[id].clicked = true; - setTimeout(this.ref+'.list_rows['+id+'].clicked=false;', this.dblclick_time); - - return false; - }; - + }; - /*********************************************************/ - /********* (message) list functionality *********/ - /*********************************************************/ - - // get next and previous rows that are not hidden - this.get_next_row = function(){ - if (!this.list_rows) return false; - var last_selected_row = this.list_rows[this.last_selected]; - var new_row = last_selected_row.obj.nextSibling; - while (new_row && (new_row.nodeType != 1 || new_row.style.display == 'none')) { - new_row = new_row.nextSibling; - } - return new_row; - } - - this.get_prev_row = function(){ - if (!this.list_rows) return false; - var last_selected_row = this.list_rows[this.last_selected]; - var new_row = last_selected_row.obj.previousSibling; - while (new_row && (new_row.nodeType != 1 || new_row.style.display == 'none')) { - new_row = new_row.previousSibling; - } - return new_row; - } - - // highlight/unhighlight a row - this.highlight_row = function(id, multiple) + this.msglist_dbl_click = function(list) { - var selected = false - - if (this.list_rows[id] && !multiple) - { - this.clear_selection(); - this.selection[0] = id; - this.list_rows[id].obj.className += ' selected'; - selected = true; - } - - else if (this.list_rows[id]) - { - if (!this.in_selection(id)) // select row - { - this.selection[this.selection.length] = id; - this.set_classname(this.list_rows[id].obj, 'selected', true); - } - else // unselect row - { - var p = find_in_array(id, this.selection); - var a_pre = this.selection.slice(0, p); - var a_post = this.selection.slice(p+1, this.selection.length); - this.selection = a_pre.concat(a_post); - this.set_classname(this.list_rows[id].obj, 'selected', false); - this.set_classname(this.list_rows[id].obj, 'unfocused', false); - } - selected = (this.selection.length==1); - } - - // enable/disable commands for message - if (this.task=='mail') - { - if (this.env.mailbox==this.env.drafts_mailbox) - { - this.enable_command('show', selected); - this.enable_command('delete', 'moveto', this.selection.length>0 ? true : false); - } - else - { - this.enable_command('show', 'reply', 'reply-all', 'forward', 'print', selected); - this.enable_command('delete', 'moveto', this.selection.length>0 ? true : false); - } - } - else if (this.task=='addressbook') - { - this.enable_command('edit', /*'print',*/ selected); - this.enable_command('delete', 'compose', this.selection.length>0 ? true : false); - } + 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); }; -// 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.list_rows[this.last_selected]) - 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() + this.msglist_keypress = function(list) { - 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 (rows[uid].classname.indexOf('deleted') > 0) { + rows[uid].classname = rows[uid].classname.replace(/\s*deleted/, ''); + this.set_classname(rows[uid].obj, 'deleted', false); } - if (this.message_rows[uid].unread && this.env.unreadicon) + if (rows[uid].unread && this.env.unreadicon) icn_src = this.env.unreadicon; - else if (this.message_rows[uid].replied && this.env.repliedicon) + else if (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; + if (rows[uid].icon && icn_src) + 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) { + 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' : ''; row.appendChild(col); - - if (attop && tbody.rows.length) - tbody.insertBefore(row, tbody.firstChild); - else - tbody.appendChild(row); - - this.init_message_row(row); + + this.message_list.insert_row(row, attop); }; @@ -3384,7 +2929,7 @@ function rcube_webmail() if (this.gui_objects.quotadisplay) this.gui_objects.quotadisplay.innerHTML = text; }; - + // update the mailboxlist this.set_unread_count = function(mbox, count, set_title) @@ -3433,7 +2978,7 @@ function rcube_webmail() // add row to contacts list - this.add_contact_row = function(cid, cols) + this.add_contact_row = function(cid, cols, select) { if (!this.gui_objects.contactslist || !this.gui_objects.contactslist.tBodies[0]) return false; @@ -3446,7 +2991,7 @@ function rcube_webmail() row.id = 'rcmrow'+cid; row.className = 'contact '+(even ? 'even' : 'odd'); - if (this.in_selection(cid)) + if (this.contact_list.in_selection(cid)) row.className += ' selected'; // add each submitted col @@ -3458,8 +3003,7 @@ function rcube_webmail() row.appendChild(col); } - tbody.appendChild(row); - this.init_table_row(row, 'contact_rows'); + this.contact_list.insert_row(row); }; @@ -3474,78 +3018,25 @@ function rcube_webmail() { tinyMCE.execCommand('mceRemoveControl', true, textElementName); } - } + }; + + /********************************************************/ - /********* drag & drop methods *********/ + /********* remote request methods *********/ /********************************************************/ - this.drag_mouse_move = function(e) + this.goto_url = function(action, query, lock) { - if (this.drag_start) - { - if (!this.draglayer) - this.draglayer = new rcube_layer('rcmdraglayer', {x:0, y:0, width:300, vis:0, zindex:2000}); - - // get subjects of selectedd messages - var names = ''; - var c, subject, obj; - for(var n=0; n12) // only show 12 lines - { - names += '...'; - break; - } - - if (this.message_rows[this.selection[n]].obj) - { - obj = this.message_rows[this.selection[n]].obj; - subject = ''; - - for(c=0; c 50 ? subject.substring(0, 50)+'...' : subject) + '
'; - } - } - } - - this.draglayer.write(names); - this.draglayer.show(1); - } - - var pos = this.get_mouse_pos(e); - this.draglayer.move(pos.x+20, pos.y-5); - - this.drag_start = false; - this.drag_active = true; - - return false; - }; - + if (lock) + this.set_busy(true); - this.drag_mouse_up = function() - { - document.onmousemove = null; - - if (this.draglayer && this.draglayer.visible) - this.draglayer.show(0); - - this.drag_active = false; - - return false; + var querystring = query ? '&'+query : ''; + location.href = this.env.comm_path+'&_action='+action+querystring; }; - - /********************************************************/ - /********* remote request methods *********/ - /********************************************************/ - - this.http_sockets = new Array(); // find a non-busy socket or create a new one @@ -3677,91 +3168,16 @@ function rcube_webmail() // and return the message uid this.get_single_uid = function() { - return this.env.uid ? this.env.uid : (this.selection.length==1 ? this.selection[0] : null); + return this.env.uid ? this.env.uid : (this.message_list ? this.message_list.get_single_selection() : null); }; // same as above but for contacts this.get_single_cid = function() { - return this.env.cid ? this.env.cid : (this.selection.length==1 ? this.selection[0] : null); + return this.env.cid ? this.env.cid : (this.contact_list ? this.contact_list.get_single_selection() : null); }; -/* deprecated methods - - // check if Shift-key is pressed on event - this.check_shiftkey = function(e) - { - if(!e && window.event) - e = window.event; - - if(bw.linux && bw.ns4 && e.modifiers) - return true; - else if((bw.ns4 && e.modifiers & Event.SHIFT_MASK) || (e && e.shiftKey)) - return true; - else - return false; - } - - // check if Shift-key is pressed on event - this.check_ctrlkey = function(e) - { - if(!e && window.event) - e = window.event; - - if(bw.linux && bw.ns4 && e.modifiers) - return true; - else if (bw.mac) - return this.check_shiftkey(e); - else if((bw.ns4 && e.modifiers & Event.CTRL_MASK) || (e && e.ctrlKey)) - return true; - else - return false; - } -*/ - - // returns modifier key (constants defined at top of file) - this.get_modifier = function(e) - { - var opcode = 0; - e = e || window.event; - - if (bw.mac && e) - { - opcode += (e.metaKey && CONTROL_KEY) + (e.shiftKey && SHIFT_KEY); - return opcode; - } - if (e) - { - opcode += (e.ctrlKey && CONTROL_KEY) + (e.shiftKey && SHIFT_KEY); - return opcode; - } - if (e.cancelBubble) - { - e.cancelBubble = true; - e.returnValue = false; - } - else if (e.preventDefault) - e.preventDefault(); - } - - - this.get_mouse_pos = function(e) - { - if(!e) e = window.event; - var mX = (e.pageX) ? e.pageX : e.clientX; - var mY = (e.pageY) ? e.pageY : e.clientY; - - if(document.body && document.all) - { - mX += document.body.scrollLeft; - mY += document.body.scrollTop; - } - - return { x:mX, y:mY }; - }; - - this.get_caret_pos = function(obj) { if (typeof(obj.selectionEnd)!='undefined') @@ -3826,7 +3242,10 @@ function rcube_webmail() -// class for HTTP requests +/** + * Class for sending HTTP requests + * @constructor + */ function rcube_http_request() { this.url = ''; @@ -3889,7 +3308,7 @@ function rcube_http_request() { // default value for contentType if not provided contentType = typeof(contentType) != 'undefined' ? - contentType : 'application/x-www-form-urlencoded'; + contentType : 'application/x-www-form-urlencoded'; this.build(); diff --git a/program/js/common.js b/program/js/common.js index b0dc5564a..d5ecf8f89 100644 --- a/program/js/common.js +++ b/program/js/common.js @@ -3,7 +3,7 @@ | RoundCube common js library | | | | This file is part of the RoundCube web development suite | - | Copyright (C) 2005, RoundCube Dev, - Switzerland | + | Copyright (C) 2005-2006, RoundCube Dev, - Switzerland | | Licensed under the GNU GPL | | | +-----------------------------------------------------------------------+ @@ -13,8 +13,16 @@ $Id$ */ +// Constants +var CONTROL_KEY = 1; +var SHIFT_KEY = 2; +var CONTROL_SHIFT_KEY = 3; -// default browsercheck + +/** + * Default browser check class + * @construcotr + */ function roundcube_browser() { this.ver = parseFloat(navigator.appVersion); @@ -92,10 +100,118 @@ function roundcube_browser() } +// static functions for event handling +var rcube_event = { + +/** + * returns modifier key (constants defined at top of file) + */ +get_modifier: function(e) +{ + var opcode = 0; + e = e || window.event; + + if (bw.mac && e) + { + opcode += (e.metaKey && CONTROL_KEY) + (e.shiftKey && SHIFT_KEY); + return opcode; + } + if (e) + { + opcode += (e.ctrlKey && CONTROL_KEY) + (e.shiftKey && SHIFT_KEY); + return opcode; + } +}, + +/** + * Return absolute mouse position of an event + */ +get_mouse_pos: function(e) +{ + if (!e) e = window.event; + var mX = (e.pageX) ? e.pageX : e.clientX; + var mY = (e.pageY) ? e.pageY : e.clientY; + + if (document.body && document.all) + { + mX += document.body.scrollLeft; + mY += document.body.scrollTop; + } + + return { x:mX, y:mY }; +}, + +/** + * Add an object method as event listener to a certain element + */ +add_listener: function(p) +{ + if (!p.object || !p.method) // not enough arguments + return; + if (!p.element) + p.element = document; + + if (!p.object._rc_events) + p.object._rc_events = []; + + var key = p.event + '*' + p.method; + if (!p.object._rc_events[key]) + p.object._rc_events[key] = function(e){ return p.object[p.method](e); }; + + if (p.element.addEventListener) + p.element.addEventListener(p.event, p.object._rc_events[key], false); + else if (p.element.attachEvent) + p.element.attachEvent('on'+p.event, p.object._rc_events[key]); + else + p.element['on'+p.event] = p.object._rc_events[key]; +}, + +/** + * Remove event listener + */ +remove_listener: function(p) +{ + if (!p.element) + p.element = document; + + var key = p.event + '*' + p.method; + if (p.object && p.object._rc_events && p.object._rc_events[key]) { + if (p.element.removeEventListener) + p.element.removeEventListener(p.event, p.object._rc_events[key], false); + else if (p.element.detachEvent) + p.element.detachEvent('on'+p.event, p.object._rc_events[key]); + else + p.element['on'+p.event] = null; + } +}, + +/** + * Prevent event propagation and bubbeling + */ +cancel: function(evt) +{ + var e = evt ? evt : window.event; + if (e.preventDefault) + e.preventDefault(); + if (e.stopPropagation) + e.stopPropagation(); + + e.cancelBubble = true; + e.returnValue = false; + return false; +} + +}; var rcube_layer_objects = new Array(); + +/** + * RoundCube generic layer (floating box) class + * + * @constructor + */ function rcube_layer(id, attributes) { this.name = id; @@ -263,6 +379,7 @@ function rcube_layer(id, attributes) } } + // check if input is a valid email address // By Cal Henderson // http://code.iamcal.com/php/rfc822/ @@ -346,7 +463,7 @@ function find_in_array() // make a string URL safe function urlencode(str) { - return window.encodeURI ? encodeURI(str).replace(/&/g, '%26') : escape(str); + return window.encodeURIComponent ? encodeURIComponent(str) : escape(str); } diff --git a/program/js/list.js b/program/js/list.js new file mode 100644 index 000000000..88719049a --- /dev/null +++ b/program/js/list.js @@ -0,0 +1,704 @@ +/* + +-----------------------------------------------------------------------+ + | RoundCube List Widget | + | | + | This file is part of the RoundCube Webmail client | + | Copyright (C) 2006, RoundCube Dev, - Switzerland | + | Licensed under the GNU GPL | + | | + +-----------------------------------------------------------------------+ + | Authors: Thomas Bruederli | + | Charles McNulty | + +-----------------------------------------------------------------------+ + | Requires: common.js | + +-----------------------------------------------------------------------+ + + $Id: list.js 344 2006-09-18 03:49:28Z thomasb $ +*/ + + +/** + * RoundCube List Widget class + * @contructor + */ +function rcube_list_widget(list, p) + { + // static contants + this.ENTER_KEY = 13; + this.DELETE_KEY = 46; + + this.list = list ? list : null; + this.frame = null; + this.rows = []; + this.selection = []; + + this.multiselect = false; + this.draggable = false; + this.keyboard = false; + + this.dont_select = false; + this.drag_active = false; + this.last_selected = 0; + this.in_selection_before = false; + this.focused = false; + this.drag_mouse_start = null; + this.dblclick_time = 600; + this.row_init = function(){}; + this.events = { click:[], dblclick:[], select:[], keypress:[], dragstart:[], dragend:[] }; + + // overwrite default paramaters + if (p && typeof(p)=='object') + for (var n in p) + this[n] = p[n]; + } + + +rcube_list_widget.prototype = { + + +/** + * get all message rows from HTML table and init each row + */ +init: function() +{ + if (this.list && this.list.tBodies[0]) + { + this.rows = new Array(); + + var row; + for(var r=0; r