+ this.init_message_row = function(row)
+ {
+ var expando, self = this, uid = row.uid,
+ status_icon = (this.env.status_col != null ? 'status' : 'msg') + 'icn' + row.uid;
+
+ if (uid && this.env.messages[uid])
+ $.extend(row, this.env.messages[uid]);
+
+ // set eventhandler to status icon
+ if (row.icon = document.getElementById(status_icon)) {
+ row.icon._row = row.obj;
+ row.icon.onmousedown = function(e) { self.command('toggle_status', this); rcube_event.cancel(e); };
+ }
+
+ // save message icon position too
+ if (this.env.status_col != null)
+ row.msgicon = document.getElementById('msgicn'+row.uid);
+ else
+ row.msgicon = row.icon;
+
+ // set eventhandler to flag icon, if icon found
+ if (this.env.flagged_col != null && (row.flagicon = document.getElementById('flagicn'+row.uid))) {
+ row.flagicon._row = row.obj;
+ row.flagicon.onmousedown = function(e) { self.command('toggle_flag', this); rcube_event.cancel(e); };
+ }
+
+ 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); };
+ }
+
+ this.triggerEvent('insertrow', { uid:uid, row:row });
+ };
+
+ // create a table row in the message list
+ this.add_message_row = function(uid, cols, flags, attop)
+ {
+ if (!this.gui_objects.messagelist || !this.message_list)
+ return false;
+
+ if (!this.env.messages[uid])
+ this.env.messages[uid] = {};
+
+ // merge flags over local message object
+ $.extend(this.env.messages[uid], {
+ deleted: flags.deleted?1:0,
+ replied: flags.replied?1:0,
+ unread: flags.unread?1:0,
+ forwarded: flags.forwarded?1:0,
+ flagged: flags.flagged?1:0,
+ has_children: flags.has_children?1:0,
+ depth: flags.depth?flags.depth:0,
+ 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),
+ ml: flags.ml?1:0,
+ ctype: flags.ctype,
+ // flags from plugins
+ flags: flags.extra_flags
+ });
+
+ var c, html, 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],
+ css_class = 'message'
+ + (even ? ' even' : ' odd')
+ + (flags.unread ? ' unread' : '')
+ + (flags.deleted ? ' deleted' : '')
+ + (flags.flagged ? ' flagged' : '')
+ + (flags.unread_children && !flags.unread && !this.env.autoexpand_threads ? ' unroot' : '')
+ + (message.selected ? ' selected' : ''),
+ // for performance use DOM instead of jQuery here
+ row = document.createElement('tr'),
+ col = document.createElement('td');
+
+ row.id = 'rcmrow'+uid;
+ row.className = css_class;
+
+ // message status icons
+ css_class = 'msgicon';
+ if (this.env.status_col === null) {
+ css_class += ' status';
+ if (flags.deleted)
+ css_class += ' deleted';
+ else if (flags.unread)
+ css_class += ' unread';
+ else if (flags.unread_children > 0)
+ css_class += ' unreadchildren';
+ }
+ if (flags.replied)
+ css_class += ' replied';
+ if (flags.forwarded)
+ css_class += ' forwarded';
+
+ // update selection
+ if (message.selected && !list.in_selection(uid))
+ list.selection.push(uid);
+
+ // threads
+ if (this.env.threading) {
+ // This assumes that div width is hardcoded to 15px,
+ var width = message.depth * 15;
+ if (message.depth) {
+ if ((rows[message.parent_uid] && rows[message.parent_uid].expanded === false)
+ || ((this.env.autoexpand_threads == 0 || this.env.autoexpand_threads == 2) &&
+ (!rows[message.parent_uid] || !rows[message.parent_uid].expanded))
+ ) {
+ row.style.display = 'none';
+ message.expanded = false;
+ }
+ else
+ message.expanded = true;
+ }
+ else if (message.has_children) {
+ if (typeof(message.expanded) == 'undefined' && (this.env.autoexpand_threads == 1 || (this.env.autoexpand_threads == 2 && message.unread_children))) {
+ message.expanded = true;
+ }
+ }
+
+ if (width)
+ tree += '<span id="rcmtab' + uid + '" class="branch" style="width:' + width + 'px;"> </span>';
+
+ if (message.has_children && !message.depth)
+ expando = '<div id="rcmexpando' + uid + '" class="' + (message.expanded ? 'expanded' : 'collapsed') + '"> </div>';
+ }
+
+ tree += '<span id="msgicn'+uid+'" class="'+css_class+'"> </span>';
+
+ // build subject link
+ if (!bw.ie && cols.subject) {
+ var action = flags.mbox == this.env.drafts_mailbox ? 'compose' : 'show';
+ var uid_param = flags.mbox == this.env.drafts_mailbox ? '_draft_uid' : '_uid';
+ cols.subject = '<a href="./?_task=mail&_action='+action+'&_mbox='+urlencode(flags.mbox)+'&'+uid_param+'='+uid+'"'+
+ ' onclick="return rcube_event.cancel(event)" onmouseover="rcube_webmail.long_subject_title(this,'+(message.depth+1)+')">'+cols.subject+'</a>';
+ }
+
+ // add each submitted col
+ for (var n in this.env.coltypes) {
+ c = this.env.coltypes[n];
+ col = document.createElement('td');
+ col.className = String(c).toLowerCase();
+
+ if (c == 'flag') {
+ css_class = (flags.flagged ? 'flagged' : 'unflagged');
+ html = '<span id="flagicn'+uid+'" class="'+css_class+'"> </span>';
+ }
+ else if (c == 'attachment') {
+ if (/application\/|multipart\/m/.test(flags.ctype))
+ html = '<span class="attachment"> </span>';
+ else if (/multipart\/report/.test(flags.ctype))
+ html = '<span class="report"> </span>';
+ else
+ html = ' ';
+ }
+ else if (c == 'status') {
+ if (flags.deleted)
+ css_class = 'deleted';
+ else if (flags.unread)
+ css_class = 'unread';
+ else if (flags.unread_children > 0)
+ css_class = 'unreadchildren';
+ else
+ css_class = 'msgicon';
+ html = '<span id="statusicn'+uid+'" class="'+css_class+'"> </span>';
+ }
+ else if (c == 'threads')
+ html = expando;
+ else if (c == 'subject')
+ html = tree + cols[c];
+ else
+ html = cols[c];
+
+ col.innerHTML = html;
+
+ row.appendChild(col);
+ }
+
+ list.insert_row(row, attop);
+
+ // remove 'old' row
+ if (attop && this.env.pagesize && list.rowcount > this.env.pagesize) {
+ var uid = list.get_last_row();
+ list.remove_row(uid);
+ list.clear_selection(uid);
+ }
+ };
+
+ this.set_list_sorting = function(sort_col, sort_order)
+ {
+ // set table header class
+ $('#rcm'+this.env.sort_col).removeClass('sorted'+(this.env.sort_order.toUpperCase()));
+ if (sort_col)
+ $('#rcm'+sort_col).addClass('sorted'+sort_order);
+
+ this.env.sort_col = sort_col;
+ this.env.sort_order = sort_order;
+ };
+
+ this.set_list_options = function(cols, sort_col, sort_order, threads)
+ {
+ var update, add_url = '';
+
+ if (typeof sort_col == 'undefined')
+ sort_col = this.env.sort_col;
+ if (!sort_order)
+ sort_order = this.env.sort_order;
+
+ if (this.env.sort_col != sort_col || this.env.sort_order != sort_order) {
+ update = 1;
+ this.set_list_sorting(sort_col, sort_order);
+ }
+
+ if (this.env.threading != threads) {
+ update = 1;
+ add_url += '&_threads=' + threads;
+ }
+
+ if (cols && cols.length) {
+ // make sure new columns are added at the end of the list
+ var i, idx, name, newcols = [], oldcols = this.env.coltypes;
+ for (i=0; i<oldcols.length; i++) {
+ name = oldcols[i] == 'to' ? 'from' : oldcols[i];
+ idx = $.inArray(name, cols);
+ if (idx != -1) {
+ newcols.push(name);
+ delete cols[idx];
+ }
+ }
+ for (i=0; i<cols.length; i++)
+ if (cols[i])
+ newcols.push(cols[i]);
+
+ if (newcols.join() != oldcols.join()) {
+ update = 1;
+ add_url += '&_cols=' + newcols.join(',');
+ }
+ }
+
+ if (update)
+ this.list_mailbox('', '', sort_col+'_'+sort_order, add_url);
+ };
+