CHANGELOG | ●●●●● patch | view | raw | blame | history | |
program/js/app.js | ●●●●● patch | view | raw | blame | history | |
program/js/common.js | ●●●●● patch | view | raw | blame | history | |
program/js/list.js | ●●●●● patch | view | raw | blame | history | |
skins/default/addresses.css | ●●●●● patch | view | raw | blame | history | |
skins/default/common.css | ●●●●● patch | view | raw | blame | history | |
skins/default/images/dimple.png | patch | view | raw | blame | history | |
skins/default/mail.css | ●●●●● patch | view | raw | blame | history | |
skins/default/splitter.js | ●●●●● patch | view | raw | blame | history | |
skins/default/templates/addressbook.html | ●●●●● patch | view | raw | blame | history | |
skins/default/templates/mail.html | ●●●●● patch | view | raw | blame | history |
CHANGELOG
@@ -1,6 +1,11 @@ CHANGELOG RoundCube Webmail --------------------------- 2006/12/17 (thomasb) ---------- - Added patch by Ryan Rittenhouse & David Glick for a resizeable preview pane 2006/12/06 (thomasb) ---------- - Improve memory usage when sending mail (closes #1484098) program/js/app.js
@@ -26,6 +26,7 @@ this.buttons = new Object(); this.gui_objects = new Object(); this.commands = new Object(); this.onloads = new Array(); // create public reference to myself rcube_webmail_client = this; @@ -77,13 +78,17 @@ 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() @@ -101,7 +106,7 @@ // 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); @@ -293,6 +298,16 @@ // start keep-alive interval this.start_keepalive(); // execute all foreign onload scripts for (var i=0; i<this.onloads.length; i++) { if (typeof(this.onloads[i]) == 'string') eval(this.onloads[i]); else if (typeof(this.onloads[i]) == 'function') this.onloads[i](); } }; @@ -678,7 +693,7 @@ this.show_message(this.env.next_uid, false, this.env.action=='preview'); break; case 'lastmessage': case 'lastmessage': if (this.env.last_uid) this.show_message(this.env.last_uid); break; @@ -1209,6 +1224,7 @@ add_url += '&_refresh=1'; this.env.current_page = page; this.message_list.clear_selection(); this.show_messageframe(false); } // also send search request to get the right messages @@ -1324,17 +1340,16 @@ else { var selection = this.message_list.get_selection(); var id; for (var n=0; n<selection.length; n++) for (var n=0, id; n<selection.length; n++) { id = selection[n]; a_uids[a_uids.length] = id; this.message_list.remove_row(id); } this.message_list.select_next(); this.show_messageframe(false); } var lock = false; // show wait message program/js/common.js
@@ -530,6 +530,33 @@ return {x:iX, y:iY}; } /** * Return the currently applied value of a css property * * @param {Object} html_element Node reference * @param {String} css_property Property name to read in Javascript notation (eg. 'textAlign') * @param {String} mozilla_equivalent Equivalent property name in CSS notation (eg. 'text-align') * @return CSS property value * @type String */ function get_elements_computed_style(html_element, css_property, mozilla_equivalent) { if (arguments.length==2) mozilla_equivalent = css_property; var el = html_element; if (typeof(html_element)=='string') el = nex_get_object(html_element); if (el && el.currentStyle) return el.currentStyle[css_property]; else if (el && document.defaultView && document.defaultView.getComputedStyle) return document.defaultView.getComputedStyle(el, null).getPropertyValue(mozilla_equivalent); else return false; } // cookie functions by GoogieSpell @@ -542,6 +569,8 @@ (secure ? "; secure" : ""); document.cookie = curCookie; } roundcube_browser.prototype.set_cookie = setCookie; function getCookie(name) { @@ -561,5 +590,7 @@ return unescape(dc.substring(begin + prefix.length, end)); } roundcube_browser.prototype.get_cookie = getCookie; var bw = new roundcube_browser(); program/js/list.js
@@ -272,7 +272,7 @@ return false; var last_selected_row = this.rows[this.last_selected]; var new_row = last_selected_row && last_selected_row.obj.nextSibling; var new_row = last_selected_row ? last_selected_row.obj.nextSibling : null; while (new_row && (new_row.nodeType != 1 || new_row.style.display == 'none')) new_row = new_row.nextSibling; @@ -285,7 +285,7 @@ return false; var last_selected_row = this.rows[this.last_selected]; var new_row = last_selected_row && last_selected_row.obj.previousSibling; var new_row = last_selected_row ? last_selected_row.obj.previousSibling : null; while (new_row && (new_row.nodeType != 1 || new_row.style.display == 'none')) new_row = new_row.previousSibling; skins/default/addresses.css
@@ -70,10 +70,23 @@ border: 1px solid #999999; overflow: hidden; /* css hack for IE */ width: expression((parseInt(document.documentElement.clientWidth)-530)+'px'); width: expression((parseInt(document.documentElement.clientWidth)-80-document.getElementById('addresslist').offsetWidth)+'px'); height: expression((parseInt(document.documentElement.clientHeight)-135)+'px'); } #addressviewsplitter { background-position: 6px center; } #addressviewsplitter .splitterLine { margin-left: 3px; width: 9px; } body.iframe, #contact-frame { skins/default/common.css
@@ -213,6 +213,25 @@ border: 1px solid #CCCCCC; } .splitter { position: absolute; padding: 2px; background: url(images/dimple.png) center no-repeat; } .splitter-h { cursor: n-resize; background-position: center 2px; } .splitter-v { cursor: e-resize; background-position: 1px center; } /***** common table settings ******/ skins/default/images/dimple.png
skins/default/mail.css
@@ -123,7 +123,7 @@ #mailpreviewframe { position: absolute; top: 300px; top: 305px; left: 200px; right: 40px; bottom: 40px; @@ -131,7 +131,7 @@ background-color: #F9F9F9; /* css hack for IE */ width: expression((parseInt(document.documentElement.clientWidth)-240)+'px'); height: expression((parseInt(document.documentElement.clientHeight)-340)+'px'); height: expression((parseInt(document.documentElement.clientHeight)-135-document.getElementById('mailcontframe').offsetHeight)+'px'); } #messagecontframe skins/default/splitter.js
New file @@ -0,0 +1,209 @@ /** * RoundCube splitter GUI class * * @constructor */ function rcube_splitter(attrib) { this.p1id = attrib.p1; this.p2id = attrib.p2; this.id = attrib.id ? attrib.id : this.p1id + '_' + this.p2id + '_splitter'; this.orientation = attrib.orientation; this.horizontal = (this.orientation == 'horizontal' || this.orientation == 'h'); this.offset_1 = bw.ie ? 0 : (bw.safari ? 2 : -1); this.offset_2 = bw.ie ? -2 : (bw.safari ? -2 : 1); this.pos = 0; this.init = function() { this.p1 = document.getElementById(this.p1id); this.p2 = document.getElementById(this.p2id); // create and position the handle for this splitter this.p1pos = rcube_get_object_pos(this.p1); this.p2pos = rcube_get_object_pos(this.p2); var top = this.p1pos.y + this.p1.offsetHeight; var height = this.p2pos.y - this.p1pos.y - this.p1.offsetHeight; var left = this.p1pos.x + this.p1.offsetWidth; var width = this.p2pos.x - this.p1pos.x - this.p1.offsetWidth; if (this.horizontal) this.layer = new rcube_layer(this.id, {x: this.p1pos.x, y: top, height: height, width: this.p1.offsetWidth, vis: 1}); else this.layer = new rcube_layer(this.id, {x: left, y: this.p1pos.y, width: width, height: this.p1.offsetHeight, vis: 1}); this.elm = this.layer.elm; this.elm.className = 'splitter '+(this.horizontal ? 'splitter-h' : 'splitter-v'); // add the mouse event listeners rcube_event.add_listener({element: this.elm, event:'mousedown', object:this, method:'onDragStart'}); rcube_event.add_listener({element: window, event:'resize', object:this, method:'onResize'}); // read saved position form cookie var cookie = bw.get_cookie(this.id); if (cookie) { var param = cookie.split(':'); for (var i=0, p; i<param.length; i++) { p = param[i].split('='); this[p[0]] = !isNaN(p[1]) ? parseFloat(p[1]) : p[1]; } this.resize(); } }; /** * Set size and position of all DOM objects * according to the saved splitter position */ this.resize = function() { if (this.horizontal) { this.p1.style.height = Math.floor(this.pos - this.p1pos.y - this.layer.height / 2 + this.offset_1) + 'px'; this.p2.style.top = Math.ceil(this.pos + (this.layer.height / 2 + this.offset_2)) + 'px'; this.layer.move(this.layer.x, Math.round(this.pos - this.layer.height / 2 + 1)); } else { this.p1.style.width = Math.floor(this.pos - this.p1pos.x - this.layer.width / 2 + this.offset_1) + 'px'; this.p2.style.left = Math.ceil(this.pos + this.layer.width / 2 + this.offset_2) + 'px'; this.layer.move(Math.round(this.pos - this.layer.width / 2 + 1), this.layer.y); } }; /** * Handler for mousedown events */ this.onDragStart = function(e) { this.p1pos = rcube_get_object_pos(this.p1); this.p2pos = rcube_get_object_pos(this.p2); // start listening to mousemove events rcube_event.add_listener({element:document, event:'mousemove', object:this, method:'onDrag'}); rcube_event.add_listener({element:document, event:'mouseup', object:this, method:'onDragStop'}); // need to listen in any iframe documents too, b/c otherwise the splitter stops moving when we move over an iframe var iframes = document.getElementsByTagName('IFRAME'); this.iframe_events = Object(); for (var n in iframes) { var iframedoc = null; if (iframes[n].contentDocument) iframedoc = iframes[n].contentDocument; else if (iframes[n].contentWindow) iframedoc = iframes[n].contentWindow.document; else if (iframes[n].document) iframedoc = iframes[n].document; if (iframedoc) { // I don't use the add_listener function for this one because I need to create closures to fetch // the position of each iframe when the event is received var s = this; var id = iframes[n].id; this.iframe_events[n] = function(e){ e._rc_pos_offset = rcube_get_object_pos(document.getElementById(id)); return s.onDrag(e); } if (iframedoc.addEventListener) iframedoc.addEventListener('mousemove', this.iframe_events[n], false); else if (iframes[n].attachEvent) iframedoc.attachEvent('onmousemove', this.iframe_events[n]); else iframedoc['onmousemove'] = this.iframe_events[n]; rcube_event.add_listener({element:iframedoc, event:'mouseup', object:this, method:'onDragStop'}); } } } /** * Handler for mousemove events */ this.onDrag = function(e) { var pos = rcube_event.get_mouse_pos(e); if (e._rc_pos_offset) { pos.x += e._rc_pos_offset.x; pos.y += e._rc_pos_offset.y; } if (this.horizontal) { if (((pos.y - this.layer.height * 1.5) > this.p1pos.y) && ((pos.y + this.layer.height * 1.5) < (this.p2pos.y + this.p2.offsetHeight))) { this.pos = pos.y; this.resize(); } } else { if (((pos.x - this.layer.width * 1.5) > this.p1pos.x) && ((pos.x + this.layer.width * 1.5) < (this.p2pos.x + this.p2.offsetWidth))) { this.pos = pos.x; this.resize(); } } this.p1pos = rcube_get_object_pos(this.p1); this.p2pos = rcube_get_object_pos(this.p2); return false; }; /** * Handler for mouseup events */ this.onDragStop = function(e) { // cancel the listening for drag events rcube_event.remove_listener({element:document, event:'mousemove', object:this, method:'onDrag'}); rcube_event.remove_listener({element:document, event:'mouseup', object:this, method:'onDragStop'}); var iframes = document.getElementsByTagName('IFRAME'); for (var n in iframes) { var iframedoc; if (iframes[n].contentDocument) iframedoc = iframes[n].contentDocument; else if (iframes[n].contentWindow) iframedoc = iframes[n].contentWindow.document; else if (iframes[n].document) iframedoc = iframes[n].document; if (iframedoc) { if (this.iframe_events[n]) { if (iframedoc.removeEventListener) iframedoc.removeEventListener('mousemove', this.iframe_events[n], false); else if (iframedoc.detachEvent) iframedoc.detachEvent('onmousemove', this.iframe_events[n]); else iframedoc['onmousemove'] = null; } rcube_event.remove_listener({element:iframedoc, event:'mouseup', object:this, method:'onDragStop'}); } } // save state in cookie var exp = new Date(); exp.setYear(exp.getFullYear() + 1); bw.set_cookie(this.id, 'pos='+this.pos, exp); return bw.safari ? true : rcube_event.cancel(e); }; /** * Handler for window resize events */ this.onResize = function(e) { this.p1pos = rcube_get_object_pos(this.p1); this.p2pos = rcube_get_object_pos(this.p2); var height = this.horizontal ? this.p2pos.y - this.p1pos.y - this.p1.offsetHeight : this.p1.offsetHeight; var width = this.horizontal ? this.p1.offsetWidth : this.p2pos.x - this.p1pos.x - this.p1.offsetWidth; this.layer.resize(width, height); }; } // end class rcube_splitter skins/default/templates/addressbook.html
@@ -4,6 +4,7 @@ <title><roundcube:object name="pagetitle" /></title> <roundcube:include file="/includes/links.html" /> <link rel="stylesheet" type="text/css" href="/addresses.css" /> <script type="text/javascript" src="/splitter.js"></script> </head> <body> @@ -31,6 +32,11 @@ <roundcube:object name="addresslist" id="contacts-table" class="records-table" cellspacing="0" summary="Contacts list" /> </div> <script type="text/javascript"> var addrviewsplit = new rcube_splitter({id:'addressviewsplitter', p1: 'addresslist', p2: 'contacts-box', orientation: 'v'}); rcmail.add_onload('addrviewsplit.init()'); </script> <div id="contacts-box"> <roundcube:object name="addressframe" id="contact-frame" width="100%" height="100%" frameborder="0" src="/watermark.html" /> </div> skins/default/templates/mail.html
@@ -4,6 +4,7 @@ <title><roundcube:object name="pagetitle" /></title> <roundcube:include file="/includes/links.html" /> <link rel="stylesheet" type="text/css" href="/mail.css" /> <script type="text/javascript" src="/splitter.js"></script> </head> <body> @@ -55,6 +56,10 @@ </div> <roundcube:if condition="config:preview_pane == true" /> <script type="text/javascript"> var mailviewsplit = new rcube_splitter({id:'mailviewsplitter', p1: 'mailcontframe', p2: 'mailpreviewframe', orientation: 'h'}); rcmail.add_onload('mailviewsplit.init()'); </script> <div id="mailpreviewframe"> <roundcube:object name="messagecontentframe" id="messagecontframe" width="100%" height="100%" frameborder="0" src="/watermark.html" /> </div> @@ -62,7 +67,7 @@ <style type="text/css"> #mailcontframe { bottom: auto; height: 210px; height: 208px; } </style> <roundcube:endif />