summaryrefslogtreecommitdiff
path: root/program/js
diff options
context:
space:
mode:
authorAleksander Machniak <alec@alec.pl>2013-05-08 14:28:36 +0200
committerAleksander Machniak <alec@alec.pl>2013-05-08 14:28:36 +0200
commita522971cf853b2f0ccd1b569491a06218ebbaee9 (patch)
treecf0e8c6bbe0978cf302b112080370b9a01cf5900 /program/js
parentea6d6958e0a32c88bf8c00cbd118cfcd48fae096 (diff)
parentc4723999e21da0b266b0467de6e58cbd26c4b5bf (diff)
Merge branch 'master' of github.com:roundcube/roundcubemail
Conflicts: program/js/list.js
Diffstat (limited to 'program/js')
-rw-r--r--program/js/app.js101
-rw-r--r--program/js/list.js177
2 files changed, 178 insertions, 100 deletions
diff --git a/program/js/app.js b/program/js/app.js
index 474a1b8c3..af09572ff 100644
--- a/program/js/app.js
+++ b/program/js/app.js
@@ -936,16 +936,13 @@ function rcube_webmail()
url._to = props;
}
else {
- // use contact_id passed as command parameter
- var n, len, a_cids = [];
+ var a_cids = [];
+ // use contact id passed as command parameter
if (props)
a_cids.push(props);
// get selected contacts
- else if (this.contact_list) {
- var selection = this.contact_list.get_selection();
- for (n=0, len=selection.length; n<len; n++)
- a_cids.push(selection[n]);
- }
+ else if (this.contact_list)
+ a_cids = this.contact_list.get_selection();
if (a_cids.length)
this.http_post('mailto', { _cid: a_cids.join(','), _source: this.env.source }, true);
@@ -1582,7 +1579,7 @@ function rcube_webmail()
this.msglist_set_coltypes = function(list)
{
- var i, found, name, cols = list.list.tHead.rows[0].cells;
+ var i, found, name, cols = list.thead.rows[0].cells;
this.env.coltypes = [];
@@ -1632,13 +1629,17 @@ function rcube_webmail()
this.open_window = function(url, width, height)
{
- var w = Math.min(width, screen.width - 10),
- h = Math.min(height, screen.height - 100),
- l = (screen.width - w) / 2 + (screen.left || 0),
- t = Math.max(0, (screen.height - h) / 2 + (screen.top || 0) - 20),
+ var dh = (window.outerHeight || 0) - (window.innerHeight || 0),
+ dw = (window.outerWidth || 0) - (window.innerWidth || 0),
+ sh = screen.availHeight || screen.height,
+ sw = screen.availWidth || screen.width,
+ w = Math.min(width, sw),
+ h = Math.min(height, sh),
+ l = Math.max(0, (sw - w) / 2 + (screen.left || 0)),
+ t = Math.max(0, (sh - h) / 2 + (screen.top || 0)),
wname = 'rcmextwin' + new Date().getTime(),
extwin = window.open(url + (url.match(/\?/) ? '&' : '?') + '_extwin=1', wname,
- 'width='+w+',height='+h+',top='+t+',left='+l+',resizable=yes,toolbar=no,status=no,location=no');
+ 'width='+(w-dw)+',height='+(h-dh)+',top='+t+',left='+l+',resizable=yes,toolbar=no,status=no,location=no');
// write loading... message to empty windows
if (!url && extwin.document) {
@@ -1732,10 +1733,7 @@ function rcube_webmail()
+ (flags.flagged ? ' flagged' : '')
+ (flags.unread_children && flags.seen && !this.env.autoexpand_threads ? ' unroot' : '')
+ (message.selected ? ' selected' : ''),
- // for performance use DOM instead of jQuery here
- row = document.createElement('tr');
-
- row.id = 'rcmrow'+uid;
+ row = { cols:[], style:{}, id:'rcmrow'+uid };
// message status icons
css_class = 'msgicon';
@@ -1799,8 +1797,7 @@ function rcube_webmail()
// add each submitted col
for (n in this.env.coltypes) {
c = this.env.coltypes[n];
- col = document.createElement('td');
- col.className = String(c).toLowerCase();
+ col = { className: String(c).toLowerCase() };
if (c == 'flag') {
css_class = (flags.flagged ? 'flagged' : 'unflagged');
@@ -1845,8 +1842,7 @@ function rcube_webmail()
html = cols[c];
col.innerHTML = html;
-
- row.appendChild(col);
+ row.cols.push(col);
}
list.insert_row(row, attop);
@@ -2209,7 +2205,7 @@ function rcube_webmail()
if (root)
row = rows[root] ? rows[root].obj : null;
else
- row = this.message_list.list.tBodies[0].firstChild;
+ row = this.message_list.tbody.firstChild;
while (row) {
if (row.nodeType == 1 && (r = rows[row.uid])) {
@@ -2385,7 +2381,7 @@ function rcube_webmail()
this.delete_excessive_thread_rows = function()
{
var rows = this.message_list.rows,
- tbody = this.message_list.list.tBodies[0],
+ tbody = this.message_list.tbody,
row = tbody.firstChild,
cnt = this.env.pagesize + 1;
@@ -4328,21 +4324,7 @@ function rcube_webmail()
newcid = newcid+'-'+source;
}
- if (list.rows[cid] && (row = list.rows[cid].obj)) {
- for (c=0; c<cols_arr.length; c++)
- if (row.cells[c])
- $(row.cells[c]).html(cols_arr[c]);
-
- // cid change
- if (newcid) {
- newcid = this.html_identifier(newcid);
- row.id = 'rcmrow' + newcid;
- list.remove_row(cid);
- list.init_row(row);
- list.selection[0] = newcid;
- row.style.display = '';
- }
- }
+ list.update_row(cid, cols_arr, newcid, true);
};
// add row to contacts list
@@ -4352,7 +4334,7 @@ function rcube_webmail()
return false;
var c, col, list = this.contact_list,
- row = document.createElement('tr');
+ row = { cols:[] };
row.id = 'rcmrow'+this.html_identifier(cid);
row.className = 'contact ' + (classes || '');
@@ -4362,10 +4344,10 @@ function rcube_webmail()
// add each submitted col
for (c in cols) {
- col = document.createElement('td');
+ col = {};
col.className = String(c).toLowerCase();
col.innerHTML = cols[c];
- row.appendChild(col);
+ row.cols.push(col);
}
list.insert_row(row);
@@ -4471,11 +4453,22 @@ function rcube_webmail()
this.name_input.bind('keydown', function(e){ return rcmail.add_input_keydown(e); });
this.name_input_li = $('<li>').addClass(type).append(this.name_input);
- var li = type == 'contactsearch' ? $('li:last', this.gui_objects.folderlist) : $('ul.groups li:last', this.get_folder_li(this.env.source,'',true));
+ var ul, li;
+
+ // find list (UL) element
+ if (type == 'contactsearch')
+ ul = this.gui_objects.folderlist;
+ else
+ ul = $('ul.groups', this.get_folder_li(this.env.source,'',true));
+
+ // append to the list
+ li = $('li:last', ul);
if (li.length)
this.name_input_li.insertAfter(li);
- else
- this.name_input_li.appendTo(type == 'contactsearch' ? this.gui_objects.folderlist : $('ul.groups', this.get_folder_li(this.env.source,'',true)));
+ else {
+ this.name_input_li.appendTo(ul);
+ ul.show(); // make sure the list is visible
+ }
}
this.name_input.select().focus();
@@ -4532,11 +4525,13 @@ function rcube_webmail()
this.reset_add_input = function()
{
if (this.name_input) {
+ var li = this.name_input.parent();
if (this.env.group_renaming) {
- var li = this.name_input.parent();
li.children().last().show();
this.env.group_renaming = false;
}
+ else if ($('li', li.parent()).length == 1)
+ li.parent().hide();
this.name_input.remove();
@@ -4964,18 +4959,16 @@ function rcube_webmail()
this.update_identity_row = function(id, name, add)
{
- var row, col, list = this.identity_list,
+ var list = this.identity_list,
rid = this.html_identifier(id);
- if (list.rows[rid] && (row = list.rows[rid].obj)) {
- $(row.cells[0]).html(name);
- }
- else if (add) {
- row = $('<tr>').attr('id', 'rcmrow'+rid).get(0);
- col = $('<td>').addClass('mail').html(name).appendTo(row);
- list.insert_row(row);
+ if (add) {
+ list.insert_row({ id:'rcmrow'+rid, cols:[ { className:'mail', innerHTML:name } ] });
list.select(rid);
}
+ else {
+ list.update_row(rid, [ name ]);
+ }
};
@@ -5750,7 +5743,7 @@ function rcube_webmail()
this.set_message_coltypes = function(coltypes, repl, smart_col)
{
var list = this.message_list,
- thead = list ? list.list.tHead : null,
+ thead = list ? list.thead : null,
cell, col, n, len, th, tr;
this.env.coltypes = coltypes;
diff --git a/program/js/list.js b/program/js/list.js
index e689c6722..fbebc8a20 100644
--- a/program/js/list.js
+++ b/program/js/list.js
@@ -30,6 +30,9 @@ function rcube_list_widget(list, p)
this.BACKSPACE_KEY = 8;
this.list = list ? list : null;
+ this.tagname = this.list ? this.list.nodeName.toLowerCase() : 'table';
+ this.thead;
+ this.tbody;
this.frame = null;
this.rows = [];
this.selection = [];
@@ -56,7 +59,7 @@ function rcube_list_widget(list, p)
this.focused = false;
this.drag_mouse_start = null;
this.dblclick_time = 600;
- this.row_init = function(){};
+ this.row_init = function(){}; // @deprecated; use list.addEventListener('initrow') instead
// overwrite default paramaters
if (p && typeof p === 'object')
@@ -73,11 +76,19 @@ rcube_list_widget.prototype = {
*/
init: function()
{
- if (this.list && this.list.tBodies[0]) {
+ if (this.tagname == 'table' && this.list && this.list.tBodies[0]) {
+ this.thead = this.list.tHead;
+ this.tbody = this.list.tBodies[0];
+ }
+ else if (this.tagname != 'table' && this.list) {
+ this.tbody = this.list;
+ }
+
+ if (this.tbody) {
this.rows = [];
this.rowcount = 0;
- var r, len, rows = this.list.tBodies[0].rows;
+ var r, len, rows = this.tbody.childNodes;
for (r=0, len=rows.length; r<len; r++) {
this.init_row(rows[r]);
@@ -127,7 +138,8 @@ init_row: function(row)
if (document.all)
row.onselectstart = function() { return false; };
- this.row_init(this.rows[uid]);
+ this.row_init(this.rows[uid]); // legacy support
+ this.triggerEvent('initrow', this.rows[uid]);
}
},
@@ -137,16 +149,16 @@ init_row: function(row)
*/
init_header: function()
{
- if (this.list && this.list.tHead) {
+ if (this.thead) {
this.colcount = 0;
var col, r, p = this;
// add events for list columns moving
- if (this.column_movable && this.list.tHead && this.list.tHead.rows) {
- for (r=0; r<this.list.tHead.rows[0].cells.length; r++) {
+ if (this.column_movable && this.thead && this.thead.rows) {
+ for (r=0; r<this.thead.rows[0].cells.length; r++) {
if (this.column_fixed == r)
continue;
- col = this.list.tHead.rows[0].cells[r];
+ col = this.thead.rows[0].cells[r];
col.onmousedown = function(e){ return p.drag_column(e, this); };
this.colcount++;
}
@@ -160,10 +172,16 @@ init_header: function()
*/
clear: function(sel)
{
- var tbody = document.createElement('tbody');
+ if (this.tagname == 'table') {
+ var tbody = document.createElement('tbody');
+ this.list.insertBefore(tbody, this.tbody);
+ this.list.removeChild(this.list.tBodies[1]);
+ this.tbody = tbody;
+ }
+ else {
+ $(this.row_tagname() + ':not(.thead)', this.tbody).remove();
+ }
- this.list.insertBefore(tbody, this.list.tBodies[0]);
- this.list.removeChild(this.list.tBodies[1]);
this.rows = [];
this.rowcount = 0;
@@ -181,12 +199,12 @@ clear: function(sel)
*/
remove_row: function(uid, sel_next)
{
- var obj = this.rows[uid] ? this.rows[uid].obj : null;
+ var node = this.rows[uid] ? this.rows[uid].obj : null;
- if (!obj)
+ if (!node)
return;
- obj.style.display = 'none';
+ node.style.display = 'none';
if (sel_next)
this.select_next();
@@ -201,9 +219,28 @@ remove_row: function(uid, sel_next)
*/
insert_row: function(row, before)
{
- var tbody = this.list.tBodies[0];
+ var tbody = this.tbody;
+
+ // create a real dom node first
+ if (row.nodeName === undefined) {
+ // for performance reasons use DOM instead of jQuery here
+ var domrow = document.createElement(this.row_tagname());
+ if (row.id) domrow.id = row.id;
+ if (row.className) domrow.className = row.className;
+ if (row.style) $.extend(domrow.style, row.style);
+
+ for (var domcell, col, i=0; row.cols && i < row.cols.length; i++) {
+ col = row.cols[i];
+ domcell = document.createElement(this.col_tagname());
+ if (col.className) domcell.className = col.className;
+ if (col.innerHTML) domcell.innerHTML = col.innerHTML;
+ domrow.appendChild(domcell);
+ }
+
+ row = domrow;
+ }
- if (before && tbody.rows.length)
+ if (before && tbody.childNodes.length)
tbody.insertBefore(row, (typeof before == 'object' && before.parentNode == tbody) ? before : tbody.firstChild);
else
tbody.appendChild(row);
@@ -212,6 +249,28 @@ insert_row: function(row, before)
this.rowcount++;
},
+/**
+ *
+ */
+update_row: function(id, cols, newid, select)
+{
+ var row = this.rows[id];
+ if (!row) return false;
+
+ var domrow = row.obj;
+ for (var domcell, col, i=0; cols && i < cols.length; i++) {
+ this.get_cell(domrow, i).html(cols[i]);
+ }
+
+ if (newid) {
+ delete this.rows[id];
+ domrow.id = 'rcmrow' + newid;
+ this.init_row(domrow);
+
+ if (select)
+ this.selection[0] = newid;
+ }
+},
/**
@@ -230,9 +289,9 @@ focus: function(e)
}
// Un-focus already focused elements (#1487123, #1487316, #1488600, #1488620)
+ // It looks that window.focus() does the job for all browsers, but not Firefox (#1489058)
$(':focus:not(body)').blur();
- // un-focus iframe bodies (#1489058), this doesn't work in Opera and Chrome
- $('iframe').contents().find('body').blur();
+ window.focus();
if (e || (e = window.event))
rcube_event.cancel(e);
@@ -271,8 +330,8 @@ drag_column: function(e, col)
this.add_dragfix();
// find selected column number
- for (var i=0; i<this.list.tHead.rows[0].cells.length; i++) {
- if (col == this.list.tHead.rows[0].cells[i]) {
+ for (var i=0; i<this.thead.rows[0].cells.length; i++) {
+ if (col == this.thead.rows[0].cells[i]) {
this.selected_column = i;
break;
}
@@ -451,7 +510,7 @@ expand: function(row)
this.triggerEvent('expandcollapse', { uid:row.uid, expanded:row.expanded, obj:row.obj });
}
else {
- var tbody = this.list.tBodies[0];
+ var tbody = this.tbody;
new_row = tbody.firstChild;
depth = 0;
last_expanded_parent_depth = 0;
@@ -504,7 +563,7 @@ collapse_all: function(row)
return false;
}
else {
- new_row = this.list.tBodies[0].firstChild;
+ new_row = this.tbody.firstChild;
depth = 0;
}
@@ -543,7 +602,7 @@ expand_all: function(row)
this.triggerEvent('expandcollapse', { uid:row.uid, expanded:row.expanded, obj:row.obj });
}
else {
- new_row = this.list.tBodies[0].firstChild;
+ new_row = this.tbody.firstChild;
depth = 0;
}
@@ -611,7 +670,7 @@ get_prev_row: function()
get_first_row: function()
{
if (this.rowcount) {
- var i, len, rows = this.list.tBodies[0].rows;
+ var i, len, rows = this.tbody.childNodes;
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)
@@ -624,7 +683,7 @@ get_first_row: function()
get_last_row: function()
{
if (this.rowcount) {
- var i, rows = this.list.tBodies[0].rows;
+ var i, rows = this.tbody.childNodes;
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)
@@ -634,6 +693,22 @@ get_last_row: function()
return null;
},
+row_tagname: function()
+{
+ var row_tagnames = { table:'tr', ul:'li', '*':'div' };
+ return row_tagnames[this.tagname] || row_tagnames['*'];
+},
+
+col_tagname: function()
+{
+ var col_tagnames = { table:'td', '*':'span' };
+ return col_tagnames[this.tagname] || col_tagnames['*'];
+},
+
+get_cell: function(row, index)
+{
+ return $(this.col_tagname(), row).eq(index);
+},
/**
* selects or unselects the proper row depending on the modifier key pressed
@@ -781,19 +856,19 @@ shift_select: function(id, control)
this.shift_start = id;
var n, i, j, to_row = this.rows[id],
- from_rowIndex = this.rows[this.shift_start].obj.rowIndex,
- to_rowIndex = to_row.obj.rowIndex;
+ from_rowIndex = this._rowIndex(this.rows[this.shift_start].obj),
+ to_rowIndex = this._rowIndex(to_row.obj);
if (!to_row.expanded && to_row.has_children)
if (to_row = this.rows[(this.row_children(id)).pop()])
- to_rowIndex = to_row.obj.rowIndex;
+ to_rowIndex = this._rowIndex(to_row.obj);
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 (n in this.rows) {
- if (this.rows[n].obj.rowIndex >= i && this.rows[n].obj.rowIndex <= j) {
+ if (this._rowIndex(this.rows[n].obj) >= i && this._rowIndex(this.rows[n].obj) <= j) {
if (!this.in_selection(n)) {
this.highlight_row(n, true);
}
@@ -806,6 +881,13 @@ shift_select: function(id, control)
}
},
+/**
+ * Helper method to emulate the rowIndex property of non-tr elements
+ */
+_rowIndex: function(obj)
+{
+ return (obj.rowIndex !== undefined) ? obj.rowIndex : $(obj).prevAll().length;
+},
/**
* Check if given id is part of the current selection
@@ -1150,7 +1232,7 @@ drag_mouse_move: function(e)
this.draglayer.html('');
// get subjects of selected messages
- var i, n, obj;
+ var i, n, obj, me;
for (n=0; n<this.selection.length; n++) {
// only show 12 lines
if (n>12) {
@@ -1158,29 +1240,28 @@ drag_mouse_move: function(e)
break;
}
+ me = this;
if (obj = this.rows[this.selection[n]].obj) {
- for (i=0; i<obj.childNodes.length; i++) {
- if (obj.childNodes[i].nodeName == 'TD') {
- if (n == 0)
- this.drag_start_pos = $(obj.childNodes[i]).offset();
+ $('> '+this.col_tagname(), obj).each(function(i,elem){
+ if (n == 0)
+ me.drag_start_pos = $(elem).offset();
- if (this.subject_col < 0 || (this.subject_col >= 0 && this.subject_col == i)) {
- var subject = $(obj.childNodes[i]).text();
-
- if (!subject)
- break;
+ if (me.subject_col < 0 || (me.subject_col >= 0 && me.subject_col == i)) {
+ var subject = $(elem).text();
+ if (subject) {
// remove leading spaces
subject = $.trim(subject);
// truncate line to 50 characters
subject = (subject.length > 50 ? subject.substring(0, 50) + '...' : subject);
var entry = $('<div>').text(subject);
- this.draglayer.append(entry);
- break;
+ me.draglayer.append(entry);
}
+
+ return false; // break
}
- }
+ });
}
}
@@ -1255,7 +1336,7 @@ column_drag_mouse_move: function(e)
if (!this.col_draglayer) {
var lpos = $(this.list).offset(),
- cells = this.list.tHead.rows[0].cells;
+ cells = this.thead.rows[0].cells;
// create dragging layer
this.col_draglayer = $('<div>').attr('id', 'rcmcoldraglayer')
@@ -1411,7 +1492,11 @@ del_dragfix: function()
*/
column_replace: function(from, to)
{
- var len, cells = this.list.tHead.rows[0].cells,
+ // only supported for <table> lists
+ if (!this.thead || !this.thead.rows)
+ return;
+
+ var len, cells = this.thead.rows[0].cells,
elem = cells[from],
before = cells[to],
td = document.createElement('td');
@@ -1424,8 +1509,8 @@ column_replace: function(from, to)
cells[0].parentNode.replaceChild(elem, td);
// replace list cells
- for (r=0, len=this.list.tBodies[0].rows.length; r<len; r++) {
- row = this.list.tBodies[0].rows[r];
+ for (r=0, len=this.tbody.rows.length; r<len; r++) {
+ row = this.tbody.rows[r];
elem = row.cells[from];
before = row.cells[to];