Improve row rendering.
authorMichael M Slusarz <slusarz@curecanti.org>
Fri, 3 Apr 2009 20:04:01 +0000 (14:04 -0600)
committerMichael M Slusarz <slusarz@curecanti.org>
Fri, 3 Apr 2009 20:46:18 +0000 (14:46 -0600)
Instead of inserting a row into the DOM, and then altering the row via
DOM manipulation/javascript, do all necessary data processing before the
row is inserted into the DOM.

imp/js/src/DimpBase.js
imp/js/src/ViewPort.js
imp/templates/javascript/mailbox-dimp.js

index e8f8bc7..076a13d 100644 (file)
@@ -401,46 +401,70 @@ var DimpBase = {
             page_size: DIMP.conf.splitbar_pos,
             onScrollIdle: settitle,
             onSlide: settitle,
-            onContent: function(rows) {
-                var mf, search,
+            onContent: function(row) {
+                var bg, search,
                     thread = ((this.viewport.getMetaData('sortby') == DIMP.conf.sortthread) && this.viewport.getMetaData('thread'));
+
                 if (this.viewport.isFiltering()) {
-                    search = this.sfilters.get(this._getSearchfilterField()).capitalize();
-                    mf = new RegExp("(" + $F('msgList_filter') + ")", "i");
+                    search = this.sfilters.get(this._getSearchfilterField());
                 }
 
-                rows.get('dataob').each(function(row) {
-                    var elt, tmp, u,
-                        r = $(row.domid);
-
-                    this.updateStatusFlags(row);
-
-                    // Add thread graphics
-                    if (thread && thread.get(row.imapuid)) {
-                        elt = r.down('.msgSubject');
-                        tmp = document.createDocumentFragment();
-                        u = thread.get(row.imapuid);
-                        $R(0, u.length, true).each(function(i) {
-                            var c = u.charAt(i);
-                            if (!this.tcache[c]) {
-                                this.tcache[c] = new Element('SPAN', { className: 'threadImg threadImg' + c });
-                            }
-                            tmp.appendChild(this.tcache[c].cloneNode(false));
-                        }, this);
-                        elt.select('SPAN.threadImg').invoke('remove');
-                        elt.insertBefore(tmp, elt.firstChild);
+                row.subjectdata = row.status = '';
+
+                // Add thread graphics
+                if (thread && thread.get(row.imapuid)) {
+                    u = thread.get(row.imapuid);
+                    $R(0, u.length, true).each(function(i) {
+                        var c = u.charAt(i);
+                        if (!this.tcache[c]) {
+                            this.tcache[c] = '<span class="threadImg threadImg' + c + '"></span>';
+                        }
+                        row.subjectdata += this.tcache[c];
+                    }, this);
+                }
+
+                /* Generate the status flags. */
+                row.flag.each(function(a) {
+                    var ptr = DIMP.conf.flags[a];
+                    if (ptr.p) {
+                        if (!ptr.elt) {
+                            /* Until text-overflow is supported on all
+                             * browsers, need to truncate label text
+                             * ourselves. */
+                            ptr.elt = '<span class="' + ptr.c + '" title="' + ptr.l + '" style="background:' + ptr.b + '">' + ptr.l.truncate(10) + '</span>';
+                        }
+                        row.subjectdata += ptr.elt;
+                    } else {
+                        if (!ptr.elt) {
+                            ptr.elt = '<div class="msgflags ' + ptr.c + '" title="' + ptr.l + '"></div>';
+                        }
+                        row.status += ptr.elt;
+
+                        row.bg_string += ' ' + ptr.c;
+
+                        if (ptr.b) {
+                            bg = ptr.b;
+                        }
                     }
+                });
+
+                // Set bg
+                if (bg) {
+                    row.style = 'background:' + bg;
+                }
 
+                // Highlight search terms
+                if (search == 'from' || search == 'subject') {
+                    row[search] = row[search].gsub(new RegExp("(" + $F('msgList_filter') + ")", "i"), '<span class="searchMatch">#{1}</span>');
+                }
+            }.bind(this),
+            onContentComplete: function(rows) {
+                rows.each(function(row) {
                     // Add context menu
                     this._addMouseEvents({ id: row.domid, type: row.menutype });
-                    new Drag(r, this._msgDragConfig);
-
-                    // Highlight search terms
-                    if (search == 'From' || search == 'Subject') {
-                        elt = r.down('.msg' + search);
-                        elt.update(elt.getText().escapeHTML().gsub(mf, '<span class="searchMatch">#{1}</span>'));
-                    }
+                    new Drag(row.domid, this._msgDragConfig);
                 }, this);
+
                 this.setMessageListTitle();
             }.bind(this),
             onComplete: function() {
@@ -2193,68 +2217,10 @@ var DimpBase = {
             ob.flag = ob.flag.without(flag);
             if (add) {
                 ob.flag.push(flag);
-            } else {
-                var r = $(ob.domid);
-                if (r) {
-                    r.removeClassName(DIMP.conf.flags[flag].c);
-                }
             }
-            this.updateStatusFlags(ob);
-        }, this);
-    },
-
-    updateStatusFlags: function(row)
-    {
-        var bg = null,
-            pf = document.createDocumentFragment(),
-            r = $(row.domid),
-            sf = document.createDocumentFragment(),
-            stat, sub;
 
-        if (!r) {
-            return;
-        }
-
-        stat = r.down('.msgStatus');
-        sub = r.down('.msgSubject');
-
-        /* Clear existing user flags. */
-        sub.select('.flagUser').invoke('remove');
-
-        row.flag.each(function(a) {
-            var ptr = DIMP.conf.flags[a];
-            if (ptr.p) {
-                if (!ptr.elt) {
-                    // Until text-overflow is supported on all browsers,
-                    // need to truncate label text ourselves.
-                    ptr.elt = new Element('SPAN', { className: ptr.c, title: ptr.l }).setStyle({ background: ptr.b }).update(ptr.l.truncate(10));
-                }
-                pf.appendChild(ptr.elt.cloneNode(true));
-            } else {
-                if (!ptr.elt) {
-                    ptr.elt = new Element('DIV', { className: 'msgflags ' + ptr.c, title: ptr.l });
-                }
-                r.addClassName(ptr.c);
-                sf.appendChild(ptr.elt.cloneNode(false));
-                if (ptr.b) {
-                    bg = ptr.b;
-                }
-            }
-        });
-
-        /* Clear existing flags. */
-        stat.down().nextSiblings().invoke('remove');
-
-        /* Add flag graphics. */
-        if (sf.firstChild) {
-            stat.appendChild(sf);
-        }
-        if (pf.firstChild) {
-            sub.insertBefore(pf, sub.lastChild);
-        }
-
-        /* Set (or reset) the background row color. */
-        r.setStyle({ background: bg });
+            this.viewport.updateRow(ob);
+        }, this);
     },
 
     /* Miscellaneous folder actions. */
index e955c78..6610186 100644 (file)
@@ -678,8 +678,7 @@ var ViewPort = Class.create({
         var c = this.opts.content,
             c_nodes = [],
             page_size = this.getPageSize(),
-            rows,
-            sel = this.getSelected();
+            rows;
 
         if (this.opts.onClearRows) {
             this.opts.onClearRows(c.childElements());
@@ -692,31 +691,59 @@ var ViewPort = Class.create({
         rows = this.createSelection('rownum', $A($R(offset + 1, offset + page_size)));
 
         if (rows.size()) {
-            rows.get('dataob').each(function(row) {
-                var r = Object.clone(row);
-                if (r.bg) {
-                    r.bg = row.bg.clone();
-                    if (sel.contains('uid', r.vp_id)) {
-                        r.bg.push(this.opts.selected_class);
-                    }
-                    r.bg_string = r.bg.join(' ');
-                }
-                c_nodes.push(this.template.evaluate(r));
-            }, this);
-            c.update(c_nodes.join(''));
+            c_nodes = rows.get('dataob');
+            c.update(c_nodes.collect(this.prepareRow.bind(this)).join(''));
         } else {
             // If loading a viewport for the first time, show a blank
             // viewport rather than the empty viewport status message.
             c.update((this.opts.empty && this.viewport_init != 1) ? this.opts.empty.innerHTML : '');
         }
 
-        if (this.opts.onContent) {
-            this.opts.onContent(rows);
+        if (this.opts.onContentComplete) {
+            this.opts.onContentComplete(c_nodes);
         }
 
         return true;
     },
 
+    prepareRow: function(row)
+    {
+        var r = Object.clone(row);
+
+        if (r.bg) {
+            r.bg = row.bg.clone();
+            if (this.getSelected().contains('uid', r.vp_id)) {
+                r.bg.push(this.opts.selected_class);
+            }
+            r.bg_string = r.bg.join(' ');
+        } else {
+            r.bg_string = '';
+        }
+
+        if (this.opts.onContent) {
+            this.opts.onContent(r);
+        }
+
+        return this.template.evaluate(r);
+    },
+
+    updateRow: function(row)
+    {
+        var d = $(row.domid);
+        if (d) {
+            if (this.opts.onClearRows) {
+                this.opts.onClearRows([ d ]);
+            }
+
+            d.replace(this.prepareRow(row));
+
+            if (this.opts.onContentComplete) {
+                this.opts.onContentComplete([ row ]);
+            }
+        }
+
+    },
+
     _displayFetchError: function()
     {
         if (this.opts.onFail) {
index 8cb3b89..615bdc8 100644 (file)
@@ -2,6 +2,9 @@
  * mailbox-dimp.js - Template used to format the rows in the message list
  * display.
  *
+ * 'status', 'style', and 'subjectdata' are entries that are internally
+ * created by DimpBase.js.
+ *
  * See the documentation of prototypejs - Template for the template format:
  *   http://www.prototypejs.org/api/template
  *
  */
 
 DimpBase.message_list_template =
-'<div id="#{domid}" class="#{bg_string}">' +
+'<div id="#{domid}" class="#{bg_string}" style="#{style}">' +
  '<div class="msgStatus">' +
   '<div class="msCheck"></div>' +
+  '#{status}' +
  '</div>' +
  '<div class="msgFrom">#{from}</div>' +
- '<div class="msgSubject" title="#{subject}">#{subject}</div>' +
+ '<div class="msgSubject" title="#{subject}">#{subjectdata}#{subject}</div>' +
  '<div class="msgDate">#{date}</div>' +
  '<div class="msgSize">#{size}</div>' +
 '</div>';