CHANGELOG | ●●●●● patch | view | raw | blame | history | |
THREADS | ●●●●● 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 | |
program/steps/mail/func.inc | ●●●●● patch | view | raw | blame | history | |
skins/default/iehacks.css | ●●●●● patch | view | raw | blame | history | |
skins/default/images/tree.gif | patch | view | raw | blame | history | |
skins/default/mail.css | ●●●●● patch | view | raw | blame | history | |
skins/default/safari.css | ●●●●● patch | view | raw | blame | history |
CHANGELOG
@@ -1,6 +1,7 @@ CHANGELOG RoundCube Webmail =========================== - Added thread tree icons - Extend contact groups support (#1486682) - Fix check-recent action issues and performance (#1486526) - Fix messages order after checking for recent (#1484664) THREADS
@@ -2,12 +2,13 @@ TODO (must have): - threads caching - (better) updating threaded message list on message delete and check-recent - better updating of threaded message list after message(s) deletion (?), in some cases when some children rows has been removed threads needs to be reordered TODO (other): - button in #listcontrols to mark all messages in current thread (with selected root or child message), - icons for thread tree structure KNOWN ISSUES: - IE6: message, flag, attachment icons are not displayed in program/js/app.js
@@ -87,7 +87,7 @@ if (sel) button_prop.sel = sel; if (over) button_prop.over = over; this.buttons[command][this.buttons[command].length] = button_prop; this.buttons[command].push(button_prop); }; // register a specific gui object @@ -121,7 +121,7 @@ // execute the given script on load this.add_onload = function(f) { this.onloads[this.onloads.length] = f; this.onloads.push(f); }; // initialize webmail client @@ -389,7 +389,7 @@ // execute all foreign onload scripts // @deprecated for (var i=0; i<this.onloads.length; i++) { for (var i in this.onloads) { if (typeof(this.onloads[i]) == 'string') eval(this.onloads[i]); else if (typeof(this.onloads[i]) == 'function') @@ -804,12 +804,12 @@ // use contact_id passed as command parameter var a_cids = []; if (props) a_cids[a_cids.length] = props; a_cids.push(props); // get selected contacts else if (this.contact_list) { var selection = this.contact_list.get_selection(); for (var n=0; n<selection.length; n++) a_cids[a_cids.length] = selection[n]; a_cids.push(selection[n]); } if (a_cids.length) @@ -1053,13 +1053,13 @@ // set command enabled or disabled this.enable_command = function() { var args = arguments; if (!args.length) var args = arguments, len = args.length; if (!len) return -1; var command, enable = args[args.length-1]; var command, enable = args[len-1]; for (var n=0; n<args.length-1; n++) { for (var n=0, len=len-1; n<len; n++) { command = args[n]; this.commands[command] = enable; this.set_button(command, (enable ? 'act' : 'pas')); @@ -1489,7 +1489,7 @@ for (i=0; i<cols.length; i++) if (cols[i].id && cols[i].id.match(/^rcm/)) { name = cols[i].id.replace(/^rcm/, ''); this.env.coltypes[this.env.coltypes.length] = name == 'to' ? 'from' : name; this.env.coltypes.push(name == 'to' ? 'from' : name); } if ((found = $.inArray('flag', this.env.coltypes)) >= 0) @@ -1537,6 +1537,7 @@ } if (!row.depth && row.has_children && (expando = document.getElementById('rcmexpando'+row.uid))) { row.expando = expando; expando.onmousedown = function(e) { return self.expand_message_row(e, uid); }; } @@ -1548,11 +1549,6 @@ { if (!this.gui_objects.messagelist || !this.message_list) return false; if (this.message_list.background) var tbody = this.message_list.background; else var tbody = this.gui_objects.messagelist.tBodies[0]; if (!this.env.messages[uid]) this.env.messages[uid] = {}; @@ -1566,14 +1562,15 @@ flagged: flags.flagged?1:0, has_children: flags.has_children?1:0, depth: flags.depth?flags.depth:0, unread_children: flags.unread_children, parent_uid: flags.parent_uid, unread_children: flags.unread_children?flags.unread_children:0, parent_uid: flags.parent_uid?flags.parent_uid:0, selected: this.select_all_mode || this.message_list.in_selection(uid) }); var c, tree = expando = '', list = this.message_list, rows = list.rows, tbody = this.gui_objects.messagelist.tBodies[0], rowcount = tbody.rows.length, even = rowcount%2, message = this.env.messages[uid], @@ -1656,7 +1653,7 @@ } // add each submitted col for (var n = 0; n < this.env.coltypes.length; n++) { for (var n in this.env.coltypes) { c = this.env.coltypes[n]; col = document.createElement('td'); col.className = String(c).toLowerCase(); @@ -1969,6 +1966,99 @@ } }; // Initializes threads indicators/expanders after list update this.init_threads = function(roots) { for (var n=0, len=roots.length; n<len; n++) setTimeout(function() { rcmail.add_tree_icons(roots[n]);}, 1); setTimeout(function() { rcmail.expand_threads();}, 1); }; // adds threads tree icons to the list (or specified thread) this.add_tree_icons = function(root) { var i, l, r, n, len, pos, tmp = [], uid = [], row, rows = this.message_list.rows; if (root) row = rows[root] ? rows[root].obj : null; else row = this.message_list.list.tBodies[0].firstChild; while (row) { if (row.nodeType == 1 && (r = rows[row.uid])) { if (r.depth) { for (i=tmp.length-1; i>=0; i--) { len = tmp[i].length; if (len > r.depth) { pos = len - r.depth; if (!(tmp[i][pos] & 2)) tmp[i][pos] = tmp[i][pos] ? tmp[i][pos]+2 : 2; } else if (len == r.depth) { if (!(tmp[i][0] & 2)) tmp[i][0] += 2; } if (r.depth > len) break; } tmp.push(new Array(r.depth)); tmp[tmp.length-1][0] = 1; uid.push(r.uid); } else { if (tmp.length) { for (i in tmp) { this.set_tree_icons(uid[i], tmp[i]); } tmp = []; uid = []; } if (root && row != rows[root].obj) break; } } row = row.nextSibling; } if (tmp.length) { for (i in tmp) { this.set_tree_icons(uid[i], tmp[i]); } } }; // adds tree icons to specified message row this.set_tree_icons = function(uid, tree) { var i, divs = [], html = '', len = tree.length; for (i=0; i<len; i++) { if (tree[i] > 2) divs.push({'class': 'l3', width: 15}); else if (tree[i] > 1) divs.push({'class': 'l2', width: 15}); else if (tree[i] > 0) divs.push({'class': 'l1', width: 15}); // separator div else if (divs.length && !divs[divs.length-1]['class']) divs[divs.length-1].width += 15; else divs.push({'class': null, width: 15}); } for (i=divs.length-1; i>=0; i--) { if (divs[i]['class']) html += '<div class="tree '+divs[i]['class']+'" />'; else html += '<div style="width:'+divs[i].width+'px" />'; } if (html) $('#rcmtab'+uid).html(html); }; // update parent in a thread this.update_thread_root = function(uid, flag) { @@ -2029,7 +2119,8 @@ break; r.depth--; // move left $('#rcmtab'+r.uid).width(r.depth * 15); // reset width and clear the content of a tab, icons will be added later $('#rcmtab'+r.uid).width(r.depth * 15).html(''); if (!r.depth) { // a new root count++; // increase roots count r.parent_uid = 0; @@ -2042,7 +2133,7 @@ function(e) { return e.data.p.expand_message_row(e, e.data.uid); }); r.unread_children = 0; roots[roots.length] = r; roots.push(r); } // show if it was hidden if (r.obj.style.display == 'none') @@ -2180,7 +2271,7 @@ { var row = this.message_list.rows[uid]; if (row.parent_uid || !row.has_children) if (row.parent_uid) return; if (!row.unread && row.unread_children && !row.expanded) @@ -2199,17 +2290,15 @@ if (!mbox || mbox == this.env.mailbox || (!this.env.uid && (!this.message_list || !this.message_list.get_selection().length))) return; var add_url = '&_target_mbox='+urlencode(mbox)+'&_from='+(this.env.action ? this.env.action : ''); var a_uids = []; var a_uids = [], add_url = '&_target_mbox='+urlencode(mbox)+'&_from='+(this.env.action ? this.env.action : ''); if (this.env.uid) a_uids[0] = this.env.uid; else { var selection = this.message_list.get_selection(); var id; for (var n=0; n<selection.length; n++) { id = selection[n]; a_uids[a_uids.length] = id; for (var n in selection) { a_uids.push(selection[n]); } } @@ -2254,7 +2343,7 @@ return; // also select childs of collapsed rows for (var uid, i=0; i < selection.length; i++) { for (var uid, i=0, len=selection.length; i<len; i++) { uid = selection[i]; if (this.message_list.rows[uid].has_children && !this.message_list.rows[uid].expanded) this.message_list.select_childs(uid); @@ -2302,17 +2391,29 @@ if (this.env.uid) a_uids[0] = this.env.uid; else { var selection = this.message_list.get_selection(); var id; for (var n=0; n<selection.length; n++) { var n, id, root, roots = [], selection = this.message_list.get_selection(); for (n=0, len=selection.length; n<len; n++) { id = selection[n]; a_uids[a_uids.length] = id; a_uids.push(id); if (this.env.threading) { count += this.update_thread(id); root = this.message_list.find_root(id); if (root != id && $.inArray(root, roots) < 0) { roots.push(root); } } this.message_list.remove_row(id, (this.env.display_next && n == selection.length-1)); } // make sure there are no selected rows if (!this.env.display_next) this.message_list.clear_selection(); // update thread tree icons for (n=0, len=roots.length; n<len; n++) { this.add_tree_icons(roots[n]); } } // also send search request to get the right messages @@ -2337,7 +2438,7 @@ // set a specific flag to one or more messages this.mark_message = function(flag, uid) { var a_uids = [], r_uids = [], var a_uids = [], r_uids = [], len, n, id, selection = this.message_list ? this.message_list.get_selection() : []; if (uid) @@ -2345,15 +2446,15 @@ else if (this.env.uid) a_uids[0] = this.env.uid; else if (this.message_list) { for (var n=0; n<selection.length; n++) { a_uids[a_uids.length] = selection[n]; for (n=0, len=selection.length; n<len; n++) { a_uids.push(selection[n]); } } if (!this.message_list) r_uids = a_uids; else for (var id, n=0; n<a_uids.length; n++) { for (n=0, len=a_uids.length; n<len; n++) { id = a_uids[n]; if ((flag=='read' && this.message_list.rows[id].unread) || (flag=='unread' && !this.message_list.rows[id].unread) @@ -2362,7 +2463,7 @@ || (flag=='flagged' && !this.message_list.rows[id].flagged) || (flag=='unflagged' && this.message_list.rows[id].flagged)) { r_uids[r_uids.length] = id; r_uids.push(id); } } @@ -2435,8 +2536,8 @@ return true; } var all_deleted = true; for (var uid, i=0; i<a_uids.length; i++) { var uid, all_deleted = true; for (var i=0, len=a_uids.length; i<len; i++) { uid = a_uids[i]; if (rows[uid] && !rows[uid].deleted) { all_deleted = false; @@ -2454,7 +2555,7 @@ this.flag_as_undeleted = function(a_uids) { for (var i=0; i<a_uids.length; i++) for (var i=0, len=a_uids.length; i<len; i++) this.set_message(a_uids[i], 'deleted', false); var url = '_uid='+this.uids_to_list(a_uids)+'&_flag=undelete'; @@ -2474,7 +2575,7 @@ rows = this.message_list ? this.message_list.rows : [], count = 0; for (var i=0; i<a_uids.length; i++) { for (var i=0, len=a_uids.length; i<len; i++) { uid = a_uids[i]; if (rows[uid]) { if (rows[uid].unread) @@ -3540,15 +3641,14 @@ if (!(selection.length || this.env.cid) || (!this.env.group && !confirm(this.get_label('deletecontactconfirm')))) return; var a_cids = [], qs = ''; var id, a_cids = [], qs = ''; if (this.env.cid) a_cids[a_cids.length] = this.env.cid; a_cids.push(this.env.cid); else { var id; for (var n=0; n<selection.length; n++) { id = selection[n]; a_cids[a_cids.length] = id; a_cids.push(id); this.contact_list.remove_row(id, (n == selection.length-1)); } @@ -4807,6 +4907,11 @@ // handle HTTP response this.http_response = function(response) { if (window.console) { var date1 = new Date(); var milliseconds1 = date1.getTime(); } if (response.unlock) this.set_busy(false); @@ -4875,7 +4980,6 @@ if (response.action == 'list' || response.action == 'search') { this.msglist_select(this.message_list); this.expand_threads(); this.triggerEvent('listupdate', { folder:this.env.mailbox, rowcount:this.message_list.rowcount }); } } @@ -4892,6 +4996,12 @@ } break; } if (window.console) { var date2 = new Date(); var milliseconds2 = date2.getTime(); console.log('Response execution time: ' + (milliseconds2 - milliseconds1) + 'ms'); } }; // handle HTTP request errors @@ -5014,7 +5124,7 @@ return; var type; for (var n=0; n<form.elements.length; n++) { for (var n=0, len=form.elements.length; n<len; n++) { type = form.elements[n]; if (type == 'hidden') continue; program/js/common.js
@@ -146,9 +146,8 @@ get_mouse_pos: function(e) { if (!e) e = window.event; var mX = (e.pageX) ? e.pageX : e.clientX, mY = (e.pageY) ? e.pageY : e.clientY; 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; @@ -324,13 +323,15 @@ // create a new layer in the current document this.create = function(arg) { var l = (arg.x) ? arg.x : 0, t = (arg.y) ? arg.y : 0, w = arg.width, h = arg.height, z = arg.zindex, vis = arg.vis, parent = arg.parent, var l = (arg.x) ? arg.x : 0; var t = (arg.y) ? arg.y : 0; var w = arg.width; var h = arg.height; var z = arg.zindex; var vis = arg.vis; var parent = arg.parent; var obj; obj = document.createElement('DIV'); with (obj) { @@ -431,20 +432,19 @@ function rcube_check_email(input, inline) { if (input && window.RegExp) { var qtext = '[^\\x0d\\x22\\x5c\\x80-\\xff]', dtext = '[^\\x0d\\x5b-\\x5d\\x80-\\xff]', atom = '[^\\x00-\\x20\\x22\\x28\\x29\\x2c\\x2e\\x3a-\\x3c\\x3e\\x40\\x5b-\\x5d\\x7f-\\xff]+', quoted_pair = '\\x5c[\\x00-\\x7f]', domain_literal = '\\x5b('+dtext+'|'+quoted_pair+')*\\x5d', quoted_string = '\\x22('+qtext+'|'+quoted_pair+')*\\x22', sub_domain = '('+atom+'|'+domain_literal+')', word = '('+atom+'|'+quoted_string+')', domain = sub_domain+'(\\x2e'+sub_domain+')*', local_part = word+'(\\x2e'+word+')*', addr_spec = local_part+'\\x40'+domain, delim = '[,;\s\n]', reg1 = inline ? new RegExp('(^|<|'+delim+')'+addr_spec+'($|>|'+delim+')', 'i') : new RegExp('^'+addr_spec+'$', 'i'); var qtext = '[^\\x0d\\x22\\x5c\\x80-\\xff]'; var dtext = '[^\\x0d\\x5b-\\x5d\\x80-\\xff]'; var atom = '[^\\x00-\\x20\\x22\\x28\\x29\\x2c\\x2e\\x3a-\\x3c\\x3e\\x40\\x5b-\\x5d\\x7f-\\xff]+'; var quoted_pair = '\\x5c[\\x00-\\x7f]'; var domain_literal = '\\x5b('+dtext+'|'+quoted_pair+')*\\x5d'; var quoted_string = '\\x22('+qtext+'|'+quoted_pair+')*\\x22'; var sub_domain = '('+atom+'|'+domain_literal+')'; var word = '('+atom+'|'+quoted_string+')'; var domain = sub_domain+'(\\x2e'+sub_domain+')*'; var local_part = word+'(\\x2e'+word+')*'; var addr_spec = local_part+'\\x40'+domain; var delim = '[,;\s\n]'; var reg1 = inline ? new RegExp('(^|<|'+delim+')'+addr_spec+'($|>|'+delim+')', 'i') : new RegExp('^'+addr_spec+'$', 'i'); return reg1.test(input) ? true : false; } return false; @@ -510,8 +510,8 @@ // determine whether the mouse is over the given object or not function rcube_mouse_is_over(ev, obj) { var mouse = rcube_event.get_mouse_pos(ev), pos = $(obj).offset(); var mouse = rcube_event.get_mouse_pos(ev); var pos = $(obj).offset(); return ((mouse.x >= pos.left) && (mouse.x < (pos.left + obj.offsetWidth)) && (mouse.y >= pos.top) && (mouse.y < (pos.top + obj.offsetHeight))); @@ -531,22 +531,18 @@ function getCookie(name) { var dc = document.cookie, prefix = name + "=", end, begin = dc.indexOf("; " + prefix); var dc = document.cookie; var prefix = name + "="; var begin = dc.indexOf("; " + prefix); if (begin == -1) { begin = dc.indexOf(prefix); if (begin != 0) return null; if (begin != 0) return null; } else begin += 2; end = document.cookie.indexOf(";", begin); var end = document.cookie.indexOf(";", begin); if (end == -1) end = dc.length; return unescape(dc.substring(begin + prefix.length, end)); }; program/js/list.js
@@ -76,11 +76,10 @@ this.rows = []; this.rowcount = 0; var row, r; var r, len, rows = this.list.tBodies[0].rows; for (r=0; r<this.list.tBodies[0].rows.length; r++) { row = this.list.tBodies[0].rows[r]; this.init_row(row); for (r=0, len=rows.length; r<len; r++) { this.init_row(rows[r]); this.rowcount++; } @@ -170,7 +169,7 @@ if (sel_next) this.select_next(); this.rows[uid] = null; delete this.rows[uid]; this.rowcount--; }, @@ -180,9 +179,6 @@ */ insert_row: function(row, attop) { if (this.background) var tbody = this.background; else var tbody = this.list.tBodies[0]; if (attop && tbody.rows.length) @@ -201,8 +197,9 @@ */ focus: function(e) { var id; this.focused = true; for (var n=0; n<this.selection.length; n++) { for (var n in this.selection) { id = this.selection[n]; if (this.rows[id] && this.rows[id].obj) { $(this.rows[id].obj).addClass('selected').removeClass('unfocused'); @@ -221,7 +218,7 @@ { var id; this.focused = false; for (var n=0; n<this.selection.length; n++) { for (var n in this.selection) { id = this.selection[n]; if (this.rows[id] && this.rows[id].obj) { $(this.rows[id].obj).removeClass('selected').addClass('unfocused'); @@ -581,11 +578,10 @@ get_first_row: function() { if (this.rowcount) { var rows = this.list.tBodies[0].rows; var i, len, rows = this.list.tBodies[0].rows; for(var i=0; i<rows.length-1; i++) for (i=0, len=rows.length-1; i<len; i++) if(rows[i].id && String(rows[i].id).match(/rcmrow([a-z0-9\-_=\+\/]+)/i) && this.rows[RegExp.$1] != null) return RegExp.$1; } @@ -595,11 +591,10 @@ get_last_row: function() { if (this.rowcount) { var rows = this.list.tBodies[0].rows; var i, rows = this.list.tBodies[0].rows; for(var i=rows.length-1; i>=0; i--) for (i=rows.length-1; i>=0; i--) if(rows[i].id && String(rows[i].id).match(/rcmrow([a-z0-9\-_=\+\/]+)/i) && this.rows[RegExp.$1] != null) return RegExp.$1; } @@ -756,15 +751,14 @@ if (!this.rows[this.shift_start] || !this.selection.length) this.shift_start = id; var from_rowIndex = this.rows[this.shift_start].obj.rowIndex; var to_rowIndex = this.rows[id].obj.rowIndex; var i = ((from_rowIndex < to_rowIndex)? from_rowIndex : to_rowIndex); var j = ((from_rowIndex > to_rowIndex)? from_rowIndex : to_rowIndex); var from_rowIndex = this.rows[this.shift_start].obj.rowIndex, to_rowIndex = this.rows[id].obj.rowIndex, i = ((from_rowIndex < to_rowIndex)? from_rowIndex : to_rowIndex), j = ((from_rowIndex > to_rowIndex)? from_rowIndex : to_rowIndex); // iterate through the entire message list for (var n in this.rows) { if ((this.rows[n].obj.rowIndex >= i) && (this.rows[n].obj.rowIndex <= j)) { if (this.rows[n].obj.rowIndex >= i && this.rows[n].obj.rowIndex <= j) { if (!this.in_selection(n)) { this.highlight_row(n, true); } @@ -804,11 +798,11 @@ this.selection = []; for (var n in this.rows) { if (!filter || (this.rows[n] && this.rows[n][filter] == true)) { if (!filter || this.rows[n][filter] == true) { this.last_selected = n; this.highlight_row(n, true); } else if (this.rows[n]) { else { $(this.rows[n].obj).removeClass('selected').removeClass('unfocused'); } } @@ -856,7 +850,7 @@ // one row if (id) { for (var n=0; n<this.selection.length; n++) for (var n=0 in this.selection) if (this.selection[n] == id) { this.selection.splice(n,1); break; @@ -864,7 +858,7 @@ } // all rows else { for (var n=0; n<this.selection.length; n++) for (var n in this.selection) if (this.rows[this.selection[n]]) { $(this.rows[this.selection[n]].obj).removeClass('selected').removeClass('unfocused'); } @@ -1097,9 +1091,8 @@ .appendTo(document.body); // also select childs of (collapsed) threads for dragging var selection = $.merge([], this.selection); var depth, row, uid, r; for (var n=0; n < selection.length; n++) { var n, uid, selection = $.merge([], this.selection); for (n in selection) { uid = selection[n]; if (this.rows[uid].has_children && !this.rows[uid].expanded) this.select_childs(uid); @@ -1372,20 +1365,6 @@ this.subject_col = to > from ? to - 1 : to; this.triggerEvent('column_replace'); }, /** * Creating the list in background */ set_background_mode: function(flag) { if (flag) { this.background = document.createElement('tbody'); } else if (this.background) { this.list.replaceChild(this.background, this.list.tBodies[0]); this.background = null; } } }; program/steps/mail/func.inc
@@ -285,6 +285,8 @@ if ($header->depth) $a_msg_flags['depth'] = $header->depth; else if ($header->has_children) $roots[] = $header->uid; if ($header->parent_uid) $a_msg_flags['parent_uid'] = $header->parent_uid; if ($header->has_children) @@ -311,6 +313,10 @@ $a_msg_flags, $insert_top); } if ($IMAP->threading && $a_headers) { $OUTPUT->command('init_threads', (array) $roots); } } skins/default/iehacks.css
@@ -156,6 +156,12 @@ border-collapse: collapse; } #messagelist thead tr td, #messagelist tbody tr td { height: 18px; } #messagelist tbody tr.unroot td.subject { text-decoration: underline; skins/default/images/tree.gif
skins/default/mail.css
@@ -397,6 +397,7 @@ list-style-type: none; overflow: hidden; white-space: nowrap; background-color: #FFF; } #mailboxlist li @@ -506,7 +507,7 @@ border-top: 1px solid #EBEBEB; padding-left: 15px; background-position: 25px 1px; background-color: #F9F9F9; background-color: #FFF; color: blue; font-weight: normal; } @@ -671,10 +672,7 @@ #messagelist thead tr td { height: 20px; padding-top: 0px; padding-bottom: 0px; padding-left: 2px; padding-right: 4px; padding: 0 4px 0 2px; vertical-align: middle; border-bottom: 1px solid #999999; color: #333333; @@ -708,12 +706,23 @@ text-decoration: none; } #messagelist thead tr td.size { text-align: left; } #messagelist thead tr td.subject { padding-left: 18px; } #messagelist tbody tr td { height: 16px; padding: 2px; height: 20px; padding: 0; font-size: 11px; overflow: hidden; vertical-align: middle; white-space: nowrap; text-overflow: ellipsis; -o-text-overflow: ellipsis; @@ -729,75 +738,45 @@ cursor: inherit; } #messagelist tbody tr td.subject a #messagelist tr td.icon, #messagelist tr td.threads, #messagelist tr td.attachment, #messagelist tr td.flag { cursor: default; width: 20px; padding: 0px 1px 1px 1px; } #messagelist col #messagelist tbody td span.branch, #messagelist tbody td img { display: table-column; text-align: left; vertical-align: middle; } #messagelist thead tr td.subject { padding-left: 22px; } #messagelist thead tr td.icon, #messagelist thead tr td.flag, #messagelist thead tr td.threads { width: 22px; padding: 0; text-align: center; } #messagelist thead tr td.threads { width: 18px; } #messagelist tbody tr td.flag { padding: 2px 3px 2px 3px; vertical-align: middle; cursor: pointer; } #messagelist tr td span.branch { display: inline-block; width: 15px; height: 15px; } #messagelist tbody td img.msgicon { vertical-align: middle; position: relative; top: 0px; margin-right: 5px; margin-right: 2px; } #messagelist tr td div.collapsed, #messagelist tr td div.expanded, #messagelist tr td img.flagicon, #messagelist tr td img.msgicon #messagelist tr td img.msgicon, #messagelist tbody tr td.flag, #messagelist tbody tr td.subject a { cursor: pointer; } #messagelist tr td div.collapsed { background: url(images/messageactions.png) -1px -91px no-repeat; background: url(images/messageactions.png) 1px -91px no-repeat; } #messagelist tr td div.expanded { background: url(images/messageactions.png) -1px -109px no-repeat; background: url(images/messageactions.png) 1px -109px no-repeat; } #messagelist tbody tr td.flag img:hover, @@ -806,10 +785,8 @@ background: url(images/icons/unflagged.png) center no-repeat; } #messagelist tr td.subject #messagelist tbody tr td.subject { overflow: hidden; vertical-align: middle; width: 99%; } @@ -821,14 +798,9 @@ #messagelist tr td.size { width: 70px; width: 60px; text-align: right; vertical-align: middle; } #messagelist thead tr td.size { text-align: left; padding: 0 2px; } #messagelist tr td.from, @@ -837,18 +809,18 @@ #messagelist tr td.replyto { width: 180px; vertical-align: middle; padding: 0 2px; } #messagelist tr td.date { width: 118px; vertical-align: middle; padding: 0 2px; } #messagelist tr.message { background-color: #FFFFFF; background-color: #FFF; } /* @@ -898,6 +870,37 @@ color: #CCCCCC; } /***** tree indicators *****/ td span.branch div { float: left; height: 16px; } td span.branch div.tree { height: 17px; width: 15px; background: url(images/tree.gif) 0px 0px no-repeat; } td span.branch div.l1 { background-position: 0px 0px; /* L */ } td span.branch div.l2 { background-position: -30px 0px; /* | */ } td span.branch div.l3 { background-position: -15px 0px; /* |- */ } .quota_text { text-align: center; font-size: 10px; skins/default/safari.css
@@ -14,3 +14,9 @@ { word-wrap: break-word; } #messagelist thead tr td, #messagelist tbody tr td { height: 18px; }