+/*
+ * Returns thread root ID for specified row ID
+ */
+find_root: function(uid)
+{
+ var r = this.rows[uid];
+
+ if (r && r.parent_uid)
+ return this.find_root(r.parent_uid);
+ else
+ return uid;
+},
+
+
+expand_row: function(e, id)
+{
+ var row = this.rows[id],
+ evtarget = rcube_event.get_target(e),
+ mod_key = rcube_event.get_modifier(e);
+
+ // Don't select this message
+ this.dont_select = true;
+ // Don't treat double click on the expando as double click on the message.
+ row.clicked = 0;
+
+ if (row.expanded) {
+ evtarget.className = 'collapsed';
+ if (mod_key == CONTROL_KEY || this.multiexpand)
+ this.collapse_all(row);
+ else
+ this.collapse(row);
+ }
+ else {
+ evtarget.className = 'expanded';
+ if (mod_key == CONTROL_KEY || this.multiexpand)
+ this.expand_all(row);
+ else
+ this.expand(row);
+ }
+},
+
+collapse: function(row)
+{
+ row.expanded = false;
+ this.triggerEvent('expandcollapse', { uid:row.uid, expanded:row.expanded });
+ var depth = row.depth;
+ var new_row = row ? row.obj.nextSibling : null;
+ var r;
+
+ while (new_row) {
+ if (new_row.nodeType == 1) {
+ var r = this.rows[new_row.uid];
+ if (r && r.depth <= depth)
+ break;
+ $(new_row).css('display', 'none');
+ if (r.expanded) {
+ r.expanded = false;
+ this.triggerEvent('expandcollapse', { uid:r.uid, expanded:r.expanded });
+ }
+ }
+ new_row = new_row.nextSibling;
+ }
+
+ return false;
+},
+
+expand: function(row)
+{
+ var r, p, depth, new_row, last_expanded_parent_depth;
+
+ if (row) {
+ row.expanded = true;
+ depth = row.depth;
+ new_row = row.obj.nextSibling;
+ this.update_expando(row.uid, true);
+ this.triggerEvent('expandcollapse', { uid:row.uid, expanded:row.expanded });
+ }
+ else {
+ var tbody = this.list.tBodies[0];
+ new_row = tbody.firstChild;
+ depth = 0;
+ last_expanded_parent_depth = 0;
+ }
+
+ while (new_row) {
+ if (new_row.nodeType == 1) {
+ r = this.rows[new_row.uid];
+ if (r) {
+ if (row && (!r.depth || r.depth <= depth))
+ break;
+
+ if (r.parent_uid) {
+ p = this.rows[r.parent_uid];
+ if (p && p.expanded) {
+ if ((row && p == row) || last_expanded_parent_depth >= p.depth - 1) {
+ last_expanded_parent_depth = p.depth;
+ $(new_row).css('display', '');
+ r.expanded = true;
+ this.triggerEvent('expandcollapse', { uid:r.uid, expanded:r.expanded });
+ }
+ }
+ else
+ if (row && (! p || p.depth <= depth))
+ break;
+ }
+ }
+ }
+ new_row = new_row.nextSibling;
+ }
+
+ return false;
+},
+
+
+collapse_all: function(row)
+{
+ var depth, new_row, r;
+
+ if (row) {
+ row.expanded = false;
+ depth = row.depth;
+ new_row = row.obj.nextSibling;
+ this.update_expando(row.uid);
+ this.triggerEvent('expandcollapse', { uid:row.uid, expanded:row.expanded });
+
+ // don't collapse sub-root tree in multiexpand mode
+ if (depth && this.multiexpand)
+ return false;
+ }
+ else {
+ new_row = this.list.tBodies[0].firstChild;
+ depth = 0;
+ }
+
+ while (new_row) {
+ if (new_row.nodeType == 1) {
+ if (r = this.rows[new_row.uid]) {
+ if (row && (!r.depth || r.depth <= depth))
+ break;
+
+ if (row || r.depth)
+ $(new_row).css('display', 'none');
+ if (r.has_children && r.expanded) {
+ r.expanded = false;
+ this.update_expando(r.uid, false);
+ this.triggerEvent('expandcollapse', { uid:r.uid, expanded:r.expanded });
+ }
+ }
+ }
+ new_row = new_row.nextSibling;
+ }
+
+ return false;
+},
+
+expand_all: function(row)
+{
+ var depth, new_row, r;
+
+ if (row) {
+ row.expanded = true;
+ depth = row.depth;
+ new_row = row.obj.nextSibling;
+ this.update_expando(row.uid, true);
+ this.triggerEvent('expandcollapse', { uid:row.uid, expanded:row.expanded });
+ }
+ else {
+ new_row = this.list.tBodies[0].firstChild;
+ depth = 0;
+ }
+
+ while (new_row) {
+ if (new_row.nodeType == 1) {
+ if (r = this.rows[new_row.uid]) {
+ if (row && r.depth <= depth)
+ break;
+
+ $(new_row).css('display', '');
+ if (r.has_children && !r.expanded) {
+ r.expanded = true;
+ this.update_expando(r.uid, true);
+ this.triggerEvent('expandcollapse', { uid:r.uid, expanded:r.expanded });
+ }
+ }
+ }
+ new_row = new_row.nextSibling;
+ }
+ return false;
+},
+
+update_expando: function(uid, expanded)
+{
+ var expando = document.getElementById('rcmexpando' + uid);
+ if (expando)
+ expando.className = expanded ? 'expanded' : 'collapsed';
+},
+
+