From: Michael M Slusarz Date: Wed, 21 Apr 2010 19:39:21 +0000 (-0600) Subject: Further optimize viewport redraw X-Git-Url: https://git.internetallee.de/?a=commitdiff_plain;h=bf7b7cdc8fbf17e607333fd2a42c6e506f1c99b1;p=horde.git Further optimize viewport redraw Try to reuse existing DOM elements, especially for common actions like delete and scrolling. This avoids the overhead of removing/creating the DOM element and the corresponding callbacks (making the element draggable/attaching context menus). --- diff --git a/imp/js/DimpBase.js b/imp/js/DimpBase.js index 49369c6df..6a894d9cc 100644 --- a/imp/js/DimpBase.js +++ b/imp/js/DimpBase.js @@ -520,15 +520,23 @@ var DimpBase = { }); /* Custom ViewPort events. */ + container.observe('ViewPort:add', function(e) { + var row = e.memo.identify(); + + // Add context menu + this._addMouseEvents({ id: row, type: 'message' }); + new Drag(row, this._msgDragConfig); + }.bindAsEventListener(this)); + container.observe('ViewPort:cacheUpdate', function(e) { delete this.cacheids[e.memo]; }.bindAsEventListener(this)); container.observe('ViewPort:clear', function(e) { - e.memo.each(this._removeMouseEvents.bind(this)); + this._removeMouseEvents(e.memo); }.bindAsEventListener(this)); - container.observe('ViewPort:contentComplete', function(e) { + container.observe('ViewPort:contentComplete', function() { var flags, ssc, tmp, ham = spam = 'show', l = this.viewport.getMetaData('label'); @@ -544,12 +552,6 @@ var DimpBase = { this.rownum = null; } - e.memo.each(function(row) { - // Add context menu - this._addMouseEvents({ id: row.VP_domid, type: 'message' }); - new Drag(row.VP_domid, this._msgDragConfig); - }, this); - // 'label' will not be set if there has been an error // retrieving data from the server. l = this.viewport.getMetaData('label'); diff --git a/imp/js/ViewPort.js b/imp/js/ViewPort.js index 4e7975782..de1809f8c 100644 --- a/imp/js/ViewPort.js +++ b/imp/js/ViewPort.js @@ -90,17 +90,21 @@ * Custom events are triggered on the container element. The parameters given * below are available through the 'memo' property of the Event object. * + * ViewPort:add + * Fired when a row has been added to the screen. + * params: (Element) The viewport row being added. + * * ViewPort:cacheUpdate * Fired when the internal cached data of a view is changed. * params: (string) View which is being updated. * * ViewPort:clear * Fired when a row is being removed from the screen. - * params: (array) The list of viewport rows being removed. + * params: (Element) The viewport row being removed. * * ViewPort:contentComplete - * Fired when a row has been added to the screen. - * params: (array) The list of viewport rows that were added. + * Fired when the view has changed and all viewport rows have been added. + * params: NONE * * ViewPort:deselect * Fired when rows are deselected. @@ -323,7 +327,7 @@ var ViewPort = Class.create({ } if (!init) { - this.opts.content.fire('ViewPort:clear', this.visibleRows()); + this.visibleRows().each(this.opts.content.fire.curry('ViewPort:clear')); this.opts.content.update(); this.scroller.clear(); } @@ -435,7 +439,6 @@ var ViewPort = Class.create({ { this._getBuffer(opts.view).setMetaData({ total_rows: this.getMetaData('total_rows', opts.view) - vs.size() }, true); - this.opts.content.fire('ViewPort:clear', vs.get('div').compact()); this._getBuffer().remove(vs.get('rownum')); this.opts.container.fire('ViewPort:cacheUpdate', opts.view || this.view); @@ -901,12 +904,12 @@ var ViewPort = Class.create({ return false; } - var c = this.opts.content, - c_nodes = [], + var added = {}, + c = this.opts.content, page_size = this.getPageSize(), - rows; - - this.opts.container.fire('ViewPort:clear', this.visibleRows()); + tmp = [], + vr = this.visibleRows(), + fdiv, rows; this.scroller.setSize(page_size, this.getMetaData('total_rows')); this.scrollTo(offset + 1, { noupdate: true, top: true }); @@ -919,15 +922,37 @@ var ViewPort = Class.create({ rows = this.createSelection('rownum', $A($R(offset + 1, offset + page_size))); if (rows.size()) { - c_nodes = rows.get('dataob'); - c.update(c_nodes.collect(this.prepareRow.bind(this)).join('')); + fdiv = document.createDocumentFragment().appendChild(new Element('DIV')); + + rows.get('dataob').each(function(r) { + var elt = $(r.VP_domid); + if (elt) { + tmp.push(elt); + } else { + fdiv.update(this.prepareRow(r)); + added[r.VP_domid] = 1; + tmp.push(fdiv.down()); + } + }, this); + + vr.pluck('id').diff(rows.get('domid')).each($).compact().each(this.opts.content.fire.curry('ViewPort:clear')); + + c.childElements().invoke('remove'); + + tmp.each(function(r) { + c.insert(r); + if (added[r.identify()]) { + this.opts.container.fire('ViewPort:add', r); + } + }, this); } else { + vr.each(this.opts.content.fire.curry('ViewPort:clear')); + vr.invoke('remove'); c.update(this.empty_msg); } this.scroller.updateDisplay(); - - this.opts.container.fire('ViewPort:contentComplete', c_nodes); + this.opts.container.fire('ViewPort:contentComplete'); return true; }, @@ -947,11 +972,9 @@ var ViewPort = Class.create({ { var d = $(row.VP_domid); if (d) { - this.opts.container.fire('ViewPort:clear', [ d ]); - + this.opts.container.fire('ViewPort:clear', d); d.replace(this.prepareRow(row)); - - this.opts.container.fire('ViewPort:contentComplete', [ row ]); + this.opts.container.fire('ViewPort:add', $(row.VP_domid)); } },