From 24b483db367291b72170f969de78efcb1a9b95bd Mon Sep 17 00:00:00 2001 From: Valerio Virgillito Date: Thu, 3 May 2012 22:53:07 -0700 Subject: integrating the latest montage version Signed-off-by: Valerio Virgillito --- node_modules/montage/ui/component.js | 201 +++++++++++++++++++++++------------ 1 file changed, 135 insertions(+), 66 deletions(-) (limited to 'node_modules/montage/ui/component.js') diff --git a/node_modules/montage/ui/component.js b/node_modules/montage/ui/component.js index 17f87b62..9d963ada 100755 --- a/node_modules/montage/ui/component.js +++ b/node_modules/montage/ui/component.js @@ -414,6 +414,11 @@ var Component = exports.Component = Montage.create(Montage,/** @lends module:mon _template: { value: null }, + + // Tree level necessary for ordering drawing re: parent-child + _treeLevel: { + value: 0 + }, /** Description TODO @function @@ -909,15 +914,15 @@ var Component = exports.Component = Montage.create(Montage,/** @lends module:mon if (!templateModuleId) { moduleId = info.moduleId; // TODO: backwards compatibility for components with its controller outside the reel folder - //console.log(moduleId); - if (/([^\/]+)\.reel\/\1$/.exec(moduleId)) { - templateModuleId = moduleId + ".html"; - } else if (/([^\/]+)\.reel$/.exec(moduleId)) { - templateModuleId = moduleId + "/" + RegExp.$1 + ".html"; - } else { - templateModuleId = moduleId + ".reel/" + moduleId.split("/").pop() + ".html"; - } - //console.log(moduleId + " === " + templateModuleId); + //if (/([^\/]+)\.reel\/\1$/.exec(moduleId)) { + // templateModuleId = moduleId + ".html"; + //} else if (/([^\/]+)\.reel$/.exec(moduleId)) { + // templateModuleId = moduleId + "/" + RegExp.$1 + ".html"; + //} else { + var slashIndex = moduleId.lastIndexOf("/"); + //templateModuleId = moduleId + ".reel/" + moduleId.split("/").pop() + ".html"; + templateModuleId = moduleId + "/" + moduleId.slice(slashIndex === -1 ? 0 : slashIndex+1, -5) + ".html"; + //} } if (logger.isDebug) { logger.debug(this, "Will load " + templateModuleId); @@ -971,14 +976,6 @@ var Component = exports.Component = Montage.create(Montage,/** @lends module:mon enumerable: false, value: false }, -/** - Description TODO - @private -*/ - _isDrawing: { - enumerable: false, - value: false - }, /** If needsDraw property returns true this call adds the current component instance to the rootComponents draw list.
@@ -989,11 +986,11 @@ var Component = exports.Component = Montage.create(Montage,/** @lends module:mon */ _drawIfNeeded: { enumerable: false, - value: function _drawIfNeeded() { - var body, - childComponent, + value: function _drawIfNeeded(level) { + var childComponent, oldDrawList; - if (this.needsDraw) { + this._treeLevel = level; + if (this.needsDraw && !this._addedToDrawCycle) { rootComponent.addToDrawCycle(this); } if (drawLogger.isDebug) { @@ -1011,7 +1008,7 @@ var Component = exports.Component = Montage.create(Montage,/** @lends module:mon drawLogger.debug(this, "childComponent: " + childComponent.element + "; canDraw: " + childComponent.canDraw()); } if (childComponent.canDraw()) { // TODO if canDraw is false when does needsDraw get reset? - childComponent._drawIfNeeded(); + childComponent._drawIfNeeded(level+1); } } } @@ -1066,11 +1063,6 @@ var Component = exports.Component = Montage.create(Montage,/** @lends module:mon if (this._templateElement) { this._replaceElementWithTemplate(); } - // TODO: removeAttribute only here for backwards compatibility - if (!this._element.getAttribute("data-montage-id")) { - this._element.removeAttribute("id"); - } - // This will schedule a second draw for any component that has children var childComponents = this.childComponents; for (var i = 0, childComponent; (childComponent = childComponents[i]); i++) { @@ -1153,16 +1145,6 @@ var Component = exports.Component = Montage.create(Montage,/** @lends module:mon value: function() { } }, - - /** - Allows draw to be called even if the children can't draw. - @type {Property} - @default {Boolean} false - */ - allowsPartialDraw: { - value: false - }, - /** Description TODO @type {Property} @@ -1296,10 +1278,7 @@ var Component = exports.Component = Montage.create(Montage,/** @lends module:mon enumerable: false, value: function(childComponent) { this.__addToDrawList(childComponent); - // if we are not added to the parent yet we add ourselves so that we build the tree - if (!this._isDrawing) { - this._addToParentsDrawList(); - } + this._addToParentsDrawList(); } }, @@ -1411,12 +1390,10 @@ var Component = exports.Component = Montage.create(Montage,/** @lends module:mon */ clearAllComposers: { value: function() { - var length, i; - length = this.composerList.length; - for (i = 0; i < length; i++) { - this.composerList[i].unload(); + var composer; + while (composer = this.composerList.shift()) { + composer.unload(); } - this.composerList = []; } } @@ -1623,6 +1600,12 @@ var rootComponent = Montage.create(Component, /** @lends module:montage/ui/compo } }, + // Create a second composer list so that the lists can be swapped during a draw instead of creating a new array every time + composerListSwap: { + value: [], + distinct: true + }, + /* Flag to track if a composer is requesting a draw @private @@ -1669,6 +1652,58 @@ var rootComponent = Montage.create(Component, /** @lends module:montage/ui/compo _frameTime: { value: null }, + + // oldSource and diff are used to detect DOM modifications outside of the + // draw loop, but only if drawLogger.isDebug is true. + _oldSource: { + value: null + }, + _diff: { + // Written by John Resig. Used under the Creative Commons Attribution 2.5 License. + // http://ejohn.org/projects/javascript-diff-algorithm/ + value: function( o, n ) { + var ns = {}; + var os = {}; + + for ( var i = 0; i < n.length; i++ ) { + if ( ns[ n[i] ] == null ) + ns[ n[i] ] = { rows: [], o: null }; + ns[ n[i] ].rows.push( i ); + } + + for (i = 0; i < o.length; i++ ) { + if ( os[ o[i] ] == null ) + os[ o[i] ] = { rows: [], n: null }; + os[ o[i] ].rows.push( i ); + } + + for (i in ns ) { + if ( ns[i].rows.length == 1 && typeof(os[i]) != "undefined" && os[i].rows.length == 1 ) { + n[ ns[i].rows[0] ] = { text: n[ ns[i].rows[0] ], row: os[i].rows[0] }; + o[ os[i].rows[0] ] = { text: o[ os[i].rows[0] ], row: ns[i].rows[0] }; + } + } + + for (i = 0; i < n.length - 1; i++ ) { + if ( n[i].text != null && n[i+1].text == null && n[i].row + 1 < o.length && o[ n[i].row + 1 ].text == null && + n[i+1] == o[ n[i].row + 1 ] ) { + n[i+1] = { text: n[i+1], row: n[i].row + 1 }; + o[n[i].row+1] = { text: o[n[i].row+1], row: i + 1 }; + } + } + + for (i = n.length - 1; i > 0; i-- ) { + if ( n[i].text != null && n[i-1].text == null && n[i].row > 0 && o[ n[i].row - 1 ].text == null && + n[i-1] == o[ n[i].row - 1 ] ) { + n[i-1] = { text: n[i-1], row: n[i].row - 1 }; + o[n[i].row-1] = { text: o[n[i].row-1], row: i - 1 }; + } + } + + return { o: o, n: n }; + } + }, + /** Description TODO @function @@ -1686,11 +1721,33 @@ var rootComponent = Montage.create(Component, /** @lends module:montage/ui/compo self._clearNeedsDrawList(); } if (drawLogger.isDebug) { + // Detect any DOM modification since the previous draw + var newSource = document.getElementsByTagName('html')[0].innerHTML; + if (self._oldSource && newSource !== self._oldSource) { + var warning = ["DOM modified outside of the draw loop"]; + var out = self._diff(self._oldSource.split("\n"), newSource.split("\n")); + for (var i = 0; i < out.n.length; i++) { + // == null ok. Is also checking for undefined + if (out.n[i].text == null) { + warning.push('+ ' + out.n[i]); + } else { + // == null ok. Is also checking for undefined + for (var n = out.n[i].row + 1; n < out.o.length && out.o[n].text == null; n++) { + warning.push('- ' + out.o[n]); + } + } + } + console.warn(warning.join("\n")); + } + console.group((timestamp ? drawLogger.toTimeString(new Date(timestamp)) + " " : "") + "Draw Fired"); } + self.drawIfNeeded(); + if (drawLogger.isDebug) { console.groupEnd(); + self._oldSource = document.getElementsByTagName('html')[0].innerHTML; } self._frameTime = null; if (self._scheduleComposerRequest) { @@ -1708,14 +1765,6 @@ var rootComponent = Montage.create(Component, /** @lends module:montage/ui/compo }, enumerable: false }, -/** - Description TODO - @type {Property} - @default null - */ - dispatchDrawEvent: { - value: null - }, /** Description TODO @private @@ -1785,42 +1834,59 @@ var rootComponent = Montage.create(Component, /** @lends module:montage/ui/compo */ drawIfNeeded:{ value: function drawIfNeeded() { - var needsDrawList = this._readyToDrawList, component, j, i, start = 0, firstDrawEvent, - composerList = this.composerList, composer, length; + var needsDrawList = this._readyToDrawList, component, i, j, start = 0, firstDrawEvent, + composerList = this.composerList, composer; needsDrawList.length = 0; this._readyToDrawListIndex = {}; - this.composerList = []; // Process the composers first so that any components that need to be newly drawn due to composer changes // get added in this cycle - length = composerList.length; - for (i = 0; i < length; i++) { - composer = composerList[i]; - composer.needsFrame = false; - composer.frame(this._frameTime); + if (composerList.length > 0) { + this.composerList = this.composerListSwap; // Swap between two arrays instead of creating a new array each draw cycle + while (composer = composerList.shift()) { + composer.needsFrame = false; + composer.frame(this._frameTime); + } + this.composerListSwap = composerList; } - this._drawIfNeeded(); + this._drawIfNeeded(0); j = needsDrawList.length; + while (start < j) { for (i = start; i < j; i++) { component = needsDrawList[i]; if (typeof component.willDraw === "function") { component.willDraw(this._frameTime); } + if (drawLogger.isDebug) { + drawLogger.debug(component._montage_metadata.objectName, " willDraw treeLevel ",component._treeLevel); + } } - this._drawIfNeeded(); + this._drawIfNeeded(0); start = j; j = needsDrawList.length; } - this.requestedAnimationFrame = null; // Allow a needsDraw called during a draw to schedule the next draw - // TODO: add the posibility to display = "none" the body during development (IKXARIA-3631). + // Sort the needsDraw list so that any newly added items are drawn in the correct order re: parent-child + var sortByLevel = function(component1, component2) { + return component1._treeLevel - component2._treeLevel; + } + needsDrawList.sort(sortByLevel); + for (i = 0; i < j; i++) { component = needsDrawList[i]; component.needsDraw = false; + } + this.requestedAnimationFrame = null; // Allow a needsDraw called during a draw to schedule the next draw + // TODO: add the possibility to display = "none" the body during development (IKXARIA-3631). + for (i = j-1; i >= 0; i--) { + component = needsDrawList[i]; component._draw(); component.draw(this._frameTime); + if (drawLogger.isDebug) { + drawLogger.debug(component._montage_metadata.objectName, " draw treeLevel ",component._treeLevel); + } } for (i = 0; i < j; i++) { @@ -1832,6 +1898,9 @@ var rootComponent = Montage.create(Component, /** @lends module:montage/ui/compo component.dispatchEvent(firstDrawEvent); component._completedFirstDraw = true; } + if (drawLogger.isDebug) { + drawLogger.debug(component._montage_metadata.objectName, " didDraw treeLevel ",component._treeLevel); + } } return !!needsDrawList.length; } -- cgit v1.2.3