From 22a66cb6e243a3f1c867b62e3942fd2e828019d9 Mon Sep 17 00:00:00 2001 From: Valerio Virgillito Date: Thu, 8 Mar 2012 13:56:09 -0800 Subject: integrating v0.7 montage into ninja Signed-off-by: Valerio Virgillito --- node_modules/montage/ui/application.js | 4 +- .../montage/ui/bluemoon/progress.reel/progress.js | 20 +- node_modules/montage/ui/check-input.js | 2 +- node_modules/montage/ui/checkbox.reel/checkbox.js | 2 +- node_modules/montage/ui/component.js | 115 ++- node_modules/montage/ui/composer/press-composer.js | 9 +- .../montage/ui/composer/translate-composer.js | 77 +- .../montage/ui/condition.reel/condition.js | 24 +- .../montage/ui/controller/array-controller.js | 8 +- node_modules/montage/ui/list.reel/list.html | 10 +- node_modules/montage/ui/loader.reel/loader.js | 6 +- .../ui/loading-panel.reel/loading-panel.css | 38 +- .../ui/loading-panel.reel/loading-panel.html | 6 +- node_modules/montage/ui/native-control.js | 3 - .../montage/ui/popup/confirm.reel/confirm.js | 4 +- node_modules/montage/ui/popup/popup.reel/popup.js | 159 ++-- node_modules/montage/ui/progress.reel/progress.css | 51 -- .../montage/ui/progress.reel/progress.html | 32 - node_modules/montage/ui/progress.reel/progress.js | 144 +--- node_modules/montage/ui/progress.reel/rule.png | Bin 956 -> 0 bytes node_modules/montage/ui/progress.reel/scroll.png | Bin 272 -> 0 bytes .../montage/ui/radio-button.reel/radio-button.js | 3 +- .../montage/ui/repetition.reel/repetition.js | 127 +++- node_modules/montage/ui/scroll.js | 820 --------------------- .../montage/ui/scroller.reel/scroller.html | 1 + node_modules/montage/ui/scroller.reel/scroller.js | 36 +- .../montage/ui/select-input.reel/select-input.js | 115 ++- .../ui/skeleton/range-input.reel/range-input.css | 27 + .../ui/skeleton/range-input.reel/range-input.html | 62 ++ .../ui/skeleton/range-input.reel/range-input.js | 234 ++++++ node_modules/montage/ui/slot.reel/slot.js | 19 +- node_modules/montage/ui/template.js | 4 + node_modules/montage/ui/text-input.js | 16 +- node_modules/montage/ui/textarea.reel/textarea.js | 2 +- .../montage/ui/toggle-button.reel/toggle-button.js | 9 +- .../ui/toggle-switch.reel/toggle-switch.css | 162 ++++ .../ui/toggle-switch.reel/toggle-switch.html | 16 + .../montage/ui/toggle-switch.reel/toggle-switch.js | 424 +++++++++++ 38 files changed, 1454 insertions(+), 1337 deletions(-) delete mode 100755 node_modules/montage/ui/progress.reel/progress.css delete mode 100755 node_modules/montage/ui/progress.reel/progress.html delete mode 100755 node_modules/montage/ui/progress.reel/rule.png delete mode 100755 node_modules/montage/ui/progress.reel/scroll.png delete mode 100755 node_modules/montage/ui/scroll.js create mode 100644 node_modules/montage/ui/skeleton/range-input.reel/range-input.css create mode 100644 node_modules/montage/ui/skeleton/range-input.reel/range-input.html create mode 100644 node_modules/montage/ui/skeleton/range-input.reel/range-input.js create mode 100755 node_modules/montage/ui/toggle-switch.reel/toggle-switch.css create mode 100755 node_modules/montage/ui/toggle-switch.reel/toggle-switch.html create mode 100644 node_modules/montage/ui/toggle-switch.reel/toggle-switch.js (limited to 'node_modules/montage/ui') diff --git a/node_modules/montage/ui/application.js b/node_modules/montage/ui/application.js index c7b3dc73..7cb4bd97 100755 --- a/node_modules/montage/ui/application.js +++ b/node_modules/montage/ui/application.js @@ -175,7 +175,7 @@ var Application = exports.Application = Montage.create(Montage, /** @lends monta _createPopupSlot: {value: function(zIndex) { var slotEl = document.createElement('div'); document.body.appendChild(slotEl); - slotEl.style['z-index'] = zIndex; + slotEl.style.zIndex = zIndex; slotEl.style.position = 'absolute'; var popupSlot = Slot.create(); @@ -221,7 +221,7 @@ var Application = exports.Application = Montage.create(Montage, /** @lends monta } // use the new zIndex for custom popup if(!isSystemPopup) { - popupSlot.element.style['z-index'] = zIndex; + popupSlot.element.style.zIndex = zIndex; } popupSlot.content = content; diff --git a/node_modules/montage/ui/bluemoon/progress.reel/progress.js b/node_modules/montage/ui/bluemoon/progress.reel/progress.js index 8bc68b05..20c60d94 100644 --- a/node_modules/montage/ui/bluemoon/progress.reel/progress.js +++ b/node_modules/montage/ui/bluemoon/progress.reel/progress.js @@ -43,8 +43,8 @@ exports.Progress = Montage.create(Component,/** @lends module:"montage/ui/bluemo set: function(val) { if(val !== this._value) { this._value = val; - if(this._value > this._maximumValue) { - this._value = this._maximumValue; + if(this._value > this._max) { + this._value = this._max; } if(this._value < 0) { this._value = 0; @@ -57,7 +57,7 @@ exports.Progress = Montage.create(Component,/** @lends module:"montage/ui/bluemo Description TODO @private */ - _maximumValue: { + _max: { enumerable: false, value: 100 }, @@ -66,15 +66,15 @@ exports.Progress = Montage.create(Component,/** @lends module:"montage/ui/bluemo @type {Function} @default {Number} 100 */ - maximumValue: { + max: { get: function() { - return this._maximumValue; + return this._max; }, set: function(val) { - if(val !== this._maximumValue) { - this._maximumValue = val; - if(this._maximumValue <= 0) { - this._maximumValue = 1; // Prevent divide by zero errors + if(val !== this._max) { + this._max = val; + if(this._max <= 0) { + this._max = 1; // Prevent divide by zero errors } this.needsDraw = true; } @@ -120,7 +120,7 @@ exports.Progress = Montage.create(Component,/** @lends module:"montage/ui/bluemo draw: { enumerable: false, value: function() { - var ratio = this._value / this._maximumValue; + var ratio = this._value / this._max; // constrain to interval [0, 1] ratio = Math.min(Math.max(ratio, 0), 1); // map into [0, 100] diff --git a/node_modules/montage/ui/check-input.js b/node_modules/montage/ui/check-input.js index 42538c02..1621eb45 100644 --- a/node_modules/montage/ui/check-input.js +++ b/node_modules/montage/ui/check-input.js @@ -69,7 +69,7 @@ var CheckInput = exports.CheckInput = Montage.create(NativeControl, { Stores if we need to fake checking. When preventDefault is called on touchstart and touchend events (e.g. by - the scrollview component) the checkbox doesn't check itself, so we need + the scroller component) the checkbox doesn't check itself, so we need to fake it later. @default false diff --git a/node_modules/montage/ui/checkbox.reel/checkbox.js b/node_modules/montage/ui/checkbox.reel/checkbox.js index df2995c3..c6364e97 100644 --- a/node_modules/montage/ui/checkbox.reel/checkbox.js +++ b/node_modules/montage/ui/checkbox.reel/checkbox.js @@ -9,7 +9,7 @@ var Montage = require("montage").Montage, var Checkbox = exports.Checkbox = Montage.create(CheckInput, {}); Checkbox.addAttributes({ - autofocus: 'off', // on/off + autofocus: {value: false, dataType: 'boolean'}, disabled: {value: false, dataType: 'boolean'}, checked: {value: false, dataType: 'boolean'}, form: null, diff --git a/node_modules/montage/ui/component.js b/node_modules/montage/ui/component.js index d347f655..69559fc1 100755 --- a/node_modules/montage/ui/component.js +++ b/node_modules/montage/ui/component.js @@ -59,7 +59,6 @@ var Component = exports.Component = Montage.create(Montage,/** @lends module:mon value: function() { var actionEvent = document.createEvent("CustomEvent"); actionEvent.initCustomEvent("action", true, true, null); - actionEvent.type = "action"; return actionEvent; } }, @@ -162,6 +161,15 @@ var Component = exports.Component = Montage.create(Montage,/** @lends module:mon } }, + setElementWithParentComponent: { + value: function(element, parent) { + this._alternateParentComponent = parent; + if (this.element != element) { + this.element = element; + } + } + }, + // access to the Application object /** Description TODO @@ -215,6 +223,11 @@ var Component = exports.Component = Montage.create(Montage,/** @lends module:mon return targetElementController; } }, + + _alternateParentComponent: { + value: null + }, + /** Description TODO @private @@ -235,21 +248,27 @@ var Component = exports.Component = Montage.create(Montage,/** @lends module:mon get: function() { var cachedParentComponent = this._cachedParentComponent; if (cachedParentComponent == null) { - var anElement = this.element, - aParentNode, - eventManager = this.eventManager; - if (anElement) { - while ((aParentNode = anElement.parentNode) !== null && eventManager.eventHandlerForElement(aParentNode) == null) { - anElement = aParentNode; - } - return (this._cachedParentComponent = aParentNode ? eventManager.eventHandlerForElement(aParentNode) : null); - } + return (this._cachedParentComponent = this.findParentComponent()); } else { return cachedParentComponent; } } }, + findParentComponent: { + value: function() { + var anElement = this.element, + aParentNode, + eventManager = this.eventManager; + if (anElement) { + while ((aParentNode = anElement.parentNode) !== null && eventManager.eventHandlerForElement(aParentNode) == null) { + anElement = aParentNode; + } + return aParentNode ? eventManager.eventHandlerForElement(aParentNode) : this._alternateParentComponent; + } + } + }, + querySelectorComponent: { value: function(selector) { if (typeof selector !== "string") { @@ -406,19 +425,30 @@ var Component = exports.Component = Montage.create(Montage,/** @lends module:mon attachToParentComponent: { value: function() { this._cachedParentComponent = null; - - var parentComponent = this.parentComponent; - + + var parentComponent = this.parentComponent, + childComponents, + childComponent; + if (parentComponent) { + childComponents = parentComponent.childComponents; + for (var i = 0; (childComponent = childComponents[i]); i++) { + var newParentComponent = childComponent.findParentComponent(); + if (newParentComponent === this) { + parentComponent.removeChildComponent(childComponent); + newParentComponent._addChildComponent(childComponent); + } + } + parentComponent._addChildComponent(this); } } }, - + detachFromParentComponent: { value: function() { var parentComponent = this.parentComponent; - + if (parentComponent) { parentComponent.removeChildComponent(this); } @@ -438,6 +468,7 @@ var Component = exports.Component = Montage.create(Montage,/** @lends module:mon if (ix > -1) { childComponents.splice(ix, 1); childComponent._cachedParentComponent = null; + childComponent._alternateParentComponent = null; } } }, @@ -458,7 +489,6 @@ var Component = exports.Component = Montage.create(Montage,/** @lends module:mon */ ownerComponent: { enumerable: false, - serializable: true, value: null }, /** @@ -488,7 +518,7 @@ var Component = exports.Component = Montage.create(Montage,/** @lends module:mon enumerable: false, value: null }, - + /** * Remove all bindings and starts buffering the needsDraw. * @function @@ -498,23 +528,20 @@ var Component = exports.Component = Montage.create(Montage,/** @lends module:mon this.needsDraw = false; this.traverseComponentTree(function(component) { Object.deleteBindings(component); - component.canDrawGate.setField("componentTreeLoaded", false); - component.blockDrawGate.setField("element", false); - component.blockDrawGate.setField("drawRequested", false); component.needsDraw = false; }); } }, - + originalContent: { value: null }, - + _newContent: { enumerable: false, value: null }, - + content: { get: function() { if (this._element) { @@ -526,21 +553,21 @@ var Component = exports.Component = Montage.create(Montage,/** @lends module:mon set: function(value) { var components = [], childNodes; - + this._newContent = value; this.needsDraw = true; - + if (typeof this.contentWillChange === "function") { this.contentWillChange(value); } - + // cleanup current content components = this.childComponents; for (var i = 0, component; (component = components[i]); i++) { component.detachFromParentComponent(); component.cleanupDeletedComponentTree(); } - + if (value instanceof Element) { findAndDetachComponents(value); } else { @@ -548,11 +575,11 @@ var Component = exports.Component = Montage.create(Montage,/** @lends module:mon findAndDetachComponents(value[i]); } } - + // find the component fringe and detach them from the component tree function findAndDetachComponents(node) { var component = node.controller; - + if (component) { component.detachFromParentComponent(); components.push(component); @@ -563,14 +590,14 @@ var Component = exports.Component = Montage.create(Montage,/** @lends module:mon } } } - + // not sure if I can rely on _cachedParentComponent to detach the nodes instead of doing one loop for dettach and another to attach... for (var i = 0, component; (component = components[i]); i++) { this._addChildComponent(component); } } }, - + /** Description TODO @function @@ -581,6 +608,9 @@ var Component = exports.Component = Montage.create(Montage,/** @lends module:mon if (this._element) { this.originalContent = Array.prototype.slice.call(this._element.childNodes, 0); } + if (!("identifier" in this)) { + this.identifier = Montage.getInfoForObject(this).label; + } } }, @@ -886,6 +916,15 @@ var Component = exports.Component = Montage.create(Montage,/** @lends module:mon // this call will be synchronous if the template is cached. Template.templateWithModuleId(info.require, templateModuleId, onTemplateLoad); }}, + + templateDidDeserializeObject: { + value: function(object) { + if (Component.isPrototypeOf(object)) { + object.ownerComponent = this; + } + } + }, + /** Callback for the _canDrawGate.
Propagates to the parent and adds the component to the draw list. @@ -990,10 +1029,10 @@ var Component = exports.Component = Montage.create(Montage,/** @lends module:mon if (attributeName === "id" || attributeName === "data-montage-id") { continue; } else { - value = (template.getAttribute(attributeName) || "") + " " + + value = (template.getAttribute(attributeName) || "") + (attributeName === "style" ? "; " : " ") + attribute.nodeValue; } - + template.setAttribute(attributeName, value); } @@ -1072,13 +1111,13 @@ var Component = exports.Component = Montage.create(Montage,/** @lends module:mon value: function() { var contents = this._newContent, element; - + this._canDrawTable = {}; this._canDrawCount = 0; - + if (contents) { element = this._element; - + element.innerHTML = ""; if (contents instanceof Element) { @@ -1088,7 +1127,7 @@ var Component = exports.Component = Montage.create(Montage,/** @lends module:mon element.appendChild(content); } } - + this._newContent = null; if (typeof this.contentDidChange === "function") { this.contentDidChange(); @@ -1196,7 +1235,7 @@ var Component = exports.Component = Montage.create(Montage,/** @lends module:mon } if (this._needsDraw !== value) { if (drawLogger.isDebug) { - drawLogger.debug("NEEDS DRAW TOGGLED " + value + " FOR " + (this.element != null ? this.element.id : '')); + drawLogger.debug("NEEDS DRAW TOGGLED " + value + " FOR " + this._montage_metadata.objectName); } this._needsDraw = !!value; if (value) { diff --git a/node_modules/montage/ui/composer/press-composer.js b/node_modules/montage/ui/composer/press-composer.js index 942de162..4a6b99b2 100644 --- a/node_modules/montage/ui/composer/press-composer.js +++ b/node_modules/montage/ui/composer/press-composer.js @@ -103,7 +103,10 @@ var PressComposer = exports.PressComposer = Montage.create(Composer,/** @lends m _startInteraction: { enumerable: false, value: function(event) { - if ("disabled" in this.component && this.component.disabled) { + if ( + ("disabled" in this.component && this.component.disabled) || + this._observedPointer !== null + ) { return false; } @@ -401,8 +404,8 @@ var PressEvent = (function(){ // These properties are available directly on the event eventProps = ["altKey", "ctrlKey", "metaKey", "shiftKey", - "cancelBubble", "clipboardData", "currentTarget", "defaultPrevented", - "eventPhase", "returnValue", "srcElement", "timeStamp", "preventDefault", + "cancelBubble", "currentTarget", "defaultPrevented", + "eventPhase", "timeStamp", "preventDefault", "stopImmediatePropagation", "stopPropagation"]; // These properties are available on the event in the case of mouse, and // on the _touch in the case of touch diff --git a/node_modules/montage/ui/composer/translate-composer.js b/node_modules/montage/ui/composer/translate-composer.js index 485290b4..4ce165dc 100644 --- a/node_modules/montage/ui/composer/translate-composer.js +++ b/node_modules/montage/ui/composer/translate-composer.js @@ -4,7 +4,7 @@ (c) Copyright 2011 Motorola Mobility, Inc. All Rights Reserved. */ /** - @module montage/ui/composer/long-press-composer + @module montage/ui/composer/long-press-composer @requires montage @requires montage/ui/composer/composer */ @@ -15,7 +15,19 @@ var Montage = require("montage").Montage, @class module:montage/ui/composer/translate-composer.TranslateComposer @extends module:montage/ui/composer/composer.Composer */ -exports.TranslateComposer = Montage.create(Composer,/** @lends module:montage/ui/event/composer/translate-composer.TranslateComposer# */ { +var TranslateComposer = exports.TranslateComposer = Montage.create(Composer,/** @lends module:montage/ui/event/composer/translate-composer.TranslateComposer# */ { + + /** + These elements perform some native action when clicked/touched and so we + should not preventDefault when a mousedown/touchstart happens on them. + @private + */ + _NATIVE_ELEMENTS: { + value: ["A", "IFRAME", "EMBED", "OBJECT", "VIDEO", "AUDIO", "CANVAS", + "LABEL", "INPUT", "BUTTON", "SELECT", "TEXTAREA", "KEYGEN", + "DETAILS", "COMMAND" + ] + }, _externalUpdate: { enumerable: false, @@ -191,6 +203,8 @@ exports.TranslateComposer = Montage.create(Composer,/** @lends module:montage/ui } }, + invertAxis: {value: null}, + _hasMomentum: { enumerable: false, value: true @@ -296,16 +310,31 @@ exports.TranslateComposer = Montage.create(Composer,/** @lends module:montage/ui value: null }, + /** + Returns if we should preventDefault on a touchstart/mousedown event. + @param {Event} The event + @returns {Boolean} Whether preventDefault should be called + @private + */ + _shouldPreventDefault: { + value: function(event) { + return !!event.target.tagName && TranslateComposer._NATIVE_ELEMENTS.indexOf(event.target.tagName) === -1 && !event.target.isContentEditable; + } + }, + +/** + Description TODO + @function + @param {Event} event TODO + */ captureMousedown: { enumerable: false, value: function (event) { + if (event.button !== 0) { + return; + } - // TODO this is a bit of a temporary workaround to ensure that we allow input fields - //to receive the mousedown that gives them focus and sets the cursor a the mousedown coordinates - if (!(event.target.tagName && - ("INPUT" === event.target.tagName || "SELECT" === event.target.tagName || "TEXTAREA" === event.target.tagName)) && - !event.target.isContentEditable) { - + if (this._shouldPreventDefault(event)) { event.preventDefault(); } @@ -317,11 +346,16 @@ exports.TranslateComposer = Montage.create(Composer,/** @lends module:montage/ui } }, + /** + Handle the mousedown that bubbled back up from beneath the element + If nobody else claimed this pointer, we should handle it now + @function + @param {Event} event TODO + */ handleMousedown: { enumerable: false, value: function (event) { - - if (!this.eventManager.componentClaimingPointer(this._observedPointer, this)) { + if (event.button === 0 && !this.eventManager.componentClaimingPointer(this._observedPointer, this)) { this.eventManager.claimPointer(this._observedPointer, this); this._start(event.clientX, event.clientY, event.target); } @@ -371,10 +405,11 @@ exports.TranslateComposer = Montage.create(Composer,/** @lends module:montage/ui captureTouchstart: { enumerable: false, value: function (event) { + if (this._shouldPreventDefault(event)) { + event.preventDefault(); + } - event.preventDefault(); - - // If already scrolling the scrollview, ignore any new touchstarts + // If already scrolling, ignore any new touchstarts if (this._observedPointer !== null && this.eventManager.isPointerClaimedByComponent(this._observedPointer, this)) { return; } @@ -391,7 +426,9 @@ exports.TranslateComposer = Montage.create(Composer,/** @lends module:montage/ui if (!this.eventManager.componentClaimingPointer(this._observedPointer)) { if (event.targetTouches.length === 1) { - event.preventDefault(); + if (this._shouldPreventDefault(event)) { + event.preventDefault(); + } this.eventManager.claimPointer(this._observedPointer, this); this._start(event.targetTouches[0].clientX, event.targetTouches[0].clientY, event.targetTouches[0].target); @@ -458,7 +495,7 @@ exports.TranslateComposer = Montage.create(Composer,/** @lends module:montage/ui angle = velocity.angle; - // The motion is with the grain of the scrollview; we may want to see if we should claim the pointer + // The motion is with the grain of the element; we may want to see if we should claim the pointer if ("horizontal" === this.axis) { isRight = (angle <= lowerRight && angle >= upperRight); @@ -516,11 +553,13 @@ exports.TranslateComposer = Montage.create(Composer,/** @lends module:montage/ui value: function (x, y) { this._isSelfUpdate=true; + var delta; if (this._axis!="vertical") { + var delta = this.invertAxis ? (x-this._pointerX) : (this._pointerX-x); if ((this._translateX<0)||(this._translateX>this._maxTranslateX)) { - this.translateX+=((this._pointerX-x)/2)*this._pointerSpeedMultiplier; + this.translateX+=(delta/2)*this._pointerSpeedMultiplier; } else { - this.translateX+=(this._pointerX-x)*this._pointerSpeedMultiplier; + this.translateX+=(delta)*this._pointerSpeedMultiplier; } } if (this._axis!="horizontal") { @@ -530,6 +569,7 @@ exports.TranslateComposer = Montage.create(Composer,/** @lends module:montage/ui this.translateY+=(this._pointerY-y)*this._pointerSpeedMultiplier; } } + this._isSelfUpdate=false; this._pointerX=x; this._pointerY=y; @@ -573,7 +613,6 @@ exports.TranslateComposer = Montage.create(Composer,/** @lends module:montage/ui var translateStartEvent = document.createEvent("CustomEvent"); translateStartEvent.initCustomEvent("translateStart", true, true, null); - translateStartEvent.type = "translateStart"; this.dispatchEvent(translateStartEvent); } }, @@ -584,11 +623,11 @@ exports.TranslateComposer = Montage.create(Composer,/** @lends module:montage/ui var translateEndEvent = document.createEvent("CustomEvent"); translateEndEvent.initCustomEvent("translateEnd", true, true, null); - translateEndEvent.type = "translateEnd"; this.dispatchEvent(translateEndEvent); } }, + _end: { enumerable: false, value: function (event) { diff --git a/node_modules/montage/ui/condition.reel/condition.js b/node_modules/montage/ui/condition.reel/condition.js index 053adb16..064f51b7 100755 --- a/node_modules/montage/ui/condition.reel/condition.js +++ b/node_modules/montage/ui/condition.reel/condition.js @@ -110,9 +110,6 @@ exports.Condition = Montage.create(Component, /** @lends module:"montage/ui/cond enumerable:false }, - /** - - */ // TODO should this strategy be part of another class? // TODO expose the options as an exported enum removalStrategy:{ @@ -131,11 +128,7 @@ exports.Condition = Montage.create(Component, /** @lends module:"montage/ui/cond } }, - /** - @param - @returns - */ didCreate:{ value:function () { this._slot = Slot.create(); @@ -150,19 +143,14 @@ exports.Condition = Montage.create(Component, /** @lends module:"montage/ui/cond prepareForDraw: { enumerable: false, value: function() { - + var i, childList, childElement; if (!this.content) { this.content = document.createElement("div"); - - var conditionContentRange = document.createRange(); - conditionContentRange.selectNodeContents(this._element); - - // TODO not wrap the range if it is a range of a single element - // we want to only deal with single elements when appending and removing; - // this keeps us from having to keep track of the range or risk losing - // a reference to the elements when they're extracted - conditionContentRange.surroundContents(this.content); - conditionContentRange.deleteContents(); //remove the contents that are part of the original structure + childList = Array.prototype.slice.call(this._element.childNodes, 0); + for (i = 0; (childElement = childList[i]); i++) { + childElement.parentElement.removeChild(childElement); + this.content.appendChild(childElement); + } } var slotRoot = document.createElement("div"); diff --git a/node_modules/montage/ui/controller/array-controller.js b/node_modules/montage/ui/controller/array-controller.js index 868ae5de..f355efc1 100755 --- a/node_modules/montage/ui/controller/array-controller.js +++ b/node_modules/montage/ui/controller/array-controller.js @@ -519,9 +519,11 @@ var ArrayController = exports.ArrayController = Montage.create(ObjectController, return null; } - this._selectedObjects = this.content.filter(function(value, i) { - return this._selectedContentIndexes.indexOf(i) >= 0; - }, this); + if(this.content) { + this._selectedObjects = this.content.filter(function(value, i) { + return this._selectedContentIndexes.indexOf(i) >= 0; + }, this); + } return this._selectedObjects; }, diff --git a/node_modules/montage/ui/list.reel/list.html b/node_modules/montage/ui/list.reel/list.html index 98629f04..2e52b11d 100755 --- a/node_modules/montage/ui/list.reel/list.html +++ b/node_modules/montage/ui/list.reel/list.html @@ -40,12 +40,12 @@ } } }, - "scrollview1": { - "module": "montage/ui/scrollview.reel", - "name": "Scrollview", + "scroller1": { + "module": "montage/ui/scroller.reel", + "name": "Scroller", "properties": { "element": { - "#": "scrollView" + "#": "scroller" } }, "bindings": { @@ -74,7 +74,7 @@
-
+
diff --git a/node_modules/montage/ui/loader.reel/loader.js b/node_modules/montage/ui/loader.reel/loader.js index b392c915..941c17da 100755 --- a/node_modules/montage/ui/loader.reel/loader.js +++ b/node_modules/montage/ui/loader.reel/loader.js @@ -298,8 +298,7 @@ exports.Loader = Montage.create(Component, /** @lends module:montage/ui/loader.L for (i = 0; (iChild = children[i]); i++) { if ((iComponent = iChild.controller)) { - this.childComponents.push(iComponent); - iComponent._cachedParentComponent = this; + iComponent.attachToParentComponent(); iComponent.needsDraw = true; } } @@ -342,8 +341,7 @@ exports.Loader = Montage.create(Component, /** @lends module:montage/ui/loader.L // based on its template this._mainComponent = exports[this.mainName].create(); this.childComponents.push(this._mainComponent); - this._mainComponent._cachedParentComponent = this; - this._mainComponent.element = document.createElement("div"); + this._mainComponent.setElementWithParentComponent(document.createElement("div"), this); this._mainComponent.needsDraw = true; } }, diff --git a/node_modules/montage/ui/loading-panel.reel/loading-panel.css b/node_modules/montage/ui/loading-panel.reel/loading-panel.css index 9a82a320..39f0db06 100755 --- a/node_modules/montage/ui/loading-panel.reel/loading-panel.css +++ b/node_modules/montage/ui/loading-panel.reel/loading-panel.css @@ -4,32 +4,40 @@ (c) Copyright 2011 Motorola Mobility, Inc. All Rights Reserved. */ -/* disabled for now */ -.montage-loading-panel > .loadingIndicator { - display: none; -} - .montage-loading-panel { position: absolute; + z-index: 999; top: 0; right: 0; bottom: 0; left: 0; - background-color: hsl(0,0%,0%); - display: -webkit-box; - -webkit-box-pack: center; - -webkit-box-align: center; } -.montage-loading-panel > .loadingCount { +.montage-loading-panel > .loadingIndicator { width: 200px; - height: 200px; + margin: 20px; + display: none; /* disabled for now, because the loading doesn't really look continuos enough. */ +} + + +.montage-loading-panel > .loadingCount { + position: absolute; + width: 160px; + height: 160px; + top: 50%; + left: 50%; + margin: -90px; + padding: 10px; border-radius: 50%; - text-align: center; color: #fff; - font: 40px/200px "Lucida Grande", Lucida, Verdana, sans-serif; - text-shadow: 0 0px 6px hsla(200,100%,50%,.6); - -webkit-box-shadow: inset 0px 0px 0 5px hsl(200,0%,10%); + font: 30px/160px "Helvetica Neue", Helvetica, Geneva, sans-serif; + text-align: center; + background: hsla(0,0%,0%,.6); + background: -webkit-radial-gradient( center 33% , hsla(0,0%,0%,.6) 10%, hsla(0,0%,0%,.8) ); + background: -moz-radial-gradient( center 33% , hsla(0,0%,0%,.65) 10%, hsla(0,0%,0%,.8) ); + -webkit-box-shadow: inset 0 0 0 3px hsla(0,0%,0%,.3), 0 0 0 3px hsla(0,0%,100%,.3); + box-shadow: inset 0 0 0 3px hsla(0,0%,0%,.3), 0 0 0 3px hsla(0,0%,100%,.3); + overflow: hidden; } .montage-loading-panel > .loadingCount > .divider { diff --git a/node_modules/montage/ui/loading-panel.reel/loading-panel.html b/node_modules/montage/ui/loading-panel.reel/loading-panel.html index 27825a09..ff1677ea 100755 --- a/node_modules/montage/ui/loading-panel.reel/loading-panel.html +++ b/node_modules/montage/ui/loading-panel.reel/loading-panel.html @@ -34,7 +34,7 @@ "boundObjectPropertyPath": "initializedModuleCount", "oneway": true }, - "maximumValue": { + "max": { "boundObject": {"@": "owner"}, "boundObjectPropertyPath": "requiredModuleCount", "oneway": true @@ -81,7 +81,9 @@
- 0/0 + 0 + / + 0
diff --git a/node_modules/montage/ui/native-control.js b/node_modules/montage/ui/native-control.js index d308ad89..907711e2 100644 --- a/node_modules/montage/ui/native-control.js +++ b/node_modules/montage/ui/native-control.js @@ -200,9 +200,6 @@ var NativeControl = exports.NativeControl = Montage.create(Component, { for(var attributeName in this._elementAttributeValues) { if(this._elementAttributeValues.hasOwnProperty(attributeName)) { - if(attributeName === 'value') { - continue; - } var value = this[attributeName]; descriptor = this._getElementAttributeDescriptor(attributeName, this); if(descriptor && descriptor.dataType === 'boolean') { diff --git a/node_modules/montage/ui/popup/confirm.reel/confirm.js b/node_modules/montage/ui/popup/confirm.reel/confirm.js index 7e186e29..0fc5fea0 100755 --- a/node_modules/montage/ui/popup/confirm.reel/confirm.js +++ b/node_modules/montage/ui/popup/confirm.reel/confirm.js @@ -115,7 +115,7 @@ var Confirm = exports.Confirm = Montage.create(Component, /** @lends module:"mon this.okCallback.call(this, evt); } var anEvent = document.createEvent("CustomEvent"); - anEvent.initCustomEvent("montage_confirm_ok", true, true); + anEvent.initCustomEvent("montage_confirm_ok", true, true, null); this.dispatchEvent(anEvent); this.popup.hide(); @@ -132,7 +132,7 @@ var Confirm = exports.Confirm = Montage.create(Component, /** @lends module:"mon this.cancelCallback.call(this, evt); } var anEvent = document.createEvent("CustomEvent"); - anEvent.initCustomEvent("montage_confirm_cancel", true, true); + anEvent.initCustomEvent("montage_confirm_cancel", true, true, null); this.dispatchEvent(anEvent); this.popup.hide(); diff --git a/node_modules/montage/ui/popup/popup.reel/popup.js b/node_modules/montage/ui/popup/popup.reel/popup.js index f13a6aed..2a61e75e 100755 --- a/node_modules/montage/ui/popup/popup.reel/popup.js +++ b/node_modules/montage/ui/popup/popup.reel/popup.js @@ -27,6 +27,10 @@ var Popup = exports.Popup = Montage.create(Component, { /** @lends module:"modul // A Delegate to control positioning (and other features, in future) of the popup in a custom manner delegate: {value: null}, + /** + Internal property. + @private + */ contentEl: { value: null }, @@ -34,66 +38,24 @@ var Popup = exports.Popup = Montage.create(Component, { /** @lends module:"modul Description TODO @type {Property} @default {Container} null + @private */ containerEl: { value: null }, -/** - Description TODO - @private -*/ - _pointer: { - value: true - }, -/** - Description TODO - @type {Function} - @default {Boolean} true - */ - pointer: { - get: function() { - return this._pointer; - }, - set: function(value) { - if (this._pointer !== value) { - this._pointer = value; - this.needsDraw = true; - } - } - }, -/** - Description TODO - @private -*/ - _boxed: { - value: true - }, -/** - Description TODO - @type {Function} - @default {Boolean} true - */ - boxed: { - get: function() { - return this._boxed; - }, - set: function(value) { - if (this._boxed !== value) { - this._boxed = value; - this.needsDraw = true; - } - } - }, + /** Description TODO @private */ _slot: {value: null}, /** + Description TODO @type {Function} @default null + @private */ slot: { get: function() { @@ -112,7 +74,8 @@ var Popup = exports.Popup = Montage.create(Component, { /** @lends module:"modul */ _content: {value: null}, /** - Description TODO + The Montage component that will be shown in this popup. + @type {Function} @default null */ @@ -137,7 +100,8 @@ var Popup = exports.Popup = Montage.create(Component, { /** @lends module:"modul */ _modal: { value: false }, /** - Description TODO + If true, the Popup will be rendered as a Modal. + @type {Function} @default {Boolean} false */ @@ -156,8 +120,10 @@ var Popup = exports.Popup = Montage.create(Component, { /** @lends module:"modul } }, - // An Object wtih values {top, left}. Set it only if the popup should display at a - // given location instead of anchoring it to a anchor element or at the center of the screen. + /** + An Object wtih values {top, left}. Set it only if the popup should display at a + given location always. + */ _position: {value: null}, position: { get: function() { @@ -169,8 +135,12 @@ var Popup = exports.Popup = Montage.create(Component, { /** @lends module:"modul } }, + /** + * Number of milliseconds after which the Popup must be dismissed. Default is 0. + */ autoDismiss: { value: 0 }, + /** @private */ _displayed: { value: false }, displayed: { get: function() { @@ -204,9 +174,10 @@ var Popup = exports.Popup = Montage.create(Component, { /** @lends module:"modul /** + Internal method. @private */ - _getPosition: { + _getElementPosition: { value: function(obj) { var curleft = 0, curtop = 0, curHt = 0, curWd = 0; if (obj.offsetParent) { @@ -222,16 +193,21 @@ var Popup = exports.Popup = Montage.create(Component, { /** @lends module:"modul } }, - _calculatePosition: { + _positionPopup: { value: function() { - var pos, delegate = this.delegate, anchor = this.anchor, type = this.type; + var position, delegate = this.delegate, anchor = this.anchor, type = this.type; - if(delegate && (typeof delegate.positionPopup === 'function')) { + // if a delegate is provided, use that to get the position + if(delegate && (typeof delegate.willPositionPopup === 'function')) { var anchorPosition; if(anchor) { - anchorPosition = this._getPosition(anchor); + anchorPosition = this._getElementPosition(anchor); } - pos = delegate.positionPopup(this, anchor, anchorPosition); + position = delegate.willPositionPopup(this, anchor, anchorPosition); + } else if(this.position !== null) { + // If a position has been specified but no delegate has been provided + // we assume that the position is static and hence use that + position = this.position; } else { // @todo - advanced positioning support var $el = this.contentEl || this.content.element; @@ -243,67 +219,55 @@ var Popup = exports.Popup = Montage.create(Component, { /** @lends module:"modul var viewportWidth = window.innerWidth; if (anchor) { + // if an anchor is provided, we position the popup relative to the anchor + // if (anchor.nodeName) { // if anchor is an element - var elPosition = this._getPosition(anchor); + var elPosition = this._getElementPosition(anchor); var tgtHeight = parseFloat(anchor.style.height || 0) || anchor.offsetHeight || 0; var tgtWidth = parseFloat(anchor.style.width || 0) || anchor.offsetWidth || 0; - pos = { + position = { top: elPosition[1] + tgtHeight + 20 /* pointer */, left: elPosition[0] + (tgtWidth / 2) - (elWidth / 2) }; - if (pos.left < 0) { - pos.left = elPosition[0]; + if (position.left < 0) { + position.left = elPosition[0]; this._showHidePointer(false); // dont show the pointer - @todo - support pointer arrow at different parts of the popup } } else { // anchor is absolute position {top, left} - pos = anchor; + position = anchor; } } else { - // position it at top or center - // for now, just show it at center - pos = { + // No positioning hints provided. POsition it at the center of the viewport by default + position = { top: (viewportHeight / 2 - (elHeight / 2)), left: (viewportWidth / 2 - (elWidth / 2)) }; } } - return pos; - } - }, - - _positionPopup: { - value: function() { - //console.log('--> position popup'); - var pos = this.position; + //this.position = position; var popupSlot = this._popupSlot; - if(pos) { - if (pos.top) { - popupSlot.element.style.top = pos.top + 'px'; - } - if (pos.left) { - popupSlot.element.style.left = pos.left + 'px'; - } - if (pos.right) { - popupSlot.element.style.right = pos.right + 'px'; - } - if (pos.bottom) { - popupSlot.element.style.bottom = pos.bottom + 'px'; - } + if(position) { + popupSlot.element.style.top = (position.top ? position.top + 'px' : ''); + popupSlot.element.style.left = (position.left ? position.left + 'px' : ''); + popupSlot.element.style.right = (position.right ? position.right + 'px' : ''); + popupSlot.element.style.bottom = (position.bottom ? position.bottom + 'px' : ''); } + } }, + _createModalMask: { value: function() { var el = document.createElement('div'); el.classList.add('montage-popup-modal-mask'); - el.style['z-index'] = 6999; + el.style.zIndex = 6999; el.classList.add('montage-invisible'); document.body.appendChild(el); @@ -340,6 +304,13 @@ var Popup = exports.Popup = Montage.create(Component, { /** @lends module:"modul } }, + /** + * Show the Popup. The Popup is displayed at a position determined by the following conditions: + * 1) If a delegate is provided and the willPositionPopup function is implemented, the position is always determined by the delegate + * 2) If Popup.position has been set, the Popup is always displayed at this location + * 3) If an anchor has been set, the popup is displayed below the anchor + * 4) If no positional hints are provided, the Popup is displayed at the center of the screen + */ show: { value: function() { var type = this.type, @@ -352,6 +323,9 @@ var Popup = exports.Popup = Montage.create(Component, { /** @lends module:"modul } }, + /** + * Hide the popup + */ hide: { value: function() { this._removeEventListeners(); @@ -397,9 +371,6 @@ var Popup = exports.Popup = Montage.create(Component, { /** @lends module:"modul draw: { value: function() { if (this.displayed) { - // custom, alert, confirm, notify - // only one popup of each type can be displayed at the same time - // kishore - does the above restriction make sense ? should we restrict it ? if(this.modal === true) { this.element.classList.add('montage-modal'); @@ -416,7 +387,7 @@ var Popup = exports.Popup = Montage.create(Component, { /** @lends module:"modul this.content.element.style.display = 'block'; this.content.element.classList.remove('montage-invisible'); // TODO do we want the panel to be focusable? - // this.content.element.setAttribute("tabindex", "0"); // Make the alert focusable + this.content.element.setAttribute("tabindex", "0"); // Make the popup content focusable if (this.autoDismiss) { var self = this; @@ -442,14 +413,14 @@ var Popup = exports.Popup = Montage.create(Component, { /** @lends module:"modul didDraw: { value: function() { if (this._displayed) { - this.content.element.focus(); if(this.modal === true) { this._showModalMask(); } - this.position = this.position || this._calculatePosition(); this._positionPopup(); + // focus the content to enable key events such as ENTER/ESC + this.content.element.focus(); } else { if(this.modal === true) { @@ -514,9 +485,7 @@ var Popup = exports.Popup = Montage.create(Component, { /** @lends module:"modul // an optimization to call positionPopup fewer times window.clearTimeout(this._timeoutId); this._timeoutId = setTimeout(function() { - //self._positionPopup(); - self.position = self._calculatePosition(); - self._positionPopup(); + self.needsDraw = true; }, 100); } } diff --git a/node_modules/montage/ui/progress.reel/progress.css b/node_modules/montage/ui/progress.reel/progress.css deleted file mode 100755 index cf9e6543..00000000 --- a/node_modules/montage/ui/progress.reel/progress.css +++ /dev/null @@ -1,51 +0,0 @@ -/* - This file contains proprietary software owned by Motorola Mobility, Inc.
- No rights, expressed or implied, whatsoever to this software are provided by Motorola Mobility, Inc. hereunder.
- (c) Copyright 2011 Motorola Mobility, Inc. All Rights Reserved. -
*/ -.montage-progress { - height: 7px; - padding: 1px; - border-radius: 5px / 4px; - overflow: hidden; - background: #ccc url(rule.png); - -webkit-box-shadow: inset rgba(0,0,0,.2) 0 0 0 1px, rgba(255,255,255,.5) 0 1px 1px, rgba(0,0,0,.1) 0 -1px 0px; -} - -.montage-progress .bar { - height: 7px; - border-radius: inherit; - - background-repeat: no-repeat; - background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, - color-stop(12%, #35c9ff), color-stop(12%, #0cbeff), - color-stop(85%, #0aa5dd), color-stop(85%, #0996c9) ); - - -webkit-transition: width .3s cubic-bezier(0.25, 0.1, 0.3, 0.9); -} - -.montage-progress.dark { - background: url(rule.png), -webkit-gradient(linear, 0% 0%, 0% 100%, - color-stop(0%, #303030), color-stop(100%, #3f3f3f) ); - - -webkit-box-shadow: rgba(255,255,255,.1) 0 1px 0, rgba(0,0,0,.1) 0 -1px 0px; -} - -@-webkit-keyframes montage-progress-scroll { - from { - background-position: 0px top; - } - to { - background-position: -8px top; - } -} - -.montage-progress .bar.scrolling { - background-image: url("scroll.png"); - background-repeat: repeat-x; - background-position: 10px top; - -webkit-animation-name: montage-progress-scroll; - -webkit-animation-duration: 1s; - -webkit-animation-timing-function: linear; - -webkit-animation-iteration-count: infinite; -} diff --git a/node_modules/montage/ui/progress.reel/progress.html b/node_modules/montage/ui/progress.reel/progress.html deleted file mode 100755 index 025847e7..00000000 --- a/node_modules/montage/ui/progress.reel/progress.html +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - -
-
-
- - - diff --git a/node_modules/montage/ui/progress.reel/progress.js b/node_modules/montage/ui/progress.reel/progress.js index 8bc68b05..973ec5b7 100755 --- a/node_modules/montage/ui/progress.reel/progress.js +++ b/node_modules/montage/ui/progress.reel/progress.js @@ -3,137 +3,17 @@ No rights, expressed or implied, whatsoever to this software are provided by Motorola Mobility, Inc. hereunder.
(c) Copyright 2011 Motorola Mobility, Inc. All Rights Reserved. */ -/** - @module "montage/ui/bluemoon/progress.reel" - @requires montage/core/core - @requires montage/ui/component -*/ var Montage = require("montage").Montage, - Component = require("ui/component").Component; -/** - @class module:montage/ui/progress.Progress - @extends module:montage/ui/component.Component -*/ -exports.Progress = Montage.create(Component,/** @lends module:"montage/ui/bluemoon/progress.reel".Progress# */ { -/** - Description TODO - @private -*/ - _barElement: { - enumerable: false, - value: null - }, -/** - Description TODO - @private -*/ - _value: { - enumerable: false, - value: 0 - }, -/** - Description TODO - @type {Function} - @default {Number} 0 - */ - value: { - get: function() { - return this._value; - }, - set: function(val) { - if(val !== this._value) { - this._value = val; - if(this._value > this._maximumValue) { - this._value = this._maximumValue; - } - if(this._value < 0) { - this._value = 0; - } - this.needsDraw = true; - } - } - }, -/** - Description TODO - @private -*/ - _maximumValue: { - enumerable: false, - value: 100 - }, -/** - Description TODO - @type {Function} - @default {Number} 100 - */ - maximumValue: { - get: function() { - return this._maximumValue; - }, - set: function(val) { - if(val !== this._maximumValue) { - this._maximumValue = val; - if(this._maximumValue <= 0) { - this._maximumValue = 1; // Prevent divide by zero errors - } - this.needsDraw = true; - } - } - }, -/** - Description TODO - @private -*/ - _scrollingChanged: { - enumerable: false, - value: true - }, -/** - Description TODO - @private -*/ - _scrolling: { - enumerable: false, - value: false - }, -/** - Description TODO - @type {Function} - @default {Boolean} false - */ - scrolling: { - get: function() { - return this._scrolling; - }, - set: function(value) { - if(this._scrolling !== value) { - this._scrollingChanged = true; - this._scrolling = value; - this.needsDraw = true; - } - } - }, -/** - Description TODO - @function - */ - draw: { - enumerable: false, - value: function() { - var ratio = this._value / this._maximumValue; - // constrain to interval [0, 1] - ratio = Math.min(Math.max(ratio, 0), 1); - // map into [0, 100] - var percentage = ratio * 100; - this._barElement.style.width = percentage + '%'; - if(this._scrollingChanged) { - if(this._scrolling) { - this._barElement.classList.add("scrolling"); - } else { - this._barElement.classList.remove("scrolling"); - } - this._scrollingChanged = false; - } - } - } + Component = require("ui/component").Component, + NativeControl = require("ui/native-control").NativeControl; + + +var Progress = exports.Progress = Montage.create(NativeControl, { + }); + +Progress.addAttributes({ + form: null, + max: {dataType: 'number'}, + value: {dataType: 'number'} +}); \ No newline at end of file diff --git a/node_modules/montage/ui/progress.reel/rule.png b/node_modules/montage/ui/progress.reel/rule.png deleted file mode 100755 index 511b20df..00000000 Binary files a/node_modules/montage/ui/progress.reel/rule.png and /dev/null differ diff --git a/node_modules/montage/ui/progress.reel/scroll.png b/node_modules/montage/ui/progress.reel/scroll.png deleted file mode 100755 index b5ef6eef..00000000 Binary files a/node_modules/montage/ui/progress.reel/scroll.png and /dev/null differ diff --git a/node_modules/montage/ui/radio-button.reel/radio-button.js b/node_modules/montage/ui/radio-button.reel/radio-button.js index 9fe43336..b6f87205 100755 --- a/node_modules/montage/ui/radio-button.reel/radio-button.js +++ b/node_modules/montage/ui/radio-button.reel/radio-button.js @@ -65,7 +65,6 @@ var RadioButton = exports.RadioButton = Montage.create(CheckInput, { anEvent.initCustomEvent("checked", true, true, { name: this.name }); - anEvent.type = "checked"; RadioButton.dispatchEvent(anEvent); RadioButton.addEventListener('checked', this); } @@ -97,7 +96,7 @@ var RadioButton = exports.RadioButton = Montage.create(CheckInput, { } }); RadioButton.addAttributes({ - autofocus: 'off', // on/off + autofocus: {value: false, dataType: 'boolean'}, disabled: {value: false, dataType: 'boolean'}, checked: {value: false, dataType: 'boolean'}, form: null, diff --git a/node_modules/montage/ui/repetition.reel/repetition.js b/node_modules/montage/ui/repetition.reel/repetition.js index 3405a3d7..acc03747 100755 --- a/node_modules/montage/ui/repetition.reel/repetition.js +++ b/node_modules/montage/ui/repetition.reel/repetition.js @@ -15,7 +15,8 @@ var Montage = require("montage").Montage, Component = require("ui/component").Component, Template = require("ui/template").Template, logger = require("core/logger").logger("repetition"), - Gate = require("core/gate").Gate; + Gate = require("core/gate").Gate, + ChangeTypeModification = require("core/event/mutable-event").ChangeTypes.MODIFICATION; /** @class module:"montage/ui/repetition.reel".Repetition @extends module:montage/ui/component.Component @@ -26,6 +27,26 @@ var Repetition = exports.Repetition = Montage.create(Component, /** @lends modul */ hasTemplate: {value: false}, + didCreate: { + value: function() { + this.addEventListener("change@objects", this._onObjectsChange, false); + } + }, + + _onObjectsChange: { + enumerable: false, + value: function(event) { + if(event._event.propertyChange !== ChangeTypeModification) { + this.selectedIndexes = null; + this._mappedObjects = null; + + if (this._isComponentExpanded) { + this._refreshItems(); + } + } + } + }, + /** @private */ @@ -149,20 +170,38 @@ var Repetition = exports.Repetition = Montage.create(Component, /** @lends modul serializable: true, value: null }, + + _mappedObjects: { + enumerable: false, + serializable: true, + value: null + }, /** Description TODO @type {Function} @default null */ objects: { + dependencies: ["indexMap"], enumerable: false, get: function() { - return this._objects; + if (!this.indexMap) { + return this._objects; + } else { + if (this._objects && !this._mappedObjects) { + this._mappedObjects = this.indexMap.map(function(value) { + return this._objects.getProperty(value); + }, this); + } + return this._mappedObjects; + } }, set: function(value) { if (logger.isDebug) { logger.debug(this, " set objects:", (value ? value.length : null), value, "same objects?", value === this._objects); } + + this._mappedObjects = null; this._objects = value; // Objects have changed, clear the selectedIndexes, if we're managing our own selection @@ -174,13 +213,6 @@ var Repetition = exports.Repetition = Montage.create(Component, /** @lends modul this._refreshItems(); } - }, - modify: function(modificationType, newValue, oldValue) { - this.selectedIndexes = null; - - if (this._isComponentExpanded) { - this._refreshItems(); - } } }, /** @@ -238,7 +270,31 @@ var Repetition = exports.Repetition = Montage.create(Component, /** @lends modul serializable: true, value: null }, - /* Format: {firstNode, lastNode}*/ + + _indexMap: { + enumerable: false, + value: null + }, + + indexMap: { + get: function() { + return this._indexMap; + }, + set: function(value) { + if (value === this._indexMap) { + return; + } + + this._mappedObjects = null; + this._indexMap = value; + + if (this._isComponentExpanded) { + this._refreshItems(); + } + + //TODO react to modifications to the indexMap? + } + }, /** Description TODO @@ -297,9 +353,16 @@ var Repetition = exports.Repetition = Montage.create(Component, /** @lends modul var objectCount = this._objects ? this._objects.length : 0, itemCount = this._items.length + this._itemsToAppend.length, - neededItemCount = objectCount - itemCount, + neededItemCount, i; + + if (this._objects && this.indexMap) { + objectCount = this.indexMap.length; + } + + neededItemCount = objectCount - itemCount; + // TODO: this needs to be here because the repetition might be ready to draw during a call to _addItem (if all modules are already loaded). // The problem is that when the gate is open, and the repetition hasn't ask to be drawn, the _canDraw = true will never happen and it will not happen when needsDraw = true afterwards. This kind of sucks because it means the needsDraw=true and the opening of the Gate needs to be in the correct order. // needsDraw should do _canDraw = true if the gate was opened, but we need to be careful since _canDraw=true only works if there was a previous _canDraw=false. @@ -356,6 +419,7 @@ var Repetition = exports.Repetition = Montage.create(Component, /** @lends modul // for clarity sake this._itemsToAppend.push(this._currentItem); index = items.length + this._itemsToAppend.length - 1; + self._canDraw = false; componentsCount = this._iterationChildComponentsCount; this._iterationTemplate.instantiateWithComponent(this, function() { @@ -433,6 +497,11 @@ var Repetition = exports.Repeti