diff --git a/.gitignore b/.gitignore index f9b5e3c120..b89c0e745f 100644 --- a/.gitignore +++ b/.gitignore @@ -13,7 +13,7 @@ log.txt ## Build /dist -montage.dist.js +montage.min.js ## jsdoc /doc diff --git a/README.md b/README.md index 1b280f94f6..45e3011353 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ # MontageJS +[![npm version](https://img.shields.io/npm/v/montage.svg?style=flat)](https://www.npmjs.com/package/montage) + [![Build Status](https://travis-ci.org/montagejs/montage.svg?branch=master)](http://travis-ci.org/montagejs/montage) [![Analytics](https://ga-beacon.appspot.com/UA-35717912-2/montagejs/montage)](https://github.com/montagejs/montage) diff --git a/composer/composer.js b/composer/composer.js index a0b7e55f3c..e962d2b703 100644 --- a/composer/composer.js +++ b/composer/composer.js @@ -2,7 +2,8 @@ * @module montage/composer/composer * @requires montage/core/target */ -var Target = require("../core/target").Target; +var Target = require("../core/target").Target, + defaultEventManager = require("../core/event/event-manager").defaultEventManager; /** * The `Composer` helps to keep event normalization and calculation out of @@ -69,6 +70,19 @@ exports.Composer = Target.specialize( /** @lends Composer# */ { } }, + _shawdowRoot: { + value: null + }, + + shawdowRoot: { + get: function () { + if (!this._shawdowRoot) { + this._shawdowRoot = defaultEventManager.shawdowRootFromNode(this.element); + } + return this._shawdowRoot; + } + }, + /** * This property controls when the component will call this composer's diff --git a/composer/press-composer.js b/composer/press-composer.js index 9d53ef5c98..5500c2a99b 100644 --- a/composer/press-composer.js +++ b/composer/press-composer.js @@ -693,17 +693,35 @@ var PressComposer = exports.PressComposer = Composer.specialize(/** @lends Press _addEventListeners: { value: function () { if (window.PointerEvent) { + if (this.shawdowRoot) { + this.shawdowRoot.addEventListener("pointerup", this, false); + this.shawdowRoot.addEventListener("pointermove", this, false); + this.shawdowRoot.addEventListener("pointercancel", this, false); + } + document.addEventListener("pointerup", this, false); document.addEventListener("pointermove", this, false); document.addEventListener("pointercancel", this, false); } else if (window.MSPointerEvent && window.navigator.msPointerEnabled) { + if (this.shawdowRoot) { + this.shawdowRoot.addEventListener("MSPointerUp", this, false); + this.shawdowRoot.addEventListener("MSPointerMove", this, false); + this.shawdowRoot.addEventListener("MSPointerCancel", this, false); + } + document.addEventListener("MSPointerUp", this, false); document.addEventListener("MSPointerMove", this, false); document.addEventListener("MSPointerCancel", this, false); } else { if (this._observedPointer === "mouse") { + if (this.shawdowRoot) { + this.shawdowRoot.addEventListener("mouseup", this, false); + this.shawdowRoot.addEventListener("mousemove", this, false); + this.shawdowRoot.addEventListener("dragstart", this, false); + } + document.addEventListener("mouseup", this, false); document.addEventListener("mousemove", this, false); @@ -713,6 +731,12 @@ var PressComposer = exports.PressComposer = Composer.specialize(/** @lends Press this._element.addEventListener("dragstart", this, false); } else { + if (this.shawdowRoot) { + this.shawdowRoot.addEventListener("touchend", this, false); + this.shawdowRoot.addEventListener("touchcancel", this, false); + this.shawdowRoot.addEventListener("touchmove", this, false); + } + document.addEventListener("touchend", this, false); document.addEventListener("touchcancel", this, false); document.addEventListener("touchmove", this, false); @@ -721,6 +745,11 @@ var PressComposer = exports.PressComposer = Composer.specialize(/** @lends Press var wheelEventName = typeof window.onwheel !== "undefined" || typeof window.WheelEvent !== "undefined" ? "wheel" : "mousewheel"; + + if (this.shawdowRoot) { + this.shawdowRoot.addEventListener(wheelEventName, this, true); + this.shawdowRoot.addEventListener("scroll", this, true); + } document.addEventListener(wheelEventName, this, true); document.addEventListener("scroll", this, true); @@ -730,17 +759,35 @@ var PressComposer = exports.PressComposer = Composer.specialize(/** @lends Press _removeEventListeners: { value: function () { if (window.PointerEvent) { + if (this.shawdowRoot) { + this.shawdowRoot.removeEventListener("pointerup", this, false); + this.shawdowRoot.removeEventListener("pointermove", this, false); + this.shawdowRoot.removeEventListener("pointercancel", this, false); + } + document.removeEventListener("pointerup", this, false); document.removeEventListener("pointermove", this, false); document.removeEventListener("pointercancel", this, false); } else if (window.MSPointerEvent && window.navigator.msPointerEnabled) { + if (this.shawdowRoot) { + this.shawdowRoot.removeEventListener("MSPointerUp", this, false); + this.shawdowRoot.removeEventListener("MSPointerMove", this, false); + this.shawdowRoot.removeEventListener("MSPointerCancel", this, false); + } + document.removeEventListener("MSPointerUp", this, false); document.removeEventListener("MSPointerMove", this, false); document.removeEventListener("MSPointerCancel", this, false); } else { if (this._observedPointer === "mouse") { + if (this.shawdowRoot) { + this.shawdowRoot.removeEventListener("mouseup", this, false); + this.shawdowRoot.removeEventListener("mousemove", this, false); + this.shawdowRoot.removeEventListener("dragstart", this, false); + } + document.removeEventListener("mouseup", this, false); document.removeEventListener("mousemove", this, false); @@ -748,8 +795,15 @@ var PressComposer = exports.PressComposer = Composer.specialize(/** @lends Press // no mouse events are fired // http://www.whatwg.org/specs/web-apps/current-work/multipage/dnd.html#initiate-the-drag-and-drop-operation this._element.removeEventListener("dragstart", this, false); + } else { + if (this.shawdowRoot) { + this.shawdowRoot.removeEventListener("touchend", this, false); + this.shawdowRoot.removeEventListener("touchcancel", this, false); + this.shawdowRoot.removeEventListener("touchmove", this, false); + } + document.removeEventListener("touchend", this, false); document.removeEventListener("touchcancel", this, false); document.removeEventListener("touchmove", this, false); @@ -758,6 +812,11 @@ var PressComposer = exports.PressComposer = Composer.specialize(/** @lends Press var wheelEventName = typeof window.onwheel !== "undefined" || typeof window.WheelEvent !== "undefined" ? "wheel" : "mousewheel"; + + if (this.shawdowRoot) { + this.shawdowRoot.removeEventListener(wheelEventName, this, true); + this.shawdowRoot.removeEventListener("scroll", this, true); + } document.removeEventListener(wheelEventName, this, true); document.removeEventListener("scroll", this, true); diff --git a/composer/rotation-composer.js b/composer/rotation-composer.js new file mode 100644 index 0000000000..f9d3ab8a56 --- /dev/null +++ b/composer/rotation-composer.js @@ -0,0 +1,214 @@ +/** + * @module ./rotation-composer.reel + * @requires montage/composer/composer + */ +var Composer = require("./composer").Composer, + TranslateComposer = require("./translate-composer").TranslateComposer; + +/** + * @class RotationComposer + * @extends Composer + */ +exports.RotationComposer = Composer.specialize(/** @lends RotationComposer# */ { + + /** + Dispatched when a rotation is started + + @event rotationStart + @memberof RotationComposer + @param {RotationEvent} event + */ + + /** + Dispatched when a rotation changes + + @event rotation + @memberof RotationComposer + @param {RotationEvent} event + */ + + + /** + Unit for dispatched angles. Options: radians and degrees + Radians are the default as it is the standard in angular measures + To think about: should it accept "deg" as degrees to be equivalent to CSS notation? + */ + _unit: { + value: "radians" + }, + + unit: { + get: function () { + return this._unit; + }, + set: function (value) { + if (value === "degrees") { + this._unit = "degrees"; + } else { + this._unit = "radians"; + } + } + }, + + constructor: { + value: function RotationComposer() { + this.super(); + this._translateComposer = new TranslateComposer(); + this._translateComposer.hasMomentum = false; + this._translateComposer.hasBouncing = false; + } + }, + + // Load/unload + + load: { + value: function() { + this.component.addComposerForElement(this._translateComposer, this.element); + this._translateComposer.load(); + this._translateComposer.addEventListener("translateStart", this, false); + this._translateComposer.addEventListener("translateEnd", this, false); + this._translateComposer.addEventListener("translate", this, false); + } + }, + + unload: { + value: function() { + } + }, + + handleTranslateStart: { + value: function() { + var start = this._translateComposer.pointerStartEventPosition, + deltaX = start.pageX - this.center.pageX, + deltaY = start.pageY - this.center.pageY; + + this._translateComposer.translateX = start.pageX; + this._translateComposer.translateY = start.pageY; + this._previousAngle = Math.atan2(deltaY, deltaX); + this._deltaAngle = 0; + this._dispatchRotateStart(); + } + }, + + handleTranslateEnd: { + value: function() { + this._dispatchRotateEnd(); + } + }, + + handleTranslate: { + value: function(event) { + var deltaX = event.translateX - this.center.pageX, + deltaY = event.translateY - this.center.pageY, + currentAngle = Math.atan2(deltaY, deltaX), + deltaAngle = currentAngle - this._previousAngle; + + if (deltaAngle > Math.PI) { + deltaAngle -= Math.PI * 2; + } else { + if (deltaAngle < -Math.PI) { + deltaAngle += Math.PI * 2; + } + } + this.angleInRadians += deltaAngle; + this._deltaAngle = deltaAngle; + this._previousAngle = currentAngle; + this._dispatchRotate(); + } + }, + + angleInRadians: { + value: 0 + }, + + _deltaAngle: { + value: 0 + }, + + _dispatchRotateStart: { + value: function() { + var event = document.createEvent("CustomEvent"); + + event.initCustomEvent("rotateStart", true, true, null); + event.unit = this._unit; + if (this._unit === "radians") { + event.rotation = this.angleInRadians; + event.deltaRotation = this._deltaAngle; + } else { + event.rotation = (this.angleInRadians * 180) / Math.PI; + event.deltaRotation = (this._deltaAngle * 180) / Math.PI; + } + this.dispatchEvent(event); + } + }, + + _dispatchRotate: { + value: function() { + var event = document.createEvent("CustomEvent"); + + event.initCustomEvent("rotate", true, true, null); + event.unit = this._unit; + if (this._unit === "radians") { + event.rotation = this.angleInRadians; + event.deltaRotation = this._deltaAngle; + } else { + event.rotation = (this.angleInRadians * 180) / Math.PI; + event.deltaRotation = (this._deltaAngle * 180) / Math.PI; + } + this.dispatchEvent(event); + } + }, + + _dispatchRotateEnd: { + value: function() { + var event = document.createEvent("CustomEvent"); + + event.initCustomEvent("rotateEnd", true, true, null); + event.unit = this._unit; + event.deltaRotation = 0; + if (this._unit === "radians") { + event.rotation = this.angleInRadians; + } else { + event.rotation = (this.angleInRadians * 180) / Math.PI; + } + this.dispatchEvent(event); + } + }, + + // To review: I would call this axisCoordinates or similar + center: { + value: null + }, + + _start: { + value: null + }, + + _translateComposer: { + value: null + }, + + animateMomentum: { + get: function () { + return this._translateComposer.animateMomentum; + }, + set: function (value) { + this._translateComposer.animateMomentum = !!value; + } + }, + + /** + * Whether to keep translating after the user has releases the cursor. + * @type {boolean} + * @default true + */ + hasMomentum: { + get: function () { + return this._translateComposer.hasMomentum; + }, + set: function (value) { + this._translateComposer.hasMomentum = !!value; + } + } + +}); diff --git a/core/converter/bytes-converter.meta b/core/converter/bytes-converter.mjson similarity index 58% rename from core/converter/bytes-converter.meta rename to core/converter/bytes-converter.mjson index e6ba2ecbbe..a7d344f285 100644 --- a/core/converter/bytes-converter.meta +++ b/core/converter/bytes-converter.mjson @@ -1,34 +1,25 @@ { "bytesConverter_decimals": { - "prototype": "core/meta/property-blueprint", + "prototype": "core/meta/property-descriptor", "values": { "name": "decimals", - "blueprint": { + "objectDescriptor": { "@": "root" }, "valueType": "number", "helpKey": "" } }, - "converter_blueprint_reference": { - "prototype": "core/meta/blueprint-reference", - "values": { - "valueReference": { - "blueprintName": "Converter", - "prototypeName": "Converter", - "blueprintModule": { - "%": "core/converter/converter.meta" - } - } - } + "converter_descriptor": { + "object": "core/converter/converter.mjson" }, "root": { - "prototype": "core/meta/module-blueprint", + "prototype": "core/meta/module-object-descriptor", "values": { "name": "BytesConverter", "customPrototype": false, "parent": { - "@": "converter_blueprint_reference" + "@": "converter_descriptor" }, "propertyDescriptors": [ { @@ -43,8 +34,8 @@ ] }, "propertyValidationRules": {}, - "blueprintModule": { - "%": "core/converter/bytes-converter.meta" + "objectDescriptorModule": { + "%": "core/converter/bytes-converter.mjson" }, "exportName": "BytesConverter", "module": { diff --git a/core/converter/camel-case-converter.js b/core/converter/camel-case-converter.js new file mode 100644 index 0000000000..8cfde06bd0 --- /dev/null +++ b/core/converter/camel-case-converter.js @@ -0,0 +1,45 @@ +/** + * @module montage/core/converter/camel-case-converter + * @requires montage/core/converter/converter + */ +var Converter = require("./converter").Converter, + camelCase = require('lodash.camelcase'), + singleton; + +/** + * Converts string to camel case. + * + * @class CamelCaseConverter + * @extends Converter + */ +var CamelCaseConverter = exports.CamelCaseConverter = Converter.specialize({ + + constructor: { + value: function () { + if (this.constructor === CamelCaseConverter) { + if (!singleton) { + singleton = this; + } + + return singleton; + } + + return this; + } + }, + + convert: { + value: camelCase + } + +}); + +Object.defineProperty(exports, 'singleton', { + get: function () { + if (!singleton) { + singleton = new CamelCaseConverter(); + } + + return singleton; + } +}); diff --git a/core/converter/camel-case-converter.mjson b/core/converter/camel-case-converter.mjson new file mode 100644 index 0000000000..ecd4e690b8 --- /dev/null +++ b/core/converter/camel-case-converter.mjson @@ -0,0 +1,25 @@ +{ + "converter_descriptor": { + "object": "core/converter/converter.mjson" + }, + "root": { + "prototype": "core/meta/module-object-descriptor", + "values": { + "name": "CamelCaseConverter", + "customPrototype": false, + "parent": { + "@": "converter_descriptor" + }, + "propertyDescriptors": [], + "propertyDescriptorGroups": {}, + "propertyValidationRules": {}, + "objectDescriptorModule": { + "%": "core/converter/camel-case-converter.mjson" + }, + "exportName": "CamelCaseConverter", + "module": { + "%": "core/converter/camel-case-converter" + } + } + } +} diff --git a/core/converter/converter.js b/core/converter/converter.js index e1e139f032..245a943fae 100644 --- a/core/converter/converter.js +++ b/core/converter/converter.js @@ -5,7 +5,10 @@ * @module montage/core/converter/converter * @requires montage/core/core */ -var Montage = require("../core").Montage; +var MontageModule = require("../core"), + Montage = MontageModule.Montage, + objectDescriptorModuleIdDescriptor = MontageModule._objectDescriptorModuleIdDescriptor, + objectDescriptorDescriptor = MontageModule._objectDescriptorDescriptor; /** * @const {string} @@ -105,9 +108,9 @@ var Converter = exports.Converter = Montage.specialize( /** @lends Converter# */ }, { - blueprintModuleId: require("../core")._blueprintModuleIdDescriptor, + objectDescriptorModuleId: objectDescriptorModuleIdDescriptor, - blueprint: require("../core")._blueprintDescriptor + objectDescriptor: objectDescriptorDescriptor }); diff --git a/core/converter/converter.meta b/core/converter/converter.mjson similarity index 79% rename from core/converter/converter.meta rename to core/converter/converter.mjson index b4e3c34f60..b094991011 100644 --- a/core/converter/converter.meta +++ b/core/converter/converter.mjson @@ -1,9 +1,9 @@ { "converter_allowPartialConversion": { - "prototype": "core/meta/property-blueprint", + "prototype": "core/meta/property-descriptor", "values": { "name": "allowPartialConversion", - "blueprint": { + "objectDescriptor": { "@": "root" }, "readOnly": true, @@ -12,7 +12,7 @@ } }, "root": { - "prototype": "core/meta/module-blueprint", + "prototype": "core/meta/module-object-descriptor", "values": { "name": "Converter", "customPrototype": false, @@ -29,8 +29,8 @@ ] }, "propertyValidationRules": {}, - "blueprintModule": { - "%": "core/converter/converter.meta" + "objectDescriptorModule": { + "%": "core/converter/converter.mjson" }, "exportName": "Converter", "module": { diff --git a/core/converter/currency-converter.meta b/core/converter/currency-converter.mjson similarity index 64% rename from core/converter/currency-converter.meta rename to core/converter/currency-converter.mjson index 08618cfa1d..6973e3ace5 100644 --- a/core/converter/currency-converter.meta +++ b/core/converter/currency-converter.mjson @@ -1,32 +1,23 @@ { "currenyConverter_currency": { - "prototype": "core/meta/property-blueprint", + "prototype": "core/meta/property-descriptor", "values": { "name": "currency", - "blueprint": { + "objectDescriptor": { "@": "root" }, "valueType": "string", "helpKey": "" } }, - "number_converter_blueprint_reference": { - "prototype": "core/meta/blueprint-reference", - "values": { - "valueReference": { - "blueprintName": "NumberConverter", - "prototypeName": "NumberConverter", - "blueprintModule": { - "%": "core/converter/number-converter.meta" - } - } - } + "number_converter_descriptor": { + "object": "core/converter/number-converter.mjson" }, "currencyConverter_showCurrencyBeforeNumber": { - "prototype": "core/meta/property-blueprint", + "prototype": "core/meta/property-descriptor", "values": { "name": "showCurrencyBeforeNumber", - "blueprint": { + "objectDescriptor": { "@": "root" }, "valueType": "boolean", @@ -34,12 +25,12 @@ } }, "root": { - "prototype": "core/meta/module-blueprint", + "prototype": "core/meta/module-object-descriptor", "values": { "name": "CurrencyConverter", "customPrototype": false, "parent": { - "@": "number_converter_blueprint_reference" + "@": "number_converter_descriptor" }, "propertyDescriptors": [ { @@ -60,8 +51,8 @@ ] }, "propertyValidationRules": {}, - "blueprintModule": { - "%": "core/converter/currency-converter.meta" + "objectDescriptorModule": { + "%": "core/converter/currency-converter.mjson" }, "exportName": "CurrencyConverter", "module": { diff --git a/core/converter/date-converter.meta b/core/converter/date-converter.mjson similarity index 64% rename from core/converter/date-converter.meta rename to core/converter/date-converter.mjson index 02559c8aac..e80dd259f8 100644 --- a/core/converter/date-converter.meta +++ b/core/converter/date-converter.mjson @@ -1,9 +1,9 @@ { "dateConverter_validator": { - "prototype": "core/meta/property-blueprint", + "prototype": "core/meta/property-descriptor", "values": { "name": "validator", - "blueprint": { + "objectDescriptor": { "@": "root" }, "valueType": "object", @@ -11,35 +11,26 @@ } }, "dateConverter_pattern": { - "prototype": "core/meta/property-blueprint", + "prototype": "core/meta/property-descriptor", "values": { "name": "pattern", - "blueprint": { + "objectDescriptor": { "@": "root" }, "valueType": "string", "helpKey": "" } }, - "converter_blueprint_reference": { - "prototype": "core/meta/blueprint-reference", - "values": { - "valueReference": { - "blueprintName": "Converter", - "prototypeName": "Converter", - "blueprintModule": { - "%": "core/converter/converter.meta" - } - } - } + "converter_descriptor": { + "object": "core/converter/converter.mjson" }, "root": { - "prototype": "core/meta/module-blueprint", + "prototype": "core/meta/module-object-descriptor", "values": { "name": "DateConverter", "customPrototype": false, "parent": { - "@": "converter_blueprint_reference" + "@": "converter_descriptor" }, "propertyDescriptors": [ { @@ -60,8 +51,8 @@ ] }, "propertyValidationRules": {}, - "blueprintModule": { - "%": "core/converter/date-converter.meta" + "objectDescriptorModule": { + "%": "core/converter/date-converter.mjson" }, "exportName": "DateConverter", "module": { diff --git a/core/converter/expression-converter.meta b/core/converter/expression-converter.mjson similarity index 72% rename from core/converter/expression-converter.meta rename to core/converter/expression-converter.mjson index a18233e33a..ae8943cb7d 100644 --- a/core/converter/expression-converter.meta +++ b/core/converter/expression-converter.mjson @@ -1,15 +1,6 @@ { - "converter_object-descriptor_reference": { - "prototype": "core/meta/object-descriptor-reference", - "values": { - "valueReference": { - "blueprintName": "Converter", - "prototypeName": "Converter", - "blueprintModule": { - "%": "core/converter/converter.meta" - } - } - } + "converter_descriptor": { + "object": "core/converter/converter.mjson" }, "convertExpression": { "prototype": "core/meta/property-descriptor", @@ -39,7 +30,7 @@ "name": "ExpressionConverter", "customPrototype": false, "parent": { - "@": "converter_object-descriptor_reference" + "@": "converter_descriptor" }, "propertyDescriptors": [ { @@ -52,7 +43,7 @@ "propertyDescriptorGroups": {}, "propertyValidationRules": {}, "objectDescriptorModule": { - "%": "core/converter/expression-converter.meta" + "%": "core/converter/expression-converter.mjson" }, "exportName": "ExpressionConverter", "module": { diff --git a/core/converter/invert-converter.js b/core/converter/invert-converter.js index ee4a588763..1aa811cbae 100644 --- a/core/converter/invert-converter.js +++ b/core/converter/invert-converter.js @@ -2,7 +2,10 @@ * @module montage/core/converter/invert-converter * @requires montage/core/converter/converter */ -var Converter = require("./converter").Converter; +var Converter = require("./converter").Converter, + deprecate = require("../deprecate"), + shouldMuteWarning = false, + singleton; /** * Inverts the value of a boolean value. @@ -10,7 +13,29 @@ var Converter = require("./converter").Converter; * @class InvertConverter * @extends Converter */ -var InvertConverter = exports.InvertConverter = Converter.specialize( { +var InvertConverter = exports.InvertConverter = Converter.specialize({ + + constructor: { + value: function () { + if (this.constructor === InvertConverter) { + if (!singleton) { + singleton = this; + } + + if (!shouldMuteWarning) { + deprecate.deprecationWarning( + "Instantiating InvertConverter is deprecated," + + " use its singleton instead" + ); + } + + return singleton; + } + + return this; + } + }, + convert: { value: function (v) { return !v; @@ -23,3 +48,15 @@ var InvertConverter = exports.InvertConverter = Converter.specialize( { } } }); + +Object.defineProperty(exports, 'singleton', { + get: function () { + if (!singleton) { + shouldMuteWarning = true; + singleton = new InvertConverter(); + shouldMuteWarning = false; + } + + return singleton; + } +}); diff --git a/core/converter/invert-converter.meta b/core/converter/invert-converter.meta deleted file mode 100644 index 70f3401b26..0000000000 --- a/core/converter/invert-converter.meta +++ /dev/null @@ -1,34 +0,0 @@ -{ - "converter_blueprint_reference": { - "prototype": "core/meta/blueprint-reference", - "values": { - "valueReference": { - "blueprintName": "Converter", - "prototypeName": "Converter", - "blueprintModule": { - "%": "core/converter/converter.meta" - } - } - } - }, - "root": { - "prototype": "core/meta/module-blueprint", - "values": { - "name": "InvertConverter", - "customPrototype": false, - "parent": { - "@": "converter_blueprint_reference" - }, - "propertyDescriptors": [], - "propertyDescriptorGroups": {}, - "propertyValidationRules": {}, - "blueprintModule": { - "%": "core/converter/inverter-converter.meta" - }, - "exportName": "InvertConverter", - "module": { - "%": "core/converter/invert-converter" - } - } - } -} diff --git a/core/converter/invert-converter.mjson b/core/converter/invert-converter.mjson new file mode 100644 index 0000000000..a62f59c59f --- /dev/null +++ b/core/converter/invert-converter.mjson @@ -0,0 +1,25 @@ +{ + "converter_descriptor": { + "object": "core/converter/converter.mjson" + }, + "root": { + "prototype": "core/meta/module-object-descriptor", + "values": { + "name": "InvertConverter", + "customPrototype": false, + "parent": { + "@": "converter_descriptor" + }, + "propertyDescriptors": [], + "propertyDescriptorGroups": {}, + "propertyValidationRules": {}, + "objectDescriptorModule": { + "%": "core/converter/inverter-converter.mjson" + }, + "exportName": "InvertConverter", + "module": { + "%": "core/converter/invert-converter" + } + } + } +} diff --git a/core/converter/kebab-case-converter.js b/core/converter/kebab-case-converter.js new file mode 100644 index 0000000000..a418784567 --- /dev/null +++ b/core/converter/kebab-case-converter.js @@ -0,0 +1,44 @@ +/** + * @module montage/core/converter/kebab-case-converter + * @requires montage/core/converter/converter + */ +var Converter = require("./converter").Converter, + kebabCase = require('lodash.kebabcase'), + singleton; + +/** + * Converts string to kebab case. + * + * @class KebabCaseConverter + * @extends Converter + */ +var KebabCaseConverter = exports.KebabCaseConverter = Converter.specialize({ + + constructor: { + value: function () { + if (this.constructor === KebabCaseConverter) { + if (!singleton) { + singleton = this; + } + + return singleton; + } + + return this; + } + }, + + convert: { + value: kebabCase + } +}); + +Object.defineProperty(exports, 'singleton', { + get: function () { + if (!singleton) { + singleton = new KebabCaseConverter(); + } + + return singleton; + } +}); diff --git a/core/converter/kebab-case-converter.mjson b/core/converter/kebab-case-converter.mjson new file mode 100644 index 0000000000..5b077b3188 --- /dev/null +++ b/core/converter/kebab-case-converter.mjson @@ -0,0 +1,25 @@ +{ + "converter_descriptor": { + "object": "core/converter/converter.mjson" + }, + "root": { + "prototype": "core/meta/module-object-descriptor", + "values": { + "name": "KebabCaseConverter", + "customPrototype": false, + "parent": { + "@": "converter_descriptor" + }, + "propertyDescriptors": [], + "propertyDescriptorGroups": {}, + "propertyValidationRules": {}, + "objectDescriptorModule": { + "%": "core/converter/kebab-case-converter.mjson" + }, + "exportName": "KebabCaseConverter", + "module": { + "%": "core/converter/kebab-case-converter" + } + } + } +} diff --git a/core/converter/lower-case-converter.js b/core/converter/lower-case-converter.js index edbfe1feb0..43ca920c24 100644 --- a/core/converter/lower-case-converter.js +++ b/core/converter/lower-case-converter.js @@ -2,13 +2,37 @@ * @module montage/core/converter/lower-case-converter * @requires montage/core/converter/converter */ -var Converter = require("./converter").Converter; +var Converter = require("./converter").Converter, + deprecate = require("../deprecate"), + shouldMuteWarning = false, + singleton; /** * @class LowerCaseConverter * @classdesc Converts a string to lowercase. */ -exports.LowerCaseConverter = Converter.specialize( /** @lends LowerCaseConverter# */{ +var LowerCaseConverter = exports.LowerCaseConverter = Converter.specialize({ + + constructor: { + value: function () { + if (this.constructor === LowerCaseConverter) { + if (!singleton) { + singleton = this; + } + + if (!shouldMuteWarning) { + deprecate.deprecationWarning( + "Instantiating LowerCaseConverter is deprecated," + + " use its singleton instead" + ); + } + + return singleton; + } + + return this; + } + }, _convert: { value: function (v) { @@ -39,3 +63,14 @@ exports.LowerCaseConverter = Converter.specialize( /** @lends LowerCaseConverter }); +Object.defineProperty(exports, 'singleton', { + get: function () { + if (!singleton) { + shouldMuteWarning = true; + singleton = new LowerCaseConverter(); + shouldMuteWarning = false; + } + + return singleton; + } +}); diff --git a/core/converter/lower-case-converter.meta b/core/converter/lower-case-converter.meta deleted file mode 100644 index 911f55ae4d..0000000000 --- a/core/converter/lower-case-converter.meta +++ /dev/null @@ -1,34 +0,0 @@ -{ - "converter_blueprint_reference": { - "prototype": "core/meta/blueprint-reference", - "values": { - "valueReference": { - "blueprintName": "Converter", - "prototypeName": "Converter", - "blueprintModule": { - "%": "core/converter/converter.meta" - } - } - } - }, - "root": { - "prototype": "core/meta/module-blueprint", - "values": { - "name": "LowerCaseConverter", - "customPrototype": false, - "parent": { - "@": "converter_blueprint_reference" - }, - "propertyDescriptors": [], - "propertyDescriptorGroups": {}, - "propertyValidationRules": {}, - "blueprintModule": { - "%": "core/converter/lower-case-converter.meta" - }, - "exportName": "LowerCaseConverter", - "module": { - "%": "core/converter/lower-case-converter" - } - } - } -} diff --git a/core/converter/lower-case-converter.mjson b/core/converter/lower-case-converter.mjson new file mode 100644 index 0000000000..2fcc94263e --- /dev/null +++ b/core/converter/lower-case-converter.mjson @@ -0,0 +1,25 @@ +{ + "converter_descriptor": { + "object": "core/converter/converter.mjson" + }, + "root": { + "prototype": "core/meta/module-object-descriptor", + "values": { + "name": "LowerCaseConverter", + "customPrototype": false, + "parent": { + "@": "converter_descriptor" + }, + "propertyDescriptors": [], + "propertyDescriptorGroups": {}, + "propertyValidationRules": {}, + "objectDescriptorModule": { + "%": "core/converter/lower-case-converter.mjson" + }, + "exportName": "LowerCaseConverter", + "module": { + "%": "core/converter/lower-case-converter" + } + } + } +} diff --git a/core/converter/new-line-to-br-converter.js b/core/converter/new-line-to-br-converter.js index 54b59e8a35..871d67f622 100644 --- a/core/converter/new-line-to-br-converter.js +++ b/core/converter/new-line-to-br-converter.js @@ -2,7 +2,10 @@ * @module montage/core/converter/new-line-to-br-converter * @requires montage/core/converter/converter */ -var Converter = require("./converter").Converter; +var Converter = require("./converter").Converter, + deprecate = require("../deprecate"), + shouldMuteWarning = false, + singleton; /** * Replaces all new line characters with a HTML <br> @@ -19,7 +22,28 @@ var newLineToBr = function (str) { * @class NewLineToBrConverter * @classdesc Converts a newline to a <br> tag. */ -exports.NewLineToBrConverter = Converter.specialize( /** @lends NewLineToBrConverter# */{ +var NewLineToBrConverter = exports.NewLineToBrConverter = Converter.specialize({ + + constructor: { + value: function () { + if (this.constructor === NewLineToBrConverter) { + if (!singleton) { + singleton = this; + } + + if (!shouldMuteWarning) { + deprecate.deprecationWarning( + "Instantiating NewLineToBrConverter is deprecated," + + " use its singleton instead" + ); + } + + return singleton; + } + + return this; + } + }, _convert: { value: function (v) { @@ -50,3 +74,14 @@ exports.NewLineToBrConverter = Converter.specialize( /** @lends NewLineToBrConve }); +Object.defineProperty(exports, 'singleton', { + get: function () { + if (!singleton) { + shouldMuteWarning = true; + singleton = new NewLineToBrConverter(); + shouldMuteWarning = false; + } + + return singleton; + } +}); diff --git a/core/converter/new-line-to-br-converter.meta b/core/converter/new-line-to-br-converter.meta deleted file mode 100644 index dc0212a045..0000000000 --- a/core/converter/new-line-to-br-converter.meta +++ /dev/null @@ -1,34 +0,0 @@ -{ - "converter_blueprint_reference": { - "prototype": "core/meta/blueprint-reference", - "values": { - "valueReference": { - "blueprintName": "Converter", - "prototypeName": "Converter", - "blueprintModule": { - "%": "core/converter/converter.meta" - } - } - } - }, - "root": { - "prototype": "core/meta/module-blueprint", - "values": { - "name": "NewLineToBrConverter", - "customPrototype": false, - "parent": { - "@": "converter_blueprint_reference" - }, - "propertyDescriptors": [], - "propertyDescriptorGroups": {}, - "propertyValidationRules": {}, - "blueprintModule": { - "%": "core/converter/new-line-to-br-converter.meta" - }, - "exportName": "NewLineToBrConverter", - "module": { - "%": "core/converter/new-line-to-br-converter" - } - } - } -} diff --git a/core/converter/new-line-to-br-converter.mjson b/core/converter/new-line-to-br-converter.mjson new file mode 100644 index 0000000000..44ca8e5111 --- /dev/null +++ b/core/converter/new-line-to-br-converter.mjson @@ -0,0 +1,25 @@ +{ + "converter_descriptor": { + "object": "core/converter/converter.mjson" + }, + "root": { + "prototype": "core/meta/module-object-descriptor", + "values": { + "name": "NewLineToBrConverter", + "customPrototype": false, + "parent": { + "@": "converter_descriptor" + }, + "propertyDescriptors": [], + "propertyDescriptorGroups": {}, + "propertyValidationRules": {}, + "objectDescriptorModule": { + "%": "core/converter/new-line-to-br-converter.mjson" + }, + "exportName": "NewLineToBrConverter", + "module": { + "%": "core/converter/new-line-to-br-converter" + } + } + } +} diff --git a/core/converter/number-converter.meta b/core/converter/number-converter.mjson similarity index 72% rename from core/converter/number-converter.meta rename to core/converter/number-converter.mjson index 9e82e7de19..6e373adf33 100644 --- a/core/converter/number-converter.meta +++ b/core/converter/number-converter.mjson @@ -1,9 +1,9 @@ { "numberConverter_shorten": { - "prototype": "core/meta/property-blueprint", + "prototype": "core/meta/property-descriptor", "values": { "name": "shorten", - "blueprint": { + "objectDescriptor": { "@": "root" }, "valueType": "boolean", @@ -11,10 +11,10 @@ } }, "numberConverter_decimals": { - "prototype": "core/meta/property-blueprint", + "prototype": "core/meta/property-descriptor", "values": { "name": "decimals", - "blueprint": { + "objectDescriptor": { "@": "root" }, "valueType": "number", @@ -22,10 +22,10 @@ } }, "numberConverter_round": { - "prototype": "core/meta/property-blueprint", + "prototype": "core/meta/property-descriptor", "values": { "name": "round", - "blueprint": { + "objectDescriptor": { "@": "root" }, "valueType": "boolean", @@ -33,10 +33,10 @@ } }, "numberConverter_forceDecimals": { - "prototype": "core/meta/property-blueprint", + "prototype": "core/meta/property-descriptor", "values": { "name": "forceDecimals", - "blueprint": { + "objectDescriptor": { "@": "root" }, "valueType": "boolean", @@ -44,10 +44,10 @@ } }, "numberConverter_allowFloat": { - "prototype": "core/meta/property-blueprint", + "prototype": "core/meta/property-descriptor", "values": { "name": "allowFloat", - "blueprint": { + "objectDescriptor": { "@": "root" }, "valueType": "boolean", @@ -55,35 +55,26 @@ } }, "numberConverter_allowNegative": { - "prototype": "core/meta/property-blueprint", + "prototype": "core/meta/property-descriptor", "values": { "name": "allowNegative", - "blueprint": { + "objectDescriptor": { "@": "root" }, "valueType": "boolean", "helpKey": "" } }, - "converter_blueprint_reference": { - "prototype": "core/meta/blueprint-reference", - "values": { - "valueReference": { - "blueprintName": "Converter", - "prototypeName": "Converter", - "blueprintModule": { - "%": "core/converter/converter.meta" - } - } - } + "converter_descriptor": { + "object": "core/converter/converter.mjson" }, "root": { - "prototype": "core/meta/module-blueprint", + "prototype": "core/meta/module-object-descriptor", "values": { "name": "NumberConverter", "customPrototype": false, "parent": { - "@": "converter_blueprint_reference" + "@": "converter_descriptor" }, "propertyDescriptors": [ { @@ -105,7 +96,7 @@ "@": "numberConverter_allowNegative" } ], - "propertyBlueprintGroups": { + "propertyDescriptorGroups": { "numberConverter": [ { "@": "numberConverter_shorten" @@ -128,8 +119,8 @@ ] }, "propertyValidationRules": {}, - "blueprintModule": { - "%": "core/converter/number-converter.meta" + "objectDescriptorModule": { + "%": "core/converter/number-converter.mjson" }, "exportName": "NumberConverter", "module": { diff --git a/core/converter/number-to-nearest-integer-converter.js b/core/converter/number-to-nearest-integer-converter.js new file mode 100644 index 0000000000..2bbff703f8 --- /dev/null +++ b/core/converter/number-to-nearest-integer-converter.js @@ -0,0 +1,52 @@ +/** + * @module montage/core/converter/number-to-nearest-integer-converter + * @requires montage/core/converter/converter + */ +var Converter = require("./converter").Converter, + singleton; + +/** + * Converts a number to an integer + * @class NumberToNearestIntegerConverter + * @extends Converter + */ +var NumberToNearestIntegerConverter = exports.NumberToNearestIntegerConverter = Converter.specialize({ + + constructor: { + value: function () { + if (this.constructor === NumberToNearestIntegerConverter) { + if (!singleton) { + singleton = this; + } + + return singleton; + } + + return this; + } + }, + + convert: { + value: function(value) { + return Math.round(value); + } + }, + + revert: { + value: function(value) { + return Math.round(value); + } + } + + +}); + +Object.defineProperty(exports, 'singleton', { + get: function () { + if (!singleton) { + singleton = new NumberToNearestIntegerConverter(); + } + + return singleton; + } +}); diff --git a/core/converter/number-to-nearest-integer-converter.mjson b/core/converter/number-to-nearest-integer-converter.mjson new file mode 100644 index 0000000000..b929b68a7b --- /dev/null +++ b/core/converter/number-to-nearest-integer-converter.mjson @@ -0,0 +1,25 @@ +{ + "converter_descriptor": { + "object": "core/converter/converter.mjson" + }, + "root": { + "prototype": "core/meta/module-object-descriptor", + "values": { + "name": "NumberToNearestIntegerConverter", + "customPrototype": false, + "parent": { + "@": "converter_descriptor" + }, + "propertyDescriptors": [], + "propertyDescriptorGroups": {}, + "propertyValidationRules": {}, + "objectDescriptorModule": { + "%": "core/converter/number-to-nearest-integer-converter.mjson" + }, + "exportName": "NumberToNearestIntegerConverter", + "module": { + "%": "core/converter/number-to-nearest-integer-converter" + } + } + } +} diff --git a/core/converter/pipeline-converter.js b/core/converter/pipeline-converter.js index 6283da5e66..eb0c6fa063 100644 --- a/core/converter/pipeline-converter.js +++ b/core/converter/pipeline-converter.js @@ -33,27 +33,31 @@ exports.PipelineConverter = Converter.specialize({ convert: { value: function (value) { - return this._convertWithNextConverter(value, this.converters.slice()); + return this._convertWithConverterAtIndex(value, 0); } }, - _convertWithNextConverter: { - value: function (input, converters) { + _convertWithConverterAtIndex: { + value: function (input, index) { var self = this, - converter = converters.shift(), + converter = this.converters[index], output = converter.convert(input), - isFinalOutput = converters.length === 0, + isFinalOutput = index === (this.converters.length - 1), isPromise = this._isThenable(output), result; + index++; + + + if (isFinalOutput) { result = isPromise ? output : Promise.resolve(output); } else if (isPromise) { result = output.then(function (value) { - return self._convertWithNextConverter(value, converters); + return self._convertWithConverterAtIndex(value, index); }); } else { - result = this._convertWithNextConverter(output, converters); + result = this._convertWithConverterAtIndex(output, index); } return result; @@ -69,27 +73,29 @@ exports.PipelineConverter = Converter.specialize({ revert: { value: function (value) { - return this._revertWithNextConverter(value, this.converters.slice()); + return this._revertWithConverterAtIndex(value, this.converters.length - 1); } }, - _revertWithNextConverter: { - value: function (input, converters) { + _revertWithConverterAtIndex: { + value: function (input, index) { var self = this, - converter = converters.pop(), + converter = this.converters[index], output = converter.revert(input), - isFinalOutput = converters.length === 0, + isFinalOutput = index === 0, isPromise = this._isThenable(output), result; + index--; + if (isFinalOutput) { result = isPromise ? output : Promise.resolve(output); } else if (isPromise) { result = output.then(function (value) { - return self._revertWithNextConverter(value, converters); + return self._revertWithConverterAtIndex(value, index); }); } else { - result = this._revertWithNextConverter(output, converters); + result = this._revertWithConverterAtIndex(output, index); } return result; diff --git a/core/converter/snake-case-converter.js b/core/converter/snake-case-converter.js new file mode 100644 index 0000000000..291558d386 --- /dev/null +++ b/core/converter/snake-case-converter.js @@ -0,0 +1,44 @@ +/** + * @module montage/core/converter/snake-case-converter + * @requires montage/core/converter/converter + */ +var Converter = require("./converter").Converter, + snakeCase = require('lodash.snakecase'), + singleton; + +/** + * Converts string to snake case. + * + * @class SnakeCaseConverter + * @extends Converter + */ +var SnakeCaseConverter = exports.SnakeCaseConverter = Converter.specialize({ + + constructor: { + value: function () { + if (this.constructor === SnakeCaseConverter) { + if (!singleton) { + singleton = this; + } + + return singleton; + } + + return this; + } + }, + + convert: { + value: snakeCase + } +}); + +Object.defineProperty(exports, 'singleton', { + get: function () { + if (!singleton) { + singleton = new SnakeCaseConverter(); + } + + return singleton; + } +}); diff --git a/core/converter/snake-case-converter.mjson b/core/converter/snake-case-converter.mjson new file mode 100644 index 0000000000..6e9cdb0410 --- /dev/null +++ b/core/converter/snake-case-converter.mjson @@ -0,0 +1,25 @@ +{ + "converter_descriptor": { + "object": "core/converter/converter.mjson" + }, + "root": { + "prototype": "core/meta/module-object-descriptor", + "values": { + "name": "SnakeCaseConverter", + "customPrototype": false, + "parent": { + "@": "converter_descriptor" + }, + "propertyDescriptors": [], + "propertyDescriptorGroups": {}, + "propertyValidationRules": {}, + "objectDescriptorModule": { + "%": "core/converter/snake-case-converter.mjson" + }, + "exportName": "SnakeCaseConverter", + "module": { + "%": "core/converter/snake-case-converter" + } + } + } +} diff --git a/core/converter/trim-converter.js b/core/converter/trim-converter.js index cc4c01b099..2e0868ad61 100644 --- a/core/converter/trim-converter.js +++ b/core/converter/trim-converter.js @@ -2,23 +2,11 @@ * @module montage/core/converter/trim-converter * @requires montage/core/converter/converter */ -var Converter = require("./converter").Converter; - - -/** - * Trims a string of any leading or trailing white space. - * @memberof module:montage/core/converter# - * @function - * @param {string} str String to be trimmed. - * @returns {string} The trimmed string. - */ -var trim = exports.trim = function (str) { - // from Google Closure library - // Since IE doesn't include non-breaking-space (0xa0) in their \s character - // class (as required by section 7.2 of the ECMAScript spec), we explicitly - // include it in the regexp to enforce consistent cross-browser behavior. - return str.replace(/^[\s\xa0]+|[\s\xa0]+$/g, ''); -}; +var Converter = require("./converter").Converter, + trim = require('lodash.trim'), + deprecate = require("../deprecate"), + shouldMuteWarning = false, + singleton; /** * @class TrimConverter @@ -32,7 +20,28 @@ var trim = exports.trim = function (str) { * console.log("After trim: " + trimConverter.convert(str)); * // After trim: Hello World */ -exports.TrimConverter = Converter.specialize( /** @lends TrimConverter# */ { +var TrimConverter = exports.TrimConverter = Converter.specialize({ + + constructor: { + value: function () { + if (this.constructor === TrimConverter) { + if (!singleton) { + singleton = this; + } + + if (!shouldMuteWarning) { + deprecate.deprecationWarning( + "Instantiating TrimConverter is deprecated," + + " use its singleton instead" + ); + } + + return singleton; + } + + return this; + } + }, _convert: { value: function (v) { @@ -64,3 +73,14 @@ exports.TrimConverter = Converter.specialize( /** @lends TrimConverter# */ { }); +Object.defineProperty(exports, 'singleton', { + get: function () { + if (!singleton) { + shouldMuteWarning = true; + singleton = new TrimConverter(); + shouldMuteWarning = false; + } + + return singleton; + } +}); diff --git a/core/converter/trim-converter.meta b/core/converter/trim-converter.meta deleted file mode 100644 index bbeaad42d4..0000000000 --- a/core/converter/trim-converter.meta +++ /dev/null @@ -1,34 +0,0 @@ -{ - "converter_blueprint_reference": { - "prototype": "core/meta/blueprint-reference", - "values": { - "valueReference": { - "blueprintName": "Converter", - "prototypeName": "Converter", - "blueprintModule": { - "%": "core/converter/converter.meta" - } - } - } - }, - "root": { - "prototype": "core/meta/module-blueprint", - "values": { - "name": "TrimConverter", - "customPrototype": false, - "parent": { - "@": "converter_blueprint_reference" - }, - "propertyDescriptors": [], - "propertyBlueprintGroups": {}, - "propertyValidationRules": {}, - "blueprintModule": { - "%": "core/converter/trim-converter.meta" - }, - "exportName": "TrimConverter", - "module": { - "%": "core/converter/trim-converter" - } - } - } -} diff --git a/core/converter/trim-converter.mjson b/core/converter/trim-converter.mjson new file mode 100644 index 0000000000..9052b42fdc --- /dev/null +++ b/core/converter/trim-converter.mjson @@ -0,0 +1,25 @@ +{ + "converter_descriptor": { + "object": "core/converter/converter.mjson" + }, + "root": { + "prototype": "core/meta/module-object-descriptor", + "values": { + "name": "TrimConverter", + "customPrototype": false, + "parent": { + "@": "converter_descriptor" + }, + "propertyDescriptors": [], + "propertyDescriptorGroups": {}, + "propertyValidationRules": {}, + "objectDescriptorModule": { + "%": "core/converter/trim-converter.mjson" + }, + "exportName": "TrimConverter", + "module": { + "%": "core/converter/trim-converter" + } + } + } +} diff --git a/core/converter/upper-case-converter.js b/core/converter/upper-case-converter.js index cff18e03a5..9e4f6bf704 100644 --- a/core/converter/upper-case-converter.js +++ b/core/converter/upper-case-converter.js @@ -2,13 +2,37 @@ * @module montage/core/converter/upper-case-converter * @requires montage/core/converter/converter */ -var Converter = require("./converter").Converter; +var Converter = require("./converter").Converter, + deprecate = require("../deprecate"), + shouldMuteWarning = false, + singleton; /** * @class UpperCaseConverter * @classdesc Converts a string to upper-case. */ -exports.UpperCaseConverter = Converter.specialize( /** @lends UpperCaseConverter# */ { +var UpperCaseConverter = exports.UpperCaseConverter = Converter.specialize({ + + constructor: { + value: function () { + if (this.constructor === UpperCaseConverter) { + if (!singleton) { + singleton = this; + } + + if (!shouldMuteWarning) { + deprecate.deprecationWarning( + "Instantiating UpperCaseConverter is deprecated," + + " use its singleton instead" + ); + } + + return singleton; + } + + return this; + } + }, _convert: { value: function (v) { @@ -41,3 +65,14 @@ exports.UpperCaseConverter = Converter.specialize( /** @lends UpperCaseConverter }); +Object.defineProperty(exports, 'singleton', { + get: function () { + if (!singleton) { + shouldMuteWarning = true; + singleton = new UpperCaseConverter(); + shouldMuteWarning = false; + } + + return singleton; + } +}); diff --git a/core/converter/upper-case-converter.meta b/core/converter/upper-case-converter.meta deleted file mode 100644 index 53a71e4fcc..0000000000 --- a/core/converter/upper-case-converter.meta +++ /dev/null @@ -1,34 +0,0 @@ -{ - "converter_blueprint_reference": { - "prototype": "core/meta/blueprint-reference", - "values": { - "valueReference": { - "blueprintName": "Converter", - "prototypeName": "Converter", - "blueprintModule": { - "%": "core/converter/converter.meta" - } - } - } - }, - "root": { - "prototype": "core/meta/module-blueprint", - "values": { - "name": "UpperCaseConverter", - "customPrototype": false, - "parent": { - "@": "converter_blueprint_reference" - }, - "propertyDescriptors": [], - "propertyDescriptorGroups": {}, - "propertyValidationRules": {}, - "blueprintModule": { - "%": "core/converter/upper-case-converter.meta" - }, - "exportName": "UpperCaseConverter", - "module": { - "%": "core/converter/upper-case-converter" - } - } - } -} diff --git a/core/converter/upper-case-converter.mjson b/core/converter/upper-case-converter.mjson new file mode 100644 index 0000000000..1788689f48 --- /dev/null +++ b/core/converter/upper-case-converter.mjson @@ -0,0 +1,25 @@ +{ + "converter_descriptor": { + "object": "core/converter/converter.mjson" + }, + "root": { + "prototype": "core/meta/module-object-descriptor", + "values": { + "name": "UpperCaseConverter", + "customPrototype": false, + "parent": { + "@": "converter_descriptor" + }, + "propertyDescriptors": [], + "propertyDescriptorGroups": {}, + "propertyValidationRules": {}, + "objectDescriptorModule": { + "%": "core/converter/upper-case-converter.mjson" + }, + "exportName": "UpperCaseConverter", + "module": { + "%": "core/converter/upper-case-converter" + } + } + } +} diff --git a/core/core.js b/core/core.js index 04cfce882d..20c2118ab9 100644 --- a/core/core.js +++ b/core/core.js @@ -11,6 +11,7 @@ require("./extras/element"); require("./extras/function"); require("./extras/regexp"); require("./extras/string"); +require("proxy-polyfill/proxy.min"); var Map = require("collections/map"); @@ -1610,10 +1611,6 @@ var pathPropertyDescriptors = { Montage.defineProperties(Montage, pathPropertyDescriptors); Montage.defineProperties(Montage.prototype, pathPropertyDescriptors); -// has to come last since serializer and deserializer depend on logger, which -// in turn depends on montage running to completion -require("./serialization/bindings"); - /* * Defines the module Id for object descriptors. This is externalized so that it can be subclassed. * Note This is a class method beware... @@ -1727,3 +1724,7 @@ exports._objectDescriptorDescriptor = { * @deprecated use exports._objectDescriptorDescriptor */ exports._blueprintDescriptor = exports._objectDescriptorDescriptor; + +// has to come last since serializer and deserializer depend on logger, which +// in turn depends on montage running to completion +require("./serialization/bindings"); diff --git a/core/event/action-event-listener.js b/core/event/action-event-listener.js index 4a3217c618..8133718a59 100644 --- a/core/event/action-event-listener.js +++ b/core/event/action-event-listener.js @@ -82,6 +82,8 @@ var ActionEventListener = exports.ActionEventListener = Montage.specialize( /** } }, { + objectDescriptorModuleId: require("../core")._objectDescriptorModuleIdDescriptor, + objectDescriptor: require("../core")._objectDescriptorDescriptor, blueprintModuleId: require("../core")._blueprintModuleIdDescriptor, blueprint: require("../core")._blueprintDescriptor }); diff --git a/core/event/action-event-listener.meta b/core/event/action-event-listener.meta index 3664130a2e..ea0f08e42e 100644 --- a/core/event/action-event-listener.meta +++ b/core/event/action-event-listener.meta @@ -1,26 +1,26 @@ { "actionEventListener_handler": { - "prototype": "core/meta/property-blueprint", + "prototype": "core/meta/property-descriptor", "values": { "name": "handler", - "blueprint": { + "objectDescriptor": { "@": "root" }, "valueType": "object" } }, "actionEventListener_action": { - "prototype": "core/meta/property-blueprint", + "prototype": "core/meta/property-descriptor", "values": { "name": "action", - "blueprint": { + "objectDescriptor": { "@": "root" }, "valueType": "string" } }, "root": { - "prototype": "core/meta/module-blueprint", + "prototype": "core/meta/module-descriptor", "values": { "name": "ActionEventListener", "customPrototype": false, @@ -32,7 +32,7 @@ "@": "actionEventListener_action" } ], - "propertyBlueprintGroups": { + "propertyDescriptorGroups": { "actionEventListener": [ { "@": "actionEventListener_handler" @@ -42,7 +42,7 @@ } ] }, - "blueprintModule": { + "objectDescriptorModule": { "%": "core/event/action-event-listener.meta" }, "exportName": "ActionEventListener", diff --git a/core/event/event-manager.js b/core/event/event-manager.js index e017a8e964..56d8e812e0 100644 --- a/core/event/event-manager.js +++ b/core/event/event-manager.js @@ -1,4 +1,4 @@ -/*global Window, Document, Element, Event, Components, Touch */ +/*global Window, Document, Element, Event, Components, Touch, MontageElement */ /** * @author Lea Verou @@ -560,6 +560,15 @@ var EventManager = exports.EventManager = Montage.specialize(/** @lends EventMan aWindow.document.nativeAddEventListener = aWindow.document.addEventListener; aWindow.XMLHttpRequest.prototype.nativeAddEventListener = aWindow.XMLHttpRequest.prototype.addEventListener; + + if (aWindow.DocumentFragment) { + aWindow.DocumentFragment.prototype.nativeAddEventListener = aWindow.DocumentFragment.prototype.addEventListener; + } + + if (aWindow.ShadowRoot) { + aWindow.ShadowRoot.prototype.nativeAddEventListener = aWindow.ShadowRoot.prototype.addEventListener; + } + if (aWindow.Worker) { aWindow.Worker.prototype.nativeAddEventListener = aWindow.Worker.prototype.addEventListener; } @@ -575,6 +584,15 @@ var EventManager = exports.EventManager = Montage.specialize(/** @lends EventMan aWindow.document.nativeRemoveEventListener = aWindow.document.removeEventListener; aWindow.XMLHttpRequest.prototype.nativeRemoveEventListener = aWindow.XMLHttpRequest.prototype.removeEventListener; + + if (aWindow.DocumentFragment) { + aWindow.DocumentFragment.prototype.nativeRemoveEventListener = aWindow.DocumentFragment.prototype.removeEventListener; + } + + if (aWindow.ShadowRoot) { + aWindow.ShadowRoot.prototype.nativeRemoveEventListener = aWindow.ShadowRoot.prototype.removeEventListener; + } + if (aWindow.Worker) { aWindow.Worker.prototype.nativeRemoveEventListener = aWindow.Worker.prototype.removeEventListener; } @@ -1167,12 +1185,27 @@ var EventManager = exports.EventManager = Montage.specialize(/** @lends EventMan if (bubbles) { // TODO why on the document and not the window? - return /* isWindow*/target.screen ? target.document : target.ownerDocument; + var shadowRoot; + return /* isWindow*/target.screen ? target.document : + (shadowRoot = this.shawdowRootFromNode(target)) ? + shadowRoot : target.ownerDocument; } else { return target; } } + } + }, + shawdowRootFromNode: { + value: function isInShadow(node) { + if (window.ShadowRoot) { + while (node) { + if (node.toString() === "[object ShadowRoot]") { + return node; + } + node = node.parentNode; + } + } } }, @@ -1183,6 +1216,16 @@ var EventManager = exports.EventManager = Montage.specialize(/** @lends EventMan // Individual Event Registration + _scrollBlockingEvents: { + value: [ + 'wheel', + 'mousewheel', + 'touchstart', + 'touchmove', + 'scroll' + ] + }, + /** * @private */ @@ -1198,7 +1241,12 @@ var EventManager = exports.EventManager = Montage.specialize(/** @lends EventMan } this._observedTarget_byEventType_[eventType].set(listenerTarget,this); - listenerTarget.nativeAddEventListener(eventType, this, true); + var isScrollBlocking = this._scrollBlockingEvents.indexOf(eventType) !== -1, + eventOpts = isScrollBlocking ? { + passive: true + } : true; + + listenerTarget.nativeAddEventListener(eventType, this, eventOpts); } // console.log("started listening: ", eventType, listenerTarget) } @@ -1262,43 +1310,50 @@ var EventManager = exports.EventManager = Montage.specialize(/** @lends EventMan } }; } + + this.registerTargetForActivation(aWindow); + + if (this.application) { + + var applicationLevelEvents = this.registeredEventListenersOnTarget_(this.application), + eventType; + for (eventType in applicationLevelEvents) { + if (applicationLevelEvents.hasOwnProperty(eventType)) { + this._observeTarget_forEventType_(aWindow, eventType); + } + } + } + } + }, + + registerTargetForActivation: { + value: function (target) { + var _document = target instanceof Window ? target.document : target; // The EventManager needs to handle "gateway/pointer/activation events" that we // haven't let children listen for yet // when the EM handles them eventually it will need to allow // all components from the event target to the window to prepareForActivationEvents // before finding event handlers that were registered for these events - if (aWindow.PointerEvent) { - aWindow.nativeAddEventListener("pointerdown", this._activationHandler, true); - aWindow.document.nativeAddEventListener("pointerenter", this._activationHandler, true); + if (window.PointerEvent) { + target.nativeAddEventListener("pointerdown", this._activationHandler, true); + _document.nativeAddEventListener("pointerenter", this._activationHandler, true); - } else if (aWindow.MSPointerEvent && aWindow.navigator.msPointerEnabled) { - aWindow.nativeAddEventListener("MSPointerDown", this._activationHandler, true); + } else if (window.MSPointerEvent && window.navigator.msPointerEnabled) { + target.nativeAddEventListener("MSPointerDown", this._activationHandler, true); // IE10 has no support for pointerenter or pointerleave events. - aWindow.document.nativeAddEventListener("mouseenter", this._activationHandler, true); + _document.nativeAddEventListener("mouseenter", this._activationHandler, true); } else { - aWindow.nativeAddEventListener("touchstart", this._activationHandler, true); - aWindow.nativeAddEventListener("mousedown", this._activationHandler, true); + target.nativeAddEventListener("touchstart", this._activationHandler, true); + target.nativeAddEventListener("mousedown", this._activationHandler, true); // mouseenter events are not dispatched from window under Chrome and Safari. - aWindow.document.nativeAddEventListener("mouseenter", this._activationHandler, true); - } - - aWindow.nativeAddEventListener("focus", this._activationHandler, true); - - if (this.application) { - - var applicationLevelEvents = this.registeredEventListenersOnTarget_(this.application), - eventType; - - for (eventType in applicationLevelEvents) { - if (applicationLevelEvents.hasOwnProperty(eventType)) { - this._observeTarget_forEventType_(aWindow, eventType); - } - } + _document.nativeAddEventListener("mouseenter", this._activationHandler, true); } + target.nativeAddEventListener("focus", this._activationHandler, true); } + }, /** @@ -2347,10 +2402,10 @@ var EventManager = exports.EventManager = Montage.specialize(/** @lends EventMan break; } } - return identifier; } }, + /** * @function @@ -2373,6 +2428,7 @@ var EventManager = exports.EventManager = Montage.specialize(/** @lends EventMan } }, + // Event Handling /** * @property @@ -2412,7 +2468,8 @@ var EventManager = exports.EventManager = Montage.specialize(/** @lends EventMan handleEvent: { enumerable: false, value: function (event) { - if (event instanceof UIEvent && !this._shouldDispatchEvent(event)) { + if ((window.MontageElement && event.target instanceof MontageElement) || + (event instanceof UIEvent && !this._shouldDispatchEvent(event))) { return void 0; } diff --git a/core/extras/dom.js b/core/extras/dom.js index 2f8f9bc648..e3aa5f8830 100644 --- a/core/extras/dom.js +++ b/core/extras/dom.js @@ -184,4 +184,17 @@ if (typeof Node !== "undefined") { } } }; -} \ No newline at end of file +} + +// Extend DOMTokenList.prototype +if (typeof DOMTokenList !== "undefined") { + var DOMTokenListPrototype = window.DOMTokenList.prototype; + + if (typeof DOMTokenListPrototype.has === 'undefined') { + Object.defineProperty(DOMTokenListPrototype, 'has', { + value: function (key) { + return this.contains(key); + } + }); + } +} diff --git a/core/extras/element.js b/core/extras/element.js index ddddbd038f..d5b742db0f 100644 --- a/core/extras/element.js +++ b/core/extras/element.js @@ -7,4 +7,10 @@ if (typeof Element !== "undefined" && !Element.isElement) { writable: true, configurable: true }); + + Object.defineProperty(Element.prototype, "nativeSetAttribute", { + value: Element.prototype.setAttribute, + writable: true, + configurable: true + }); } diff --git a/core/media-controller.js b/core/media-controller.js index f3b4b3d48c..f3fdfd5340 100644 --- a/core/media-controller.js +++ b/core/media-controller.js @@ -616,9 +616,12 @@ var MediaController = exports.MediaController = Target.specialize(/** @lends Med } }, { - blueprintModuleId:require("./core")._blueprintModuleIdDescriptor, - blueprint:require("./core")._blueprintDescriptor + blueprint:require("./core")._blueprintDescriptor, + + objectDescriptorModuleId:require("./core")._objectDescriptorModuleIdDescriptor, + + objectDescriptor:require("./core")._objectDescriptorDescriptor }); diff --git a/core/media-controller.meta b/core/media-controller.meta index b41c363450..c31dfd6058 100644 --- a/core/media-controller.meta +++ b/core/media-controller.meta @@ -1,9 +1,9 @@ { "mediaController_status": { - "prototype": "core/meta/property-blueprint", + "prototype": "core/meta/property-descriptor", "values": { "name": "status", - "blueprint": { + "objectDescriptor": { "@": "root" }, "valueType": "number", @@ -12,10 +12,10 @@ }, "mediaController_STOPPED": { - "prototype": "core/meta/property-blueprint", + "prototype": "core/meta/property-descriptor", "values": { "name": "STOPPED", - "blueprint": { + "objectDescriptor": { "@": "root" }, "valueType": "number", @@ -24,10 +24,10 @@ }, "mediaController_PLAYING": { - "prototype": "core/meta/property-blueprint", + "prototype": "core/meta/property-descriptor", "values": { "name": "PLAYING", - "blueprint": { + "objectDescriptor": { "@": "root" }, "valueType": "number", @@ -36,10 +36,10 @@ }, "mediaController_PAUSED": { - "prototype": "core/meta/property-blueprint", + "prototype": "core/meta/property-descriptor", "values": { "name": "PAUSED", - "blueprint": { + "objectDescriptor": { "@": "root" }, "valueType": "number", @@ -48,10 +48,10 @@ }, "mediaController_EMPTY": { - "prototype": "core/meta/property-blueprint", + "prototype": "core/meta/property-descriptor", "values": { "name": "EMPTY", - "blueprint": { + "objectDescriptor": { "@": "root" }, "valueType": "number", @@ -60,10 +60,10 @@ }, "mediaController_mediaController": { - "prototype": "core/meta/property-blueprint", + "prototype": "core/meta/property-descriptor", "values": { "name": "mediaController", - "blueprint": { + "objectDescriptor": { "@": "root" }, "valueType": "object", @@ -72,10 +72,10 @@ }, "mediaController_position": { - "prototype": "core/meta/property-blueprint", + "prototype": "core/meta/property-descriptor", "values": { "name": "position", - "blueprint": { + "objectDescriptor": { "@": "root" }, "valueType": "number", @@ -84,10 +84,10 @@ }, "mediaController_duration": { - "prototype": "core/meta/property-blueprint", + "prototype": "core/meta/property-descriptor", "values": { "name": "duration", - "blueprint": { + "objectDescriptor": { "@": "root" }, "valueType": "number", @@ -96,10 +96,10 @@ }, "mediaController_autoplay": { - "prototype": "core/meta/property-blueprint", + "prototype": "core/meta/property-descriptor", "values": { "name": "autoplay", - "blueprint": { + "objectDescriptor": { "@": "root" }, "valueType": "boolean", @@ -108,10 +108,10 @@ }, "mediaController_playbackRate": { - "prototype": "core/meta/property-blueprint", + "prototype": "core/meta/property-descriptor", "values": { "name": "playbackRate", - "blueprint": { + "objectDescriptor": { "@": "root" }, "valueType": "number", @@ -120,10 +120,10 @@ }, "mediaController_currentTime": { - "prototype": "core/meta/property-blueprint", + "prototype": "core/meta/property-descriptor", "values": { "name": "currentTime", - "blueprint": { + "objectDescriptor": { "@": "root" }, "valueType": "number", @@ -132,10 +132,10 @@ }, "mediaController_volume": { - "prototype": "core/meta/property-blueprint", + "prototype": "core/meta/property-descriptor", "values": { "name": "volume", - "blueprint": { + "objectDescriptor": { "@": "root" }, "valueType": "number", @@ -144,10 +144,10 @@ }, "mediaController_mute": { - "prototype": "core/meta/property-blueprint", + "prototype": "core/meta/property-descriptor", "values": { "name": "mute", - "blueprint": { + "objectDescriptor": { "@": "root" }, "valueType": "boolean", @@ -156,14 +156,14 @@ }, "root": { - "prototype": "core/meta/module-blueprint", + "prototype": "core/meta/module-object-descriptor", "values": { "name": "MediaController", "exportName": "MediaController", "module": { "%": "core/media-controller" }, - "blueprintModule": { + "objectDescriptorModule": { "%": "core/media-controller.meta" }, "prototypeName": "MediaController", diff --git a/core/meta/association-blueprint.meta b/core/meta/association-blueprint.meta index d814674918..3e769ef46d 100644 --- a/core/meta/association-blueprint.meta +++ b/core/meta/association-blueprint.meta @@ -14,16 +14,7 @@ } }, "property_blueprint_reference": { - "prototype": "core/meta/blueprint-reference", - "values": { - "valueReference": { - "blueprintName": "PropertyBlueprint", - "prototypeName": "PropertyBlueprint", - "blueprintModule": { - "%": "core/meta/property-blueprint.meta" - } - } - } + "object": "core/meta/property-blueprint.meta" }, "root": { "prototype": "core/meta/module-blueprint", diff --git a/core/meta/derived-descriptor.mjson b/core/meta/derived-descriptor.mjson index da2b8c6627..1d37966f7c 100644 --- a/core/meta/derived-descriptor.mjson +++ b/core/meta/derived-descriptor.mjson @@ -48,16 +48,7 @@ } }, "property_descriptor_reference": { - "prototype": "core/meta/object-descriptor-reference", - "values": { - "valueReference": { - "objectDescriptorName": "PropertyDescriptor", - "prototypeName": "PropertyDescriptor", - "objectDescriptorModule": { - "%": "core/meta/property-descriptor.mjson" - } - } - } + "object": "core/meta/property-descriptor.mjson" }, "root": { "prototype": "core/meta/module-object-descriptor", diff --git a/core/meta/event-descriptor.mjson b/core/meta/event-descriptor.mjson index f1b84c40d8..b5bd53b6f5 100644 --- a/core/meta/event-descriptor.mjson +++ b/core/meta/event-descriptor.mjson @@ -1,15 +1,6 @@ { "owner_reference": { - "prototype": "core/meta/object-descriptor-reference", - "values": { - "valueReference": { - "objectDescriptorName": "ObjectDescriptor", - "prototypeName": "ObjectDescriptor", - "objectDescriptorModule": { - "%": "core/meta/object-descriptor.mjson" - } - } - } + "object": "core/meta/object-descriptor.mjson" }, "name": { "prototype": "core/meta/property-descriptor", diff --git a/core/meta/model.js b/core/meta/model.js index 674fbf5585..6ac88f0cbc 100644 --- a/core/meta/model.js +++ b/core/meta/model.js @@ -370,7 +370,6 @@ var Model = exports.Model = Montage.specialize( /** @lends Model.prototype # */ if (_group === null) { _group = new ModelGroup(); _group.name = application ? application.name : ""; - //console.log("Default ModelGroup name is ", _group.name); } return _group; } diff --git a/core/meta/model.mjson b/core/meta/model.mjson index 22bce97d12..ccc387953f 100644 --- a/core/meta/model.mjson +++ b/core/meta/model.mjson @@ -1,15 +1,6 @@ { "object_descriptor_reference": { - "prototype": "core/meta/object-descriptor-reference", - "values": { - "valueReference": { - "objectDescriptorName": "ObjectDescriptor", - "prototypeName": "ObjectDescriptor", - "objectDescriptorModule": { - "%": "core/meta/object-descriptor.mjson" - } - } - } + "object": "core/meta/object-descriptor" }, "model_objectDescriptors": { "prototype": "core/meta/property-descriptor", diff --git a/core/meta/object-descriptor-reference.mjson b/core/meta/object-descriptor-reference.mjson index fd416f4f12..8d12976782 100644 --- a/core/meta/object-descriptor-reference.mjson +++ b/core/meta/object-descriptor-reference.mjson @@ -23,7 +23,7 @@ "@": "value_target_object_descriptor" } ], - "propertyBlueprintGroups": { + "propertyDescriptorGroups": { "associations": [ { "@": "value_target_object_descriptor" diff --git a/core/meta/object-descriptor.js b/core/meta/object-descriptor.js index a6219d5967..d8099b6635 100644 --- a/core/meta/object-descriptor.js +++ b/core/meta/object-descriptor.js @@ -2,7 +2,6 @@ var Montage = require("../core").Montage, DerivedDescriptor = require("./derived-descriptor").DerivedDescriptor, EventDescriptor = require("./event-descriptor").EventDescriptor, ModelModule = require("./model"), - ObjectDescriptorReference = require("./object-descriptor-reference").ObjectDescriptorReference, Promise = require("../promise").Promise, PropertyDescriptor = require("./property-descriptor").PropertyDescriptor, PropertyValidationRule = require("./validation-rule").PropertyValidationRule, @@ -59,8 +58,8 @@ var ObjectDescriptor = exports.ObjectDescriptor = Montage.specialize( /** @lends if (this.objectDescriptorInstanceModule) { serializer.setProperty("objectDescriptorModule", this.objectDescriptorInstanceModule); } - if (this._parentReference) { - serializer.setProperty("parent", this._parentReference); + if (this._parent) { + serializer.setProperty("parent", this._parent); } this._setPropertyWithDefaults(serializer, "customPrototype", this.customPrototype); @@ -85,14 +84,20 @@ var ObjectDescriptor = exports.ObjectDescriptor = Montage.specialize( /** @lends deserializeSelf: { value:function (deserializer) { - var value, model; + var value, model, parentReference; this._name = deserializer.getProperty("name"); value = deserializer.getProperty("model") || deserializer.getProperty("binder"); if (value) { this._model = value; } this.objectDescriptorInstanceModule = deserializer.getProperty("objectDescriptorModule") || deserializer.getProperty("blueprintModule"); - this._parentReference = deserializer.getProperty("parent"); + parentReference = deserializer.getProperty("parent"); + if (parentReference && parentReference.promise && parentReference.valueFromReference) { + deprecate.deprecationWarningOnce("parent reference via ObjectDescriptorReference", "direct reference with object syntax"); + this._parentReference = parentReference; + } else { + this._parent = parentReference; + } this.customPrototype = this._getPropertyWithDefaults(deserializer, "customPrototype"); // @@ -317,7 +322,7 @@ var ObjectDescriptor = exports.ObjectDescriptor = Montage.specialize( /** @lends /** * Blueprint parent - * @returns {?ObjectDescriptorReference} + * @type {?ObjectDescriptor} */ parent: { serializable: false, @@ -325,13 +330,7 @@ var ObjectDescriptor = exports.ObjectDescriptor = Montage.specialize( /** @lends return this._parent; }, set: function (objectDescriptor) { - if (objectDescriptor) { - this._parentReference = new ObjectDescriptorReference().initWithValue(objectDescriptor); - this._parent = objectDescriptor; - } else { - this._parentReference = null; - this._parent = null; - } + this._parent = objectDescriptor; } }, @@ -573,7 +572,7 @@ var ObjectDescriptor = exports.ObjectDescriptor = Montage.specialize( /** @lends name; for (name in this._propertyDescriptorGroups) { if (this._propertyDescriptorGroups.hasOwnProperty(name)) { - groups.push(name); + groups.push(name); } } if (this.parent) { @@ -782,7 +781,7 @@ var ObjectDescriptor = exports.ObjectDescriptor = Montage.specialize( /** @lends } this._eventPropertyDescriptorsTable[name] = eventDescriptor; } - + // TODO: Come back after creating event property descriptor if (eventDescriptor === exports.UnknownEventDescriptor) { eventDescriptor = null; @@ -812,7 +811,7 @@ var ObjectDescriptor = exports.ObjectDescriptor = Montage.specialize( /** @lends propertyValidationRules = []; for (propertyName in this._propertyValidationRules) { if (this._propertyValidationRules.hasOwnProperty(propertyName)) { - propertyValidationRules.push(this._propertyValidationRules[propertyName]); + propertyValidationRules.push(this._propertyValidationRules[propertyName]); } } if (this.parent) { @@ -886,7 +885,7 @@ var ObjectDescriptor = exports.ObjectDescriptor = Montage.specialize( /** @lends rule = this._propertyValidationRules[name]; if (rule.evaluateRule(objectInstance)) { messages.push(rule.messageKey); - } + } } } return messages; diff --git a/core/meta/object-descriptor.mjson b/core/meta/object-descriptor.mjson index b9c9f902a5..addc79bd7b 100644 --- a/core/meta/object-descriptor.mjson +++ b/core/meta/object-descriptor.mjson @@ -1,39 +1,12 @@ { "model_reference": { - "prototype": "core/meta/model-reference", - "values": { - "valueReference": { - "objectDescriptorName": "Model", - "prototypeName": "Model", - "objectDescriptorModule": { - "%": "core/meta/model.mjson" - } - } - } + "object": "core/meta/model.mjson" }, "property_descriptor_reference": { - "prototype": "core/meta/object-descriptor-reference", - "values": { - "valueReference": { - "objectDescriptorName": "PropertyDescriptor", - "prototypeName": "PropertyDescriptor", - "objectDescriptorModule": { - "%": "core/meta/property-descriptor.mjson" - } - } - } + "object": "core/meta/property-descriptor.mjson" }, "property_validation_rules_reference": { - "prototype": "core/meta/object-descriptor-reference", - "values": { - "valueReference": { - "objectDescriptorName": "PropertyValidationRule", - "prototypeName": "PropertyValidationRule", - "objectDescriptorModule": { - "%": "core/meta/validation-rule.mjson" - } - } - } + "object": "core/meta/validation-rule.mjson" }, "name": { "prototype": "core/meta/property-descriptor", diff --git a/core/meta/property-descriptor.js b/core/meta/property-descriptor.js index ba7152929a..12361d4001 100644 --- a/core/meta/property-descriptor.js +++ b/core/meta/property-descriptor.js @@ -1,5 +1,5 @@ var Montage = require("../core").Montage, - ObjectDescriptorReference = require("./object-descriptor-reference").ObjectDescriptorReference, + Promise = require("../promise").Promise, deprecate = require("../deprecate"), logger = require("../logger").logger("objectDescriptor"); @@ -321,11 +321,17 @@ exports.PropertyDescriptor = Montage.specialize( /** @lends PropertyDescriptor# valueDescriptor: { serializable: false, get: function () { - return this._valueDescriptorReference && this._valueDescriptorReference.promise(this.require); + // TODO: Needed for backwards compatibility with ObjectDescriptorReference. + // Remove eventually, this can become completely sync + if (typeof this._valueDescriptorReference.promise === "function") { + deprecate.deprecationWarningOnce("valueDescriptor reference via ObjectDescriptorReference", "direct reference via object syntax"); + return this._valueDescriptorReference.promise(this.require); + } else { + return Promise.resolve(this._valueDescriptorReference); + } }, set: function (descriptor) { - - this._valueDescriptorReference = new ObjectDescriptorReference().initWithValue(descriptor); + this._valueDescriptorReference = descriptor; } }, diff --git a/core/meta/property-descriptor.mjson b/core/meta/property-descriptor.mjson index f495717e71..329b506ca0 100644 --- a/core/meta/property-descriptor.mjson +++ b/core/meta/property-descriptor.mjson @@ -1,15 +1,6 @@ { "owner_reference": { - "prototype": "core/meta/object-descriptor-reference", - "values": { - "valueReference": { - "objectDescriptorName": "ObjectDescriptor", - "prototypeName": "ObjectDescriptor", - "objectDescriptorModule": { - "%": "core/meta/object-descriptor.mjson" - } - } - } + "object": "core/meta/object-descriptor.mjson" }, "property_name": { "prototype": "core/meta/property-descriptor", diff --git a/core/meta/validation-rule.mjson b/core/meta/validation-rule.mjson index eff1297052..26ab1db061 100644 --- a/core/meta/validation-rule.mjson +++ b/core/meta/validation-rule.mjson @@ -1,15 +1,6 @@ { "owner_reference": { - "prototype": "core/meta/object-descriptor-reference", - "values": { - "valueReference": { - "objectDescriptorName": "ObjectDescriptor", - "prototypeName": "ObjectDescriptor", - "objectDescriptorModule": { - "%": "core/meta/object-descriptor.mjson" - } - } - } + "object": "core/meta/object-descriptor.mjson" }, "validation_rule_object_descriptor_name": { "prototype": "core/meta/property-descriptor", diff --git a/core/object-controller.js b/core/object-controller.js index 9e08b7494e..9347476f85 100644 --- a/core/object-controller.js +++ b/core/object-controller.js @@ -53,6 +53,10 @@ exports.ObjectController = Montage.specialize( /** @lends ObjectController# */ { value: null }, + objectDescriptorModuleId:require("./core")._objectDescriptorModuleIdDescriptor, + + objectDescriptor:require("./core")._objectDescriptorDescriptor, + blueprintModuleId:require("./core")._blueprintModuleIdDescriptor, blueprint:require("./core")._blueprintDescriptor diff --git a/core/promise-controller.js b/core/promise-controller.js index d819f792fa..ba92d85a79 100644 --- a/core/promise-controller.js +++ b/core/promise-controller.js @@ -166,6 +166,10 @@ exports.PromiseController = Montage.specialize( { }, /** @lends PromiseController. */ { + objectDescriptorModuleId:require("./core")._objectDescriptorModuleIdDescriptor, + + objectDescriptor:require("./core")._objectDescriptorDescriptor, + blueprintModuleId:require("./core")._blueprintModuleIdDescriptor, blueprint:require("./core")._blueprintDescriptor diff --git a/core/promise-controller.meta b/core/promise-controller.meta index c6ac5db5aa..85c015298e 100644 --- a/core/promise-controller.meta +++ b/core/promise-controller.meta @@ -1,9 +1,9 @@ { "promiseController_promise": { - "prototype": "core/meta/property-blueprint", + "prototype": "core/meta/property-descriptor", "values": { "name": "promise", - "blueprint": { + "objectDescriptor": { "@": "root" }, "valueType": "object", @@ -11,10 +11,10 @@ } }, "promiseController_value": { - "prototype": "core/meta/property-blueprint", + "prototype": "core/meta/property-descriptor", "values": { "name": "value", - "blueprint": { + "objectDescriptor": { "@": "root" }, "valueType": "object", @@ -22,10 +22,10 @@ } }, "promiseController_error": { - "prototype": "core/meta/property-blueprint", + "prototype": "core/meta/property-descriptor", "values": { "name": "error", - "blueprint": { + "objectDescriptor": { "@": "root" }, "valueType": "object", @@ -33,10 +33,10 @@ } }, "promiseController_pending": { - "prototype": "core/meta/property-blueprint", + "prototype": "core/meta/property-descriptor", "values": { "name": "pending", - "blueprint": { + "objectDescriptor": { "@": "root" }, "valueType": "boolean", @@ -44,10 +44,10 @@ } }, "promiseController_fulfilled": { - "prototype": "core/meta/property-blueprint", + "prototype": "core/meta/property-descriptor", "values": { "name": "fulfilled", - "blueprint": { + "objectDescriptor": { "@": "root" }, "valueType": "boolean", @@ -55,10 +55,10 @@ } }, "promiseController_rejected": { - "prototype": "core/meta/property-blueprint", + "prototype": "core/meta/property-descriptor", "values": { "name": "rejected", - "blueprint": { + "objectDescriptor": { "@": "root" }, "valueType": "boolean", @@ -66,7 +66,7 @@ } }, "root": { - "prototype": "core/meta/module-blueprint", + "prototype": "core/meta/module-object-descriptor", "values": { "name": "PromiseController", "customPrototype": false, @@ -113,7 +113,7 @@ ] }, "propertyValidationRules": {}, - "blueprintModule": { + "objectDescriptorModule": { "%": "core/promise-controller.meta" }, "exportName": "PromiseController", diff --git a/core/radio-button-controller.js b/core/radio-button-controller.js index 6daa3be32d..fa2dc09a75 100644 --- a/core/radio-button-controller.js +++ b/core/radio-button-controller.js @@ -142,6 +142,10 @@ exports.RadioButtonController = Montage.specialize(/** @lends RadioButtonControl }, /** @lends RadioButtonController. */ { + objectDescriptorModuleId:require("./core")._objectDescriptorModuleIdDescriptor, + + objectDescriptor:require("./core")._objectDescriptorDescriptor, + blueprintModuleId:require("./core")._blueprintModuleIdDescriptor, blueprint:require("./core")._blueprintDescriptor diff --git a/core/radio-button-controller.meta b/core/radio-button-controller.meta index 7bbe73f29a..618634c639 100644 --- a/core/radio-button-controller.meta +++ b/core/radio-button-controller.meta @@ -1,38 +1,38 @@ { - "blueprint_radio_button_controller_value": { - "prototype": "core/meta/property-blueprint", + "objectDescriptor_radio_button_controller_value": { + "prototype": "core/meta/property-descriptor", "values": { "name": "value", - "blueprint": { "@": "root" }, + "objectDescriptor": { "@": "root" }, "valueType": "object", "helpKey": "" } }, - "blueprint_radio_button_controller_contentController": { - "prototype": "core/meta/property-blueprint", + "objectDescriptor_radio_button_controller_contentController": { + "prototype": "core/meta/property-descriptor", "values": { "name": "contentController", - "blueprint": { "@": "root" }, + "objectDescriptor": { "@": "root" }, "valueType": "object", "helpKey": "" } }, "root": { - "prototype": "core/meta/module-blueprint", + "prototype": "core/meta/module-object-descriptor", "values": { "name": "RadioButtonController", "propertyDescriptors": [ - { "@": "blueprint_radio_button_controller_value" }, - { "@": "blueprint_radio_button_controller_contentController" } + { "@": "objectDescriptor_radio_button_controller_value" }, + { "@": "objectDescriptor_radio_button_controller_contentController" } ], "propertyDescriptorGroups": { "Selection": [ - { "@": "blueprint_radio_button_controller_value" }, - { "@": "blueprint_radio_button_controller_contentController" } + { "@": "objectDescriptor_radio_button_controller_value" }, + { "@": "objectDescriptor_radio_button_controller_contentController" } ] }, "propertyValidationRules": {}, - "blueprintModule": { "%": "core/radio-button-controller.meta" }, + "objectDescriptorModule": { "%": "core/radio-button-controller.meta" }, "exportName": "RadioButtonController", "module": { "%": "core/radio-button-controller" } } diff --git a/core/range-controller.js b/core/range-controller.js index e764ff7253..d1eca2c6fc 100644 --- a/core/range-controller.js +++ b/core/range-controller.js @@ -840,7 +840,11 @@ var RangeController = exports.RangeController = Montage.specialize( /** @lends R } } -}, /** @lends RangeController */ { +}, /** @lends RangeController. */ { + + objectDescriptorModuleId:require("./core")._objectDescriptorModuleIdDescriptor, + + objectDescriptor:require("./core")._objectDescriptorDescriptor, blueprintModuleId:require("./core")._blueprintModuleIdDescriptor, diff --git a/core/range-controller.meta b/core/range-controller.meta index a77315849d..2e7fda17d7 100644 --- a/core/range-controller.meta +++ b/core/range-controller.meta @@ -1,9 +1,9 @@ { "rangeController_content": { - "prototype": "core/meta/property-blueprint", + "prototype": "core/meta/property-descriptor", "values": { "name": "content", - "blueprint": { + "objectDescriptor": { "@": "root" }, "cardinality": -1, @@ -12,10 +12,10 @@ } }, "rangeController_organizedContent": { - "prototype": "core/meta/property-blueprint", + "prototype": "core/meta/property-descriptor", "values": { "name": "organizedContent", - "blueprint": { + "objectDescriptor": { "@": "root" }, "cardinality": -1, @@ -24,10 +24,10 @@ } }, "rangeController_sortPath": { - "prototype": "core/meta/property-blueprint", + "prototype": "core/meta/property-descriptor", "values": { "name": "sortPath", - "blueprint": { + "objectDescriptor": { "@": "root" }, "valueType": "string", @@ -35,10 +35,10 @@ } }, "rangeController_reversed": { - "prototype": "core/meta/property-blueprint", + "prototype": "core/meta/property-descriptor", "values": { "name": "reversed", - "blueprint": { + "objectDescriptor": { "@": "root" }, "valueType": "boolean", @@ -46,10 +46,10 @@ } }, "rangeController_filterPath": { - "prototype": "core/meta/property-blueprint", + "prototype": "core/meta/property-descriptor", "values": { "name": "filterPath", - "blueprint": { + "objectDescriptor": { "@": "root" }, "valueType": "string", @@ -57,10 +57,10 @@ } }, "rangeController_selectAddedContent": { - "prototype": "core/meta/property-blueprint", + "prototype": "core/meta/property-descriptor", "values": { "name": "selectAddedContent", - "blueprint": { + "objectDescriptor": { "@": "root" }, "valueType": "boolean", @@ -68,10 +68,10 @@ } }, "rangeController_deselectInvisibleContent": { - "prototype": "core/meta/property-blueprint", + "prototype": "core/meta/property-descriptor", "values": { "name": "deselectInvisibleContent", - "blueprint": { + "objectDescriptor": { "@": "root" }, "valueType": "boolean", @@ -79,10 +79,10 @@ } }, "rangeController_clearSelectionOnOrderChange": { - "prototype": "core/meta/property-blueprint", + "prototype": "core/meta/property-descriptor", "values": { "name": "clearSelectionOnOrderChange", - "blueprint": { + "objectDescriptor": { "@": "root" }, "valueType": "boolean", @@ -90,10 +90,10 @@ } }, "rangeController_avoidsEmptySelection": { - "prototype": "core/meta/property-blueprint", + "prototype": "core/meta/property-descriptor", "values": { "name": "avoidsEmptySelection", - "blueprint": { + "objectDescriptor": { "@": "root" }, "valueType": "boolean", @@ -101,10 +101,10 @@ } }, "rangeController_multiSelect": { - "prototype": "core/meta/property-blueprint", + "prototype": "core/meta/property-descriptor", "values": { "name": "multiSelect", - "blueprint": { + "objectDescriptor": { "@": "root" }, "valueType": "boolean", @@ -112,7 +112,7 @@ } }, "root": { - "prototype": "core/meta/module-blueprint", + "prototype": "core/meta/module-object-descriptor", "values": { "name": "RangeController", "customPrototype": false, @@ -183,7 +183,7 @@ ] }, "propertyValidationRules": {}, - "blueprintModule": { + "objectDescriptorModule": { "%": "core/range-controller.meta" }, "exportName": "RangeController", diff --git a/core/serialization/bindings.js b/core/serialization/bindings.js index dca146577a..c8cd6e68f7 100644 --- a/core/serialization/bindings.js +++ b/core/serialization/bindings.js @@ -87,8 +87,14 @@ var deserializeObjectBindings = exports.deserializeObjectBindings = function (de descriptor = bindings[targetPath]; if (typeof descriptor !== "object") { - throw new Error("Binding descriptor must be an object, not " + typeof descriptor); - // TODO isolate the source document and produce a more useful error + if (targetPath.indexOf('.') === -1) { + throw new Error("Binding descriptor must be an object, not " + typeof descriptor); + // TODO isolate the source document and produce a more useful error + } else { + descriptor = { + "=" : "" + descriptor + }; + } } if (ONE_ASSIGNMENT in descriptor) { diff --git a/core/serialization/deserializer/montage-deserializer.js b/core/serialization/deserializer/montage-deserializer.js index 5d1f8319cb..836863a922 100644 --- a/core/serialization/deserializer/montage-deserializer.js +++ b/core/serialization/deserializer/montage-deserializer.js @@ -1,6 +1,7 @@ var Montage = require("../../core").Montage, MontageInterpreter = require("./montage-interpreter").MontageInterpreter, MontageReviver = require("./montage-reviver").MontageReviver, + Map = require("collections/map").Map, deprecate = require("../../deprecate"); var MontageDeserializer = exports.MontageDeserializer = Montage.specialize({ @@ -26,18 +27,23 @@ var MontageDeserializer = exports.MontageDeserializer = Montage.specialize({ }, init: { - value: function (serializationString, _require, objectRequires) { + value: function (serializationString, _require, objectRequires, locationId, moduleContexts) { this._serializationString = serializationString; - this._interpreter = new MontageInterpreter().init(_require, objectRequires); + moduleContexts = moduleContexts || new Map(); + this._interpreter = new MontageInterpreter().init(_require, + new MontageReviver().init(_require, objectRequires, locationId, moduleContexts)); return this; } }, initWithObject: { - value: function (serialization, _require, objectRequires) { + value: function (serialization, _require, objectRequires, locationId, moduleContexts) { this._serializationString = JSON.stringify(serialization); - this._interpreter = new MontageInterpreter().init(_require, objectRequires); + moduleContexts = moduleContexts || new Map(); + this._interpreter = new MontageInterpreter().init(_require, + new MontageReviver().init(_require, objectRequires, locationId, moduleContexts)); + return this; } }, diff --git a/core/serialization/deserializer/montage-interpreter.js b/core/serialization/deserializer/montage-interpreter.js index de214a51e5..82018efcc4 100644 --- a/core/serialization/deserializer/montage-interpreter.js +++ b/core/serialization/deserializer/montage-interpreter.js @@ -10,13 +10,12 @@ var MontageInterpreter = Montage.specialize({ _reviver: {value: null}, init: { - value: function (_require, objectRequires) { + value: function (_require, reviver) { if (typeof _require !== "function") { throw new Error("Function 'require' missing."); } - this._reviver = new MontageReviver() - .init(_require, objectRequires); + this._reviver = reviver; this._require = _require; return this; @@ -248,12 +247,14 @@ var MontageContext = Montage.specialize({ if (values.hasOwnProperty(key)) { value = values[key]; - if (typeof value === "object" && value && + if ((typeof value === "object" && value && Object.keys(value).length === 1 && - (ONE_WAY in value || TWO_WAY in value || ONE_ASSIGNMENT in value)) { + (ONE_WAY in value || TWO_WAY in value || ONE_ASSIGNMENT in value)) || + key.indexOf('.') > -1 + ) { bindings[key] = value; delete values[key]; - } + } } } diff --git a/core/serialization/deserializer/montage-reviver.js b/core/serialization/deserializer/montage-reviver.js index c3e459a8a1..2f0d11c1c8 100644 --- a/core/serialization/deserializer/montage-reviver.js +++ b/core/serialization/deserializer/montage-reviver.js @@ -1,4 +1,4 @@ -/* global console */ +/*global console, Proxy */ var Montage = require("../../core").Montage, ValuesDeserializer = require("./values-deserializer").ValuesDeserializer, SelfDeserializer = require("./self-deserializer").SelfDeserializer, @@ -7,12 +7,17 @@ var Montage = require("../../core").Montage, Alias = require("../alias").Alias, Bindings = require("../bindings"), Promise = require("../../promise").Promise, deprecate = require("../../deprecate"), + camelCaseConverter = require('../../converter/camel-case-converter').singleton, + kebabCaseConverter = require('../../converter/kebab-case-converter').singleton, ONE_ASSIGNMENT = "=", ONE_WAY = "<-", TWO_WAY = "<->"; require("../../shim/string"); +var PROXY_ELEMENT_MAP = new WeakMap(); +var DATA_ATTRIBUTES_MAP = new Map(); + var ModuleLoader = Montage.specialize( { _require: {value: null}, _objectRequires: {value: null}, @@ -93,12 +98,18 @@ var MontageReviver = exports.MontageReviver = Montage.specialize(/** @lends Mont * @param {Object} objectRequires A dictionary indexed by object label with * the require object to use for a specific object of the * serialization. + * @param {?Map} moduleContexts A map indexed by module ID with the + * MontageContext to use for a specific external object + * reference. Used to prevent circular references from creating + * an infinite loop. */ init: { - value: function (_require, objectRequires) { + value: function (_require, objectRequires, locationId, moduleContexts) { this.moduleLoader = new ModuleLoader() .init(_require, objectRequires); this._require = _require; + this._locationId = locationId; + this._moduleContexts = moduleContexts; return this; } }, @@ -139,6 +150,158 @@ var MontageReviver = exports.MontageReviver = Montage.specialize(/** @lends Mont } }, + setProxyForDatasetOnElement: { + value: function (element, montageObjectDesc) { + var originalDataset = element.dataset; + + if (Object.getPrototypeOf(originalDataset) !== null) { + var datasetAttributes = Object.keys(originalDataset), + targetObject = Object.create(null), self = this, + datasetAttribute, propertyNames; + + if (Proxy.prototype) { // The native Proxy has no prototype property. + // Workaround for Proxy polyfill https://github.com/GoogleChrome/proxy-polyfill + // the properties of a proxy must be known at creation time. + // TODO: remove when we drop the support of IE11. + if (montageObjectDesc.values) { + propertyNames = Object.keys(montageObjectDesc.values); + } else { // deprecated + propertyNames = Object.keys(montageObjectDesc.properties) + .concat(Object.keys(montageObjectDesc.bindings)); + } + + datasetAttributes = datasetAttributes.concat( + propertyNames.filter(function (propertyName) { + return propertyName.startsWith("dataset."); + }) + ); + + for (var i = 0, length = datasetAttributes.length; i < length; i++) { + datasetAttribute = datasetAttributes[i]; + if (originalDataset[datasetAttribute]) { + targetObject[datasetAttribute] = + originalDataset[datasetAttribute]; + } else { + targetObject[datasetAttribute.replace(/^dataset\./, '')] = void 0; + } + } + } + + Object.defineProperty(element, "dataset", { + value: new Proxy(targetObject, { + set: function (target, propertyName, value) { + target[propertyName] = value; + originalDataset[propertyName] = value; + element.nativeSetAttribute( + DATA_ATTRIBUTES_MAP.get(propertyName) || + (DATA_ATTRIBUTES_MAP.set( + propertyName, + 'data-' + + kebabCaseConverter.convert(propertyName) + )).get(propertyName), + value + ); + return true; + }, + get: function (target, propertyName) { + return target[propertyName]; + } + }) + }); + } + } + }, + + setProxyOnElement: { + value: function (element, montageObjectDesc) { + if (!PROXY_ELEMENT_MAP.has(element)) { + var targetObject = Object.create(null); + + if (Proxy.prototype) { // The native Proxy has no prototype property. + // Workaround for Proxy polyfill https://github.com/GoogleChrome/proxy-polyfill + // the properties of a proxy must be known at creation time. + // TODO: remove when we drop the support of IE11. + var propertyNames, propertyName; + + for (propertyName in element) { + if (element.hasOwnProperty(propertyName)) { + targetObject[propertyName] = void 0; + } + } + + if (montageObjectDesc.values) { + propertyNames = Object.keys(montageObjectDesc.values); + } else { // deprecated + propertyNames = Object.keys(montageObjectDesc.properties) + .concat(Object.keys(montageObjectDesc.bindings)); + } + + for (var i = 0, length = propertyNames.length; i < length; i++) { + propertyName = propertyNames[i]; + if (!(propertyName in element) && propertyName.indexOf('.') === -1) { + targetObject[propertyName] = void 0; + } + } + } + + PROXY_ELEMENT_MAP.set(element, new Proxy(targetObject, { + set: function (target, propertyName, value) { + if (!(propertyName in Object.getPrototypeOf(element))) { + if (Object.getOwnPropertyDescriptor(element, propertyName) === void 0) { + Object.defineProperty(element, propertyName, { + set: function (value) { + target[propertyName] = value; + + if (value === null || value === void 0) { + element.removeAttribute(propertyName); + } else { + element.nativeSetAttribute(propertyName, value); + } + }, + get: function () { + return target[propertyName]; + } + }); + } + } + + if (target[propertyName] !== value) { + element[propertyName] = value; + } + + return true; + }, + get: function (target, propertyName) { + return target[propertyName] || element[propertyName]; + } + })); + } + + return PROXY_ELEMENT_MAP.get(element); + } + }, + + wrapSetAttributeForElement: { + value: function (element) { + if (element.setAttribute === element.nativeSetAttribute) { + var proxyElement = PROXY_ELEMENT_MAP.get(element), + self = this; + + element.setAttribute = function (key, value) { + var propertyName; + if (key.startsWith('data-')) { + propertyName = camelCaseConverter.convert(key.replace('data-', '')); + proxyElement.dataset[propertyName] = value; + } else { + propertyName = camelCaseConverter.convert(key); + proxyElement[propertyName] = value; + } + element.nativeSetAttribute(key, value); + }; + } + } + }, + reviveRootObject: { value: function (value, context, label) { var error, @@ -170,19 +333,29 @@ var MontageReviver = exports.MontageReviver = Montage.specialize(/** @lends Mont return object; } - var revivedValue = this.reviveValue(value.value, context, label); + var revivedValue = this.reviveValue(value.value, context, label), + valueType = this.getTypeOf(value.value); - if (this.getTypeOf(value.value) === "Element") { + if (valueType === "Element") { if (!Promise.is(revivedValue)) { - var montageObjectDesc = this.reviveObjectLiteral(value, context); - context.setBindingsToDeserialize(revivedValue, montageObjectDesc); + var proxyElement = this.setProxyOnElement(revivedValue, value); + this.setProxyForDatasetOnElement(revivedValue, value); + this.wrapSetAttributeForElement(revivedValue); + context.setBindingsToDeserialize(proxyElement, value); this.deserializeMontageObjectValues( - revivedValue, - montageObjectDesc.values || montageObjectDesc.properties, //deprecated + proxyElement, + value.values || value.properties, //deprecated context ); - context.setUnitsToDeserialize(revivedValue, montageObjectDesc, MontageReviver._unitNames); } + } else if (valueType === "object") { + context.setBindingsToDeserialize(revivedValue, value); + this.deserializeMontageObjectValues( + revivedValue, + value.values || value.properties, //deprecated + context + ); + context.setUnitsToDeserialize(revivedValue, value, MontageReviver._unitNames); } return revivedValue; @@ -288,8 +461,8 @@ var MontageReviver = exports.MontageReviver = Montage.specialize(/** @lends Mont moduleId = value.prototype || value.object, object; - if (moduleId && moduleId.endsWith(".mjson")) { - return this.getMjsonObject(value, module, moduleId) + if (moduleId && (moduleId.endsWith(".mjson") || moduleId.endsWith(".meta"))) { + return this.getMjsonObject(value, module, moduleId, context) .then(function (object) { context.setObjectLabel(object, label); return self.instantiateMjsonObject(value, object, objectName, context, label); @@ -303,17 +476,29 @@ var MontageReviver = exports.MontageReviver = Montage.specialize(/** @lends Mont }, getMjsonObject: { - value: function (serialization, json, moduleId) { - var self = this; - return MontageReviver.getMontageDeserializer().then(function (MontageDeserializer) { - // TODO: MontageDeserializer needs an API to pass in an object - // instead of the stringified version of the object - var deserializer = new MontageDeserializer().init( - JSON.stringify(json), - MontageDeserializer.getModuleRequire(self._require, moduleId) - ); - return deserializer.deserializeObject(); - }).then(function (object) { + value: function (serialization, json, moduleId, context) { + var self = this, + mjsonObjectPromise; + if (moduleId && this._moduleContexts.has(moduleId)) { + // We have a circular reference. If we wanted to forbid circular + // references this is where we would throw an error. + mjsonObjectPromise = Promise.resolve(this._moduleContexts.get(moduleId)._objects.root); + } else { + if (this._locationId && !this._moduleContexts.has(this._locationId)) { + this._moduleContexts.set(this._locationId, context); + } + mjsonObjectPromise = MontageReviver.getMontageDeserializer().then(function (MontageDeserializer) { + var deserializer = new MontageDeserializer().initWithObject( + json, + MontageDeserializer.getModuleRequire(self._require, moduleId), + void 0, + moduleId, + self._moduleContexts + ); + return deserializer.deserializeObject(); + }); + } + return mjsonObjectPromise.then(function (object) { if ("prototype" in serialization) { return Object.create(object); } else { @@ -645,6 +830,11 @@ var MontageReviver = exports.MontageReviver = Montage.specialize(/** @lends Mont for (var propertyName in value) { if (value.hasOwnProperty(propertyName)) { + if (value[propertyName] === value) { + // catch object property that point to its parent + return value; + } + item = this.reviveValue(value[propertyName], context); if (Promise.is(item)) { @@ -881,6 +1071,11 @@ var MontageReviver = exports.MontageReviver = Montage.specialize(/** @lends Mont }); +MontageReviver.findProxyForElement = function (element) { + return PROXY_ELEMENT_MAP.get(element); +}; + if (typeof exports !== "undefined") { + exports.MontageReviver = MontageReviver; } diff --git a/core/template.js b/core/template.js index 859ec5bd59..8514053056 100644 --- a/core/template.js +++ b/core/template.js @@ -304,19 +304,19 @@ var Template = Montage.specialize( /** @lends Template# */ { return this._instantiateObjects(templateObjects, fragment) .then(function (objects) { - var resources; + var resources = self.getResources(); - part.objects = objects; - self._invokeDelegates(part, instances); - part.stopActingAsTopComponent(); - - resources = self.getResources(); if (!resources.resourcesLoaded() && resources.hasResources()) { // Start preloading the resources as soon as possible, no // need to wait for them as the draw cycle will take care // of that when loading the stylesheets into the document. resources.loadResources(targetDocument); } + + part.objects = objects; + self._invokeDelegates(part, instances); + part.stopActingAsTopComponent(); + return part; }); } diff --git a/core/tree-controller.meta b/core/tree-controller.meta index b2a5903da1..d81d0f9fa0 100644 --- a/core/tree-controller.meta +++ b/core/tree-controller.meta @@ -1,9 +1,9 @@ { "treeController_content": { - "prototype": "core/meta/property-blueprint", + "prototype": "core/meta/property-descriptor", "values": { "name": "content", - "blueprint": { + "objectDescriptor": { "@": "root" }, "cardinality": -1, @@ -12,10 +12,10 @@ } }, "treeController_childrenPath": { - "prototype": "core/meta/property-blueprint", + "prototype": "core/meta/property-descriptor", "values": { "name": "childrenPath", - "blueprint": { + "objectDescriptor": { "@": "root" }, "valueType": "string", @@ -23,10 +23,10 @@ } }, "treeController_initiallyExpanded": { - "prototype": "core/meta/property-blueprint", + "prototype": "core/meta/property-descriptor", "values": { "name": "initiallyExpanded", - "blueprint": { + "objectDescriptor": { "@": "root" }, "valueType": "boolean", @@ -34,10 +34,10 @@ } }, "treeController_noneExpanded": { - "prototype": "core/meta/property-blueprint", + "prototype": "core/meta/property-descriptor", "values": { "name": "noneExpanded", - "blueprint": { + "objectDescriptor": { "@": "root" }, "valueType": "boolean", @@ -45,10 +45,10 @@ } }, "treeController_allExpanded": { - "prototype": "core/meta/property-blueprint", + "prototype": "core/meta/property-descriptor", "values": { "name": "allExpanded", - "blueprint": { + "objectDescriptor": { "@": "root" }, "valueType": "boolean", @@ -56,10 +56,10 @@ } }, "treeController_root": { - "prototype": "core/meta/property-blueprint", + "prototype": "core/meta/property-descriptor", "values": { "name": "root", - "blueprint": { + "objectDescriptor": { "@": "root" }, "valueType": "object", @@ -69,7 +69,7 @@ } }, "root": { - "prototype": "core/meta/module-blueprint", + "prototype": "core/meta/module-object-descriptor", "values": { "name": "TreeController", "customPrototype": false, @@ -116,7 +116,7 @@ ] }, "propertyValidationRules": {}, - "blueprintModule": { + "objectDescriptorModule": { "%": "core/tree-controller.meta" }, "exportName": "TreeController", @@ -126,10 +126,10 @@ } }, "treeControllerNode_content": { - "prototype": "core/meta/property-blueprint", + "prototype": "core/meta/property-descriptor", "values": { "name": "content", - "blueprint": { + "objectDescriptor": { "@": "root" }, "cardinality": -1, @@ -138,10 +138,10 @@ } }, "treeControllerNode_expanded": { - "prototype": "core/meta/property-blueprint", + "prototype": "core/meta/property-descriptor", "values": { "name": "expanded", - "blueprint": { + "objectDescriptor": { "@": "treeControllerNode" }, "valueType": "boolean", @@ -149,10 +149,10 @@ } }, "treeControllerNode_depth": { - "prototype": "core/meta/property-blueprint", + "prototype": "core/meta/property-descriptor", "values": { "name": "depth", - "blueprint": { + "objectDescriptor": { "@": "treeControllerNode" }, "valueType": "number", @@ -160,10 +160,10 @@ } }, "treeControllerNode_index": { - "prototype": "core/meta/property-blueprint", + "prototype": "core/meta/property-descriptor", "values": { "name": "index", - "blueprint": { + "objectDescriptor": { "@": "treeControllerNode" }, "valueType": "number", @@ -171,10 +171,10 @@ } }, "treeControllerNode_isFinal": { - "prototype": "core/meta/property-blueprint", + "prototype": "core/meta/property-descriptor", "values": { "name": "isFinal", - "blueprint": { + "objectDescriptor": { "@": "treeControllerNode" }, "valueType": "boolean", @@ -182,10 +182,10 @@ } }, "treeControllerNode_parent": { - "prototype": "core/meta/property-blueprint", + "prototype": "core/meta/property-descriptor", "values": { "name": "parent", - "blueprint": { + "objectDescriptor": { "@": "treeControllerNode" }, "valueType": "object", @@ -195,10 +195,10 @@ } }, "treeControllerNode_children": { - "prototype": "core/meta/property-blueprint", + "prototype": "core/meta/property-descriptor", "values": { "name": "children", - "blueprint": { + "objectDescriptor": { "@": "treeControllerNode" }, "cardinality": -1, @@ -209,10 +209,10 @@ } }, "treeControllerNode_junctions": { - "prototype": "core/meta/property-blueprint", + "prototype": "core/meta/property-descriptor", "values": { "name": "junctions", - "blueprint": { + "objectDescriptor": { "@": "treeControllerNode" }, "valueType": "object", @@ -220,10 +220,10 @@ } }, "treeControllerNode": { - "prototype": "core/meta/blueprint", + "prototype": "core/meta/object-descriptor", "values": { "name": "TreeControllerNode", - "blueprintModuleId": "core/tree-controller.meta", + "objectDescriptorModuleId": "core/tree-controller.meta", "prototypeName": "TreeControllerNode", "customPrototype": false, "propertyDescriptors": [ diff --git a/core/websocket.js b/core/websocket.js index 7e3c652ec1..ba5585d7a0 100644 --- a/core/websocket.js +++ b/core/websocket.js @@ -22,7 +22,6 @@ exports.WebSocket = Target.specialize({ this._protocols = protocols; this._messageQueue = []; this._webSocket = null; - this._isMessagePending = false; this._isReconnecting = false; this._connect(); return this; @@ -41,47 +40,48 @@ exports.WebSocket = Target.specialize({ _webSocket: { value: undefined }, - _isMessagePending: { - value: undefined - }, reconnectionInterval: { value: 100 }, + _connect: { value: function () { - this._webSocket = new _WebSocket(this._url,this._protocols); - this._webSocket.addEventListener("error", this, false); - this._webSocket.addEventListener("open", this, false); + this._webSocket = new _WebSocket(this._url, this._protocols); + this._webSocket.addEventListener("error", this, false); + this._webSocket.addEventListener("open", this, false); } }, + send: { value: function send(data) { this._messageQueue.push(data); this._sendNextMessage(); } }, + _sendNextMessage: { value: function () { - if (!this._isMessagePending && this._messageQueue.length) { - if (this._webSocket) { - this._isMessagePending = true; - if ((this._webSocket.readyState !== exports.WebSocket.CLOSING) && (this._webSocket.readyState !== exports.WebSocket.CLOSED)) { + if (this._messageQueue.length) { + switch (this.readyState) { + case WebSocket.CONNECTING: + break; + case WebSocket.CLOSING: + case WebSocket.CLOSED: + this._reconnect(); + break; + case WebSocket.OPEN: try { this._webSocket.send(this._messageQueue[0]); + this._messageQueue.shift(); } catch (e) { - this._isMessagePending = false; this._reconnect(); } - } else { - this._isMessagePending = false; - this._reconnect(); - } - } else { - this._reconnect(); + break; } } } }, + _reconnect: { value: function () { var self; @@ -90,7 +90,6 @@ exports.WebSocket = Target.specialize({ if (!this._isReconnecting) { self = this; this._webSocket = null; - this._isMessagePending = false; this._isReconnecting = true; setTimeout(function () { self._connect(); @@ -117,8 +116,6 @@ exports.WebSocket = Target.specialize({ this._sendNextMessage(); break; case "message": - this._isMessagePending = false; - this._messageQueue.shift(); this.dispatchEvent(event); this._sendNextMessage(); break; @@ -161,7 +158,7 @@ exports.WebSocket = Target.specialize({ }, readyState: { get: function () { - return this._webSocket.readyState; + return this._webSocket ? this._webSocket.readyState : WebSocket.CLOSED; } }, diff --git a/montage.js b/montage.js index 92cdd26d41..6ffd8d3392 100644 --- a/montage.js +++ b/montage.js @@ -1,4 +1,4 @@ -/* global define, exports, require, process, window, document, bootstrap*/ +/* global define, exports, require, process, window, document, bootstrap, Reflect, customElements*/ (function (root, factory) { if (typeof bootstrap === 'function') { // Montage. Register module. @@ -442,6 +442,212 @@ return platform.loadPackage(dependency, config, packageDescription); }; + exports.initMontageCustomElement = function () { + if (typeof window.customElements === 'undefined' || typeof window.Reflect === 'undefined') { + return void 0; + } + + function makeCustomElementConstructor(superConstructor) { + var constructor = function () { + return Reflect.construct( + HTMLElement, [], constructor + ); + }; + Object.setPrototypeOf( + constructor.prototype, (superConstructor || HTMLElement).prototype + ); + Object.setPrototypeOf(constructor, superConstructor || HTMLElement); + return constructor; + } + + var MontageElement = makeCustomElementConstructor(); + + function defineMontageElement(name, options) { + if (!customElements.get(name)) { + var customElementConstructor = makeCustomElementConstructor(MontageElement); + customElementConstructor.componentConstructor = options.constructor; + customElementConstructor.observedAttributes = options.observedAttributes; + customElements.define(name, customElementConstructor); + } + } + + MontageElement.pendingCustomElements = new Map(); + + MontageElement.define = function (name, constructor, options) { + if (options && typeof options === 'object') { + options.constructor = constructor; + } else { + options = { constructor: constructor }; + } + + if (this.require) { + defineMontageElement(name, options); + } else { + this.pendingCustomElements.set(name, options); + } + }; + + MontageElement.ready = function (require, application, reviver) { + MontageElement.prototype.findProxyForElement = reviver.findProxyForElement; + this.application = application; + this.require = require; + + this.pendingCustomElements.forEach(function (constructor, name) { + defineMontageElement(name, constructor); + }); + + this.pendingCustomElements.clear(); + }; + + Object.defineProperties(MontageElement.prototype, { + + require: { + get: function () { + return MontageElement.require; + }, + configurable: false + }, + + application: { + get: function () { + return MontageElement.application; + }, + configurable: false + }, + + componentConstructor: { + get: function () { + return this.constructor.componentConstructor; + }, + configurable: false + }, + + observedAttributes: { + get: function () { + return this.constructor.observedAttributes; + }, + configurable: false + } + }); + + MontageElement.prototype.connectedCallback = function () { + if (!this._instance) { + var self = this, + component = this.instantiateComponent(); + + return this.findParentComponent().then(function (parentComponent) { + self._instance = component; + parentComponent.addChildComponent(component); + component._canDrawOutsideDocument = true; + component.needsDraw = true; + }); + } + }; + + MontageElement.prototype.disconnectedCallback = function () { + //TODO + }; + + MontageElement.prototype.findParentComponent = function () { + var eventManager = this.application.eventManager, + anElement = this, + parentComponent, + aParentNode, + candidate; + + while ((aParentNode = anElement.parentNode) !== null && + !(candidate = eventManager.eventHandlerForElement(aParentNode))) { + anElement = aParentNode; + } + + return Promise.resolve(candidate) || this.getRootComponent(); + }; + + MontageElement.prototype.getRootComponent = function () { + if (!MontageElement.rootComponentPromise) { + MontageElement.rootComponentPromise = this.require.async("montage/ui/component") + .then(function (exports) { + return exports.__root__; + }); + } + + return MontageElement.rootComponentPromise; + }; + + MontageElement.prototype.instantiateComponent = function () { + var component = new this.componentConstructor(); + this.bootstrapComponent(component); + component.element = document.createElement("div"); + return component; + }; + + MontageElement.prototype.bootstrapComponent = function (component) { + var shadowRoot = this.attachShadow({ mode: 'open' }), + mainEnterDocument = component.enterDocument, + mainTemplateDidLoad = component.templateDidLoad, + proxyElement = this.findProxyForElement(this); + + if (proxyElement) { + var observedAttributes = this.observedAttributes, + observedAttribute, + self = this, + length; + + if (observedAttributes && (length = observedAttributes.length)) { + for (var i = 0; i < length; i++) { + observedAttribute = observedAttributes[i]; + component.defineBinding(observedAttribute, { + "<->": "" + observedAttribute, source: proxyElement + }); + } + } + } + + this.application.eventManager.registerTargetForActivation(shadowRoot); + + component.templateDidLoad = function () { + var resources = component.getResources(); + + if (resources) { + self.injectResourcesWithinCustomElement( + resources.styles, + shadowRoot + ); + + self.injectResourcesWithinCustomElement( + resources.scripts, + shadowRoot + ); + } + + this.templateDidLoad = mainTemplateDidLoad; + + if (typeof this.templateDidLoad === "function") { + this.templateDidLoad(); + } + }; + + component.enterDocument = function (firstTime) { + shadowRoot.appendChild(this.element); + this.enterDocument = mainEnterDocument; + + if (typeof this.enterDocument === "function") { + this.enterDocument(firstTime); + } + }; + }; + + MontageElement.prototype.injectResourcesWithinCustomElement = function (resources, shadowRoot) { + if (resources && resources.length) { + for (var i = 0, length = resources.length; i < length; i++) { + shadowRoot.appendChild(resources[i]); + } + } + }; + + global.MontageElement = MontageElement; + }; + /** * Initializes Montage and creates the application singleton if * necessary. @@ -690,6 +896,7 @@ } else { global.__MONTAGE_LOADED__ = true; exports.initMontage(); + exports.initMontageCustomElement(); } } else { // may cause additional exports to be injected: diff --git a/package.json b/package.json index 562d1b4cd0..ed70ea0597 100644 --- a/package.json +++ b/package.json @@ -54,7 +54,12 @@ "htmlparser2": "~3.0.5", "jshint": "^2.9.5", "mr": "montagejs/mr#commonjs", - "q-io": "^1.13.3" + "q-io": "^1.13.3", + "lodash.kebabcase": "^4.1.1", + "lodash.camelcase": "^4.3.0", + "lodash.trim": "^4.5.1", + "lodash.snakecase": "^4.1.1", + "proxy-polyfill": "~0.1.7" }, "devDependencies": { "concurrently": "^3.4.0", @@ -86,7 +91,7 @@ "test:karma-chrome": "karma start --no-auto-watch --single-run --browsers=Chrome", "test:karma-debug": "karma start --auto-watch --no-single-run --browsers=PhantomJS_debug", "test:karma-dev": "karma start --auto-watch --no-single-run --capture", - "test:jasmine": "concurrently \"http-server -a localhost -p 8085\" \"open http://localhost:8085/test/run.html\"" + "test:jasmine": "concurrently \"http-server -p 8085\" \"open http://localhost:8085/test/run.html\"" }, "exclude": [ "report", diff --git a/test/all.js b/test/all.js index 63547f1f63..4046180a29 100644 --- a/test/all.js +++ b/test/all.js @@ -18,7 +18,8 @@ module.exports = require("montage-testing").run(require, [ "spec/bindings/converter-spec", "spec/bindings/self-spec", {name: "spec/document-resources-spec", node: false}, - {name: "spec/claimed-pointer-spec", node: false}, + { name: "spec/claimed-pointer-spec", node: false }, + { name: "spec/montage-custom-element-spec", node: false }, // Core "spec/core/browser-spec", "spec/core/core-spec", @@ -81,7 +82,7 @@ module.exports = require("montage-testing").run(require, [ {name: "spec/serialization/montage-serializer-spec"}, {name: "spec/serialization/montage-serializer-element-spec", node: false}, {name: "spec/serialization/montage-deserializer-spec"}, - {name: "spec/serialization/montage-deserializer-element-spec", node: false}, + { name: "spec/serialization/montage-deserializer-element-spec", node: false, karma: false}, // Trigger {name: "spec/trigger/trigger-spec", node: false}, // UI @@ -94,7 +95,7 @@ module.exports = require("montage-testing").run(require, [ {name: "spec/ui/modal-overlay-spec", node: false}, {name: "spec/ui/overlay-spec", node: false}, {name: "spec/ui/slot-spec", node: false}, - {name: "spec/ui/substitution-spec", node: false}, + {name: "spec/ui/substitution-spec", node: false}, {name: "spec/ui/text-input-spec", node: false}, {name: "spec/ui/slider-spec", node: false}, {name: "spec/ui/text/text-spec", node: false}, @@ -105,19 +106,19 @@ module.exports = require("montage-testing").run(require, [ // Reel {name: "spec/reel/template-spec", node: false, karma: true}, // UI - repetition - {name: "spec/ui/repetition-spec", node: false}, + { name: "spec/ui/repetition-spec", node: false, karma: false}, {name: "spec/ui/repetition-selection-spec", node: false, karma: false}, {name: "spec/ui/repetition-binding-spec", node: false}, {name: "spec/core/localizer-spec", node: false, karma: false}, {name: "spec/core/localizer/serialization-spec", node: false, karma: false}, - // Bluerint - {name: "spec/meta/converter-blueprint-spec", karma: false}, - {name: "spec/meta/module-blueprint-spec", karma: false}, - {name: "spec/meta/build-in-component-blueprint-spec", node: false, karma: false}, - {name: "spec/meta/component-blueprint-spec", node: false}, - {name: "spec/meta/controller-blueprint-spec", node: false}, - {name: "spec/meta/event-blueprint-spec", node: false}, - {name: "spec/meta/blueprint-spec"} + // Meta + {name: "spec/meta/converter-object-descriptor-spec", karma: false}, + {name: "spec/meta/module-object-descriptor-spec", karma: false}, + {name: "spec/meta/build-in-component-object-descriptor-spec", node: false, karma: false}, + {name: "spec/meta/component-object-descriptor-spec", node: false}, + {name: "spec/meta/controller-object-descriptor-spec", node: false}, + {name: "spec/meta/event-descriptor-spec", node: false}, + {name: "spec/meta/object-descriptor-spec"} ]).then(function () { console.log('montage-testing', 'End'); }, function (err) { diff --git a/test/spec/base/abstract-alert-spec.js b/test/spec/base/abstract-alert-spec.js index e3a734ef07..bd7a1bbdd5 100644 --- a/test/spec/base/abstract-alert-spec.js +++ b/test/spec/base/abstract-alert-spec.js @@ -229,11 +229,11 @@ describe("test/base/abstract-alert-spec", function () { }); }); - describe("blueprint", function () { + describe("objectDescriptor", function () { it("can be created", function (done) { - var blueprintPromise = AbstractAlert.blueprint || AbstractAlert.objectDescriptor; - blueprintPromise.then(function (blueprint) { - expect(blueprint).not.toBeNull(); + var objectDescriptorPromise = AbstractAlert.objectDescriptor || AbstractAlert.objectDescriptor; + objectDescriptorPromise.then(function (objectDescriptor) { + expect(objectDescriptor).not.toBeNull(); }, function (err) { fail(err); }).finally(function () { diff --git a/test/spec/base/abstract-button-spec.js b/test/spec/base/abstract-button-spec.js index bffaefda14..694114d9d9 100644 --- a/test/spec/base/abstract-button-spec.js +++ b/test/spec/base/abstract-button-spec.js @@ -233,11 +233,11 @@ describe("test/base/abstract-button-spec", function () { }); }); }); - describe("blueprint", function () { + describe("objectDescriptor", function () { it("can be created", function (done) { - var blueprintPromise = AbstractButton.blueprint; - blueprintPromise.then(function (blueprint) { - expect(blueprint).not.toBeNull(); + var objectDescriptorPromise = AbstractButton.objectDescriptor; + objectDescriptorPromise.then(function (objectDescriptor) { + expect(objectDescriptor).not.toBeNull(); }, function (err) { fail(err); }).finally(function () { diff --git a/test/spec/base/abstract-checkbox-spec.js b/test/spec/base/abstract-checkbox-spec.js index c695ca73eb..e216bfeb94 100644 --- a/test/spec/base/abstract-checkbox-spec.js +++ b/test/spec/base/abstract-checkbox-spec.js @@ -272,11 +272,11 @@ describe("test/base/abstract-checkbox-spec", function () { expect(aCheckbox.element.getAttribute("aria-checked")).toBe("false"); }); }); - describe("blueprint", function () { + describe("objectDescriptor", function () { it("can be created", function (done) { - var blueprintPromise = AbstractCheckbox.blueprint; - blueprintPromise.then(function (blueprint) { - expect(blueprint).not.toBeNull(); + var objectDescriptorPromise = AbstractCheckbox.objectDescriptor; + objectDescriptorPromise.then(function (objectDescriptor) { + expect(objectDescriptor).not.toBeNull(); }, function (err) { fail(err); }).finally(function () { diff --git a/test/spec/base/abstract-confirm-spec.js b/test/spec/base/abstract-confirm-spec.js index cbe8a1e701..4e433d667d 100644 --- a/test/spec/base/abstract-confirm-spec.js +++ b/test/spec/base/abstract-confirm-spec.js @@ -262,11 +262,11 @@ describe("test/base/abstract-confirm-spec", function () { }); }); - describe("blueprint", function () { + describe("objectDescriptor", function () { it("can be created", function (done) { - var blueprintPromise = AbstractConfirm.blueprint; - blueprintPromise.then(function (blueprint) { - expect(blueprint).not.toBeNull(); + var objectDescriptorPromise = AbstractConfirm.objectDescriptor; + objectDescriptorPromise.then(function (objectDescriptor) { + expect(objectDescriptor).not.toBeNull(); }).finally(function () { done(); }) diff --git a/test/spec/base/abstract-image-spec.js b/test/spec/base/abstract-image-spec.js index de8f3e35e8..a8a0af8c92 100644 --- a/test/spec/base/abstract-image-spec.js +++ b/test/spec/base/abstract-image-spec.js @@ -362,11 +362,11 @@ describe("test/base/abstract-image-spec", function () { }); }); - describe("blueprint", function () { + describe("objectDescriptor", function () { it("can be created", function (done) { - var blueprintPromise = AbstractImage.blueprint; - blueprintPromise.then(function (blueprint) { - expect(blueprint).not.toBeNull(); + var objectDescriptorPromise = AbstractImage.objectDescriptor; + objectDescriptorPromise.then(function (objectDescriptor) { + expect(objectDescriptor).not.toBeNull(); }, function (err) { fail(err); }).finally(function () { diff --git a/test/spec/base/abstract-link-spec.js b/test/spec/base/abstract-link-spec.js index cf2e172b58..723c38caf2 100644 --- a/test/spec/base/abstract-link-spec.js +++ b/test/spec/base/abstract-link-spec.js @@ -223,11 +223,11 @@ describe("test/base/abstract-link-spec", function () { }); }); }); - describe("blueprint", function () { + describe("objectDescriptor", function () { it("can be created", function (done) { - var blueprintPromise = AbstractLink.blueprint; - blueprintPromise.then(function (blueprint) { - expect(blueprint).not.toBeNull(); + var objectDescriptorPromise = AbstractLink.objectDescriptor; + objectDescriptorPromise.then(function (objectDescriptor) { + expect(objectDescriptor).not.toBeNull(); }, function (err) { fail(err); }).finally(function () { diff --git a/test/spec/base/abstract-number-field-spec.js b/test/spec/base/abstract-number-field-spec.js index d14f8c8966..56bd5024c1 100644 --- a/test/spec/base/abstract-number-field-spec.js +++ b/test/spec/base/abstract-number-field-spec.js @@ -443,11 +443,11 @@ describe("test/base/abstract-number-field-spec", function () { }); }); }); - describe("blueprint", function () { + describe("objectDescriptor", function () { it("can be created", function (done) { - var blueprintPromise = AbstractNumberField.blueprint; - blueprintPromise.then(function (blueprint) { - expect(blueprint).not.toBeNull(); + var objectDescriptorPromise = AbstractNumberField.objectDescriptor; + objectDescriptorPromise.then(function (objectDescriptor) { + expect(objectDescriptor).not.toBeNull(); }, function (err) { fail(err); }).finally(function () { diff --git a/test/spec/base/abstract-radio-button-spec.js b/test/spec/base/abstract-radio-button-spec.js index 5ee1cd7cff..efb3989b74 100644 --- a/test/spec/base/abstract-radio-button-spec.js +++ b/test/spec/base/abstract-radio-button-spec.js @@ -268,11 +268,11 @@ describe("test/base/abstract-radio-button-spec", function () { expect(aRadioButton.element.getAttribute("aria-checked")).toBe("false"); }); }); - describe("blueprint", function () { + describe("objectDescriptor", function () { it("can be created", function (done) { - var blueprintPromise = AbstractRadioButton.blueprint; - blueprintPromise.then(function (blueprint) { - expect(blueprint).not.toBeNull(); + var objectDescriptorPromise = AbstractRadioButton.objectDescriptor; + objectDescriptorPromise.then(function (objectDescriptor) { + expect(objectDescriptor).not.toBeNull(); }, function (err) { fail(err); }).finally(function () { diff --git a/test/spec/base/abstract-select-spec.js b/test/spec/base/abstract-select-spec.js index b2bc8a3fa1..ce5d160db2 100644 --- a/test/spec/base/abstract-select-spec.js +++ b/test/spec/base/abstract-select-spec.js @@ -386,11 +386,11 @@ describe("test/base/abstract-select-spec", function () { }); }); - describe("blueprint", function () { + describe("objectDescriptor", function () { it("can be created", function (done) { - var blueprintPromise = AbstractSelect.blueprint; - blueprintPromise.then(function (blueprint) { - expect(blueprint).not.toBeNull(); + var objectDescriptorPromise = AbstractSelect.objectDescriptor; + objectDescriptorPromise.then(function (objectDescriptor) { + expect(objectDescriptor).not.toBeNull(); }, function (err) { fail(err); }).finally(function () { diff --git a/test/spec/base/abstract-slider-spec.js b/test/spec/base/abstract-slider-spec.js index 6f3b45eb0f..568d48a177 100644 --- a/test/spec/base/abstract-slider-spec.js +++ b/test/spec/base/abstract-slider-spec.js @@ -383,11 +383,11 @@ describe("test/base/abstract-slider-spec", function () { }); }); }); - describe("blueprint", function () { + describe("objectDescriptor", function () { it("can be created", function (done) { - var blueprintPromise = AbstractSlider.blueprint; - blueprintPromise.then(function (blueprint) { - expect(blueprint).not.toBeNull(); + var objectDescriptorPromise = AbstractSlider.objectDescriptor; + objectDescriptorPromise.then(function (objectDescriptor) { + expect(objectDescriptor).not.toBeNull(); }, function (err) { fail(err); }).finally(function () { diff --git a/test/spec/base/abstract-text-area-spec.js b/test/spec/base/abstract-text-area-spec.js index a8d53ebd6e..e5c16b1d78 100644 --- a/test/spec/base/abstract-text-area-spec.js +++ b/test/spec/base/abstract-text-area-spec.js @@ -178,11 +178,11 @@ describe("test/base/abstract-text-area-spec", function () { expect(aTextArea.element.hasEventListener("change", aTextArea)).toBe(true); }); }); - describe("blueprint", function () { + describe("objectDescriptor", function () { it("can be created", function (done) { - var blueprintPromise = AbstractTextArea.blueprint; - blueprintPromise.then(function (blueprint) { - expect(blueprint).not.toBeNull(); + var objectDescriptorPromise = AbstractTextArea.objectDescriptor; + objectDescriptorPromise.then(function (objectDescriptor) { + expect(objectDescriptor).not.toBeNull(); }).finally(function () { done(); }); diff --git a/test/spec/base/abstract-text-field-spec.js b/test/spec/base/abstract-text-field-spec.js index c1df1872d7..808229a44c 100644 --- a/test/spec/base/abstract-text-field-spec.js +++ b/test/spec/base/abstract-text-field-spec.js @@ -367,11 +367,11 @@ describe("test/base/abstract-text-field-spec", function () { }); }); }); - describe("blueprint", function () { + describe("objectDescriptor", function () { it("can be created", function (done) { - var blueprintPromise = AbstractTextField.blueprint; - blueprintPromise.then(function (blueprint) { - expect(blueprint).not.toBeNull(); + var objectDescriptorPromise = AbstractTextField.objectDescriptor; + objectDescriptorPromise.then(function (objectDescriptor) { + expect(objectDescriptor).not.toBeNull(); }, function (err) { fail(err); }).finally(function () { diff --git a/test/spec/base/abstract-toggle-button-spec.js b/test/spec/base/abstract-toggle-button-spec.js index 1b47a80d6d..34d7303fa8 100644 --- a/test/spec/base/abstract-toggle-button-spec.js +++ b/test/spec/base/abstract-toggle-button-spec.js @@ -302,11 +302,11 @@ describe("test/base/abstract-toggle-button-spec", function () { }); }); }); - describe("blueprint", function () { + describe("objectDescriptor", function () { it("can be created", function (done) { - var blueprintPromise = AbstractToggleButton.blueprint; - blueprintPromise.then(function (blueprint) { - expect(blueprint).not.toBeNull(); + var objectDescriptorPromise = AbstractToggleButton.objectDescriptor; + objectDescriptorPromise.then(function (objectDescriptor) { + expect(objectDescriptor).not.toBeNull(); }, function (err) { fail(err); }).finally(function () { diff --git a/test/spec/base/abstract-toggle-switch-spec.js b/test/spec/base/abstract-toggle-switch-spec.js index f5384bae17..d394c7c5d6 100644 --- a/test/spec/base/abstract-toggle-switch-spec.js +++ b/test/spec/base/abstract-toggle-switch-spec.js @@ -65,11 +65,11 @@ describe("test/base/abstract-toggle-switch-spec", function () { }); }); - describe("blueprint", function () { + describe("objectDescriptor", function () { it("can be created", function (done) { - var blueprintPromise = AbstractToggleSwitch.blueprint; - blueprintPromise.then(function (blueprint) { - expect(blueprint).not.toBeNull(); + var objectDescriptorPromise = AbstractToggleSwitch.objectDescriptor; + objectDescriptorPromise.then(function (objectDescriptor) { + expect(objectDescriptor).not.toBeNull(); }, function (err) { fail(err); }).finally(function () { diff --git a/test/spec/converter-spec.js b/test/spec/converter-spec.js index cb4a8a9e79..637010f1a2 100644 --- a/test/spec/converter-spec.js +++ b/test/spec/converter-spec.js @@ -30,13 +30,19 @@ POSSIBILITY OF SUCH DAMAGE. */ var Montage = require("montage").Montage; var Converter= require("montage/core/converter/converter").Converter, -UpperCaseConverter = require("montage/core/converter/upper-case-converter").UpperCaseConverter, -LowerCaseConverter = require("montage/core/converter/lower-case-converter").LowerCaseConverter, -TrimConverter = require("montage/core/converter/trim-converter").TrimConverter, +UpperCaseConverter = require("montage/core/converter/upper-case-converter").singleton, +LowerCaseConverter = require("montage/core/converter/lower-case-converter").singleton, +TrimConverter = require("montage/core/converter/trim-converter").singleton, NumberConverter = require("montage/core/converter/number-converter").NumberConverter, BytesConverter = require("montage/core/converter/bytes-converter").BytesConverter, +InvertConverterModule = require("montage/core/converter/invert-converter"), +InvertConverter = InvertConverterModule.InvertConverter, +InvertConverterSingleton = InvertConverterModule.singleton, DateConverter = require("montage/core/converter/date-converter").DateConverter, ExpressionConverter = require("montage/core/converter/expression-converter").ExpressionConverter, +CamelCaseConverter = require("montage/core/converter/camel-case-converter").singleton, +SnakeCaseConverter = require("montage/core/converter/snake-case-converter").singleton, +KebabCaseConverter = require("montage/core/converter/kebab-case-converter").singleton, CurrencyConverter = require("montage/core/converter/currency-converter").CurrencyConverter; describe("converter-spec", function () { @@ -46,11 +52,10 @@ describe("converter-spec", function () { date = new Date('25 Aug 2011 12:00:00 PM'); beforeEach(function () { - //stringConverter = new StringConverter(); - ucaseConverter = new UpperCaseConverter(); - lcaseConverter = new LowerCaseConverter(); - trimConverter = new TrimConverter(); - + ucaseConverter = UpperCaseConverter; + lcaseConverter = LowerCaseConverter; + trimConverter = TrimConverter; + invertConverter = InvertConverterSingleton; numberConverter = new NumberConverter(); numberConverter.shorten = true; bytesConverter = new BytesConverter(); @@ -62,39 +67,57 @@ describe("converter-spec", function () { expressionConverter = new ExpressionConverter(); expressionConverter.convertExpression = "map{foo}"; expressionConverter.revertExpression = "map{{foo:this}}"; - //dateConverter.pattern = 'YYYY-MM-DD'; + + camelCaseConverter = CamelCaseConverter; + snakeCaseConverter = SnakeCaseConverter; + kebabCaseConverter = KebabCaseConverter; }); describe("test string formatters", function () { it("should format a string to uppercase", function () { var value = "hello world"; - //stringConverter.fn = "uppercase"; var result = ucaseConverter.convert(value); expect(result).toBe('HELLO WORLD'); }); it("should format a string to lowercase", function () { var value = "HELLO World"; - //stringConverter.fn = "lowercase"; var result = lcaseConverter.convert(value); expect(result).toBe('hello world'); }); it("should format a string by trimming it", function () { var value = " hello world "; - //stringConverter.fn = "trim"; var result = trimConverter.convert(value); expect(result).toBe('hello world'); }); - /* - it("should format a string by converting newline characters to
", function () { - var value = " hello \r\n world "; - stringConverter.fn = "trim"; - var result = stringConverter.convert(value); - expect(result).toBe('hello
world'); + it("should inverts value", function () { + expect(invertConverter.convert(true)).toBe(false); + expect(invertConverter.convert(0)).toBe(true); + }); + + it("should converts string to camel case", function () { + expect(camelCaseConverter.convert('hello world')).toBe('helloWorld'); + expect(camelCaseConverter.convert('HELLO WORLD')).toBe('helloWorld'); + expect(camelCaseConverter.convert('hello-world')).toBe('helloWorld'); + }); + + it("should converts string to snake case", function () { + expect(snakeCaseConverter.convert('hello world')).toBe('hello_world'); + expect(snakeCaseConverter.convert('HELLO WORLD')).toBe('hello_world'); + expect(snakeCaseConverter.convert('hello-world')).toBe('hello_world'); + }); + + it("should converts string to kebab case", function () { + expect(kebabCaseConverter.convert('hello world')).toBe('hello-world'); + expect(kebabCaseConverter.convert('HELLO WORLD')).toBe('hello-world'); + expect(kebabCaseConverter.convert('hello_world')).toBe('hello-world'); + }); + + it("should be a singleton", function () { + expect(invertConverter === new InvertConverter()).toBe(true); }); - */ }); diff --git a/test/spec/custom-elements/custom-elements-test.js b/test/spec/custom-elements/custom-elements-test.js new file mode 100644 index 0000000000..b3a0ba639f --- /dev/null +++ b/test/spec/custom-elements/custom-elements-test.js @@ -0,0 +1,14 @@ + +var querySelector = function (e) { return document.querySelector(e); } + +var Montage = require("montage").Montage; +var Component = require("montage/ui/component").Component; +var Application = require("montage/core/application").application; +var MontageText = require("montage/ui/text.reel").Text; +var MyButton = require("spec/custom-elements/my-button.reel").MyButton; + +var CustomElementTest = exports.CustomElementTest = Montage.specialize({ + textLabel2: { + value: 'textLabel2' + } +}); diff --git a/test/spec/custom-elements/custom-elements.html b/test/spec/custom-elements/custom-elements.html new file mode 100644 index 0000000000..a7eca0e4da --- /dev/null +++ b/test/spec/custom-elements/custom-elements.html @@ -0,0 +1,43 @@ + + + + + + +
+ + + +
+ + diff --git a/test/spec/custom-elements/my-button.reel/my-button.html b/test/spec/custom-elements/my-button.reel/my-button.html new file mode 100644 index 0000000000..38ddd82d91 --- /dev/null +++ b/test/spec/custom-elements/my-button.reel/my-button.html @@ -0,0 +1,19 @@ + + + + + + + + + + diff --git a/test/spec/custom-elements/my-button.reel/my-button.js b/test/spec/custom-elements/my-button.reel/my-button.js new file mode 100644 index 0000000000..e3ee64e80f --- /dev/null +++ b/test/spec/custom-elements/my-button.reel/my-button.js @@ -0,0 +1,15 @@ + +var Component = require("montage/ui/component").Component; +var Button = require("montage/ui/button.reel").Button; + +var MyButton = exports.MyButton = Button.specialize({ + hasTemplate: { + value: true + } +}); + +if (window.MontageElement) { + MontageElement.define("my-button", MyButton, { + observedAttributes: ['label'] + }); +} diff --git a/test/spec/meta/blueprint-spec.js b/test/spec/meta/blueprint-spec.js deleted file mode 100644 index 744e5766b5..0000000000 --- a/test/spec/meta/blueprint-spec.js +++ /dev/null @@ -1,418 +0,0 @@ -"use strict"; -/** - @module montage/data/blueprint-spec.js - @requires montage/core/core - @requires montage/core/logger - */ -var Montage = require("montage").Montage; -var Blueprint = require("montage/core/meta/blueprint").Blueprint; -var Model = require("montage/core/meta/model").Model; -var PropertyDescriptor = require("montage/core/meta/property-descriptor").PropertyDescriptor; -var AssociationBlueprint = require("montage/core/meta/association-blueprint").AssociationBlueprint; -var Serializer = require("montage/core/serialization/serializer/montage-serializer").MontageSerializer; -var Deserializer = require("montage/core/serialization/deserializer/montage-deserializer").MontageDeserializer; -var BinderHelper = require("./blueprint/binderhelper").BinderHelper; -var Person = require("./blueprint/person").Person; -var Company = require("./blueprint/company").Company; -var logger = require("montage/core/logger").logger("./blueprint-spec.js"); - -// Require to deserialize -// TODO add proper deps to montage modules -require('montage/core/meta/object-descriptor'); -require('montage/core/meta/object-descriptor-reference'); -require('montage/core/meta/blueprint-reference'); -require('montage/core/meta/property-blueprint'); -require('montage/core/meta/module-blueprint'); - -describe("meta/blueprint-spec", function () { - describe("Binder", function () { - describe("Creation", function () { - }); - describe("Adding blueprints", function () { - var binder = new Model().initWithNameAndRequire("CompanyBinder", require); - var personBlueprint = new Blueprint().initWithName("Person"); - binder.addObjectDescriptor(personBlueprint); - - var companyBlueprint = new Blueprint().initWithName("Company"); - binder.addObjectDescriptor(companyBlueprint); - - it("should have a binder", function () { - expect(personBlueprint.model).toBe(binder); - expect(companyBlueprint.model).toBe(binder); - }); - - }); - }); - - describe("Blueprint", function () { - describe("propertyDescriptors", function () { - var blueprint = new Blueprint().initWithName("Person"); - var propertyBlueprint = blueprint.newPropertyDescriptor("foo", 1); - it("should be able to add", function () { - blueprint.addPropertyDescriptor(propertyBlueprint); - expect(propertyBlueprint.owner).toBe(blueprint); - expect(blueprint.propertyDescriptorForName("foo")).toBe(propertyBlueprint); - }); - - it("should be able to remove", function () { - blueprint.removePropertyDescriptor(propertyBlueprint); - expect(propertyBlueprint.owner).toBe(null); - expect(blueprint.propertyDescriptorForName("foo")).toBeNull(); - }); - }); - describe("associations", function () { - - var personBlueprint = new Blueprint().initWithName("Person"); - var companyBlueprint = new Blueprint().initWithName("Company"); - - var employerAssociation = personBlueprint.newAssociationBlueprint("employer", Infinity); - employerAssociation.valueDescriptor = companyBlueprint; - var employeesAssociation = companyBlueprint.newAssociationBlueprint("employees", Infinity); - employeesAssociation.valueDescriptor = personBlueprint; - - personBlueprint.addPropertyDescriptor(employerAssociation); - companyBlueprint.addPropertyDescriptor(employeesAssociation); - - it("basic properties should be correct", function () { - expect(personBlueprint.propertyDescriptorForName("employer")).toBe(employerAssociation); - expect(companyBlueprint.propertyDescriptorForName("employees")).toBe(employeesAssociation); - }); - it("target blueprint promise to be resolved", function (done) { - personBlueprint.propertyDescriptorForName("employer").valueDescriptor.then(function (blueprint) { - expect(blueprint).toBeTruthy(); - expect(blueprint).toBe(companyBlueprint); - }).finally(function () { - done(); - }); - }); - it("target blueprint promise to be resolved", function (done) { - companyBlueprint.propertyDescriptorForName("employees").valueDescriptor.then(function (blueprint) { - expect(blueprint).toBeTruthy(); - expect(blueprint).toBe(personBlueprint); - }).finally(function () { - done(); - }); - }); - }); - describe("blueprint to instance association", function () { - var binder, personBlueprint, companyBlueprint; - beforeEach(function () { - binder = new Model().initWithNameAndRequire("Binder", require); - personBlueprint = new Blueprint().initWithName("Person"); - binder.addObjectDescriptor(personBlueprint); - companyBlueprint = new Blueprint().initWithName("Company"); - binder.addObjectDescriptor(companyBlueprint); - }); - it("should be found with the blueprint name", function () { - expect(binder.objectDescriptorForName("Person")).toBe(personBlueprint); - expect(binder.objectDescriptorForName("Company")).toBe(companyBlueprint); - }); - }); - describe("applying a basic blueprint to a prototype", function () { - var louis, personBlueprint; - beforeEach(function () { - var binder = new Model().initWithNameAndRequire("Binder", require); - personBlueprint = new Blueprint().initWithName("Person"); - personBlueprint.addPropertyDescriptor(personBlueprint.newPropertyDescriptor("name", 1)); - personBlueprint.addPropertyDescriptor(personBlueprint.newPropertyDescriptor("keywords", Infinity)); - - binder.addObjectDescriptor(personBlueprint); - Model.group.addModel(binder); - - louis = personBlueprint.newInstance().init(); - }); - - it("should have a blueprint", function () { - expect(louis.blueprint).toBe(personBlueprint); - }); - it("should have a the correct properties defined", function () { - expect(Object.getPrototypeOf(louis).hasOwnProperty("name")).toBeTruthy(); - expect(Object.getPrototypeOf(louis).hasOwnProperty("keywords")).toBeTruthy(); - }); - }); - - describe("adding a PropertyDescriptor", function () { - var circle, shapeBlueprint; - beforeEach(function () { - var binder = new Model().initWithNameAndRequire("Binder", require); - shapeBlueprint = new Blueprint().initWithName("Shape"); - binder.addObjectDescriptor(shapeBlueprint); - var propertyBlueprint = shapeBlueprint.newPropertyDescriptor("size", 1); - shapeBlueprint.addPropertyDescriptor(propertyBlueprint); - propertyBlueprint = shapeBlueprint.newPropertyDescriptor("readOnlyPropertyDescriptor", 1); - propertyBlueprint.readOnly = true; - shapeBlueprint.addPropertyDescriptor(propertyBlueprint); - propertyBlueprint = shapeBlueprint.newPropertyDescriptor("mandatoryPropertyDescriptor", 1); - propertyBlueprint.mandatory = true; - shapeBlueprint.addPropertyDescriptor(propertyBlueprint); - propertyBlueprint = shapeBlueprint.newPropertyDescriptor("denyDelete", 1); - propertyBlueprint.denyDelete = true; - shapeBlueprint.addPropertyDescriptor(propertyBlueprint); - Model.group.addModel(binder); - - circle = shapeBlueprint.newInstance().init(); - }); - describe("normal propertyBlueprint's property", function () { - it("should be settable", function () { - var descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(circle), "size"); - expect(typeof descriptor.get).toEqual("function"); - expect(typeof descriptor.set).toEqual("function"); - expect(circle.size).toBeNull(); - circle.size = "big"; - expect(circle.size).toEqual("big"); - }); - it("should be enumerable", function () { - var descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(circle), "size"); - expect(descriptor.enumerable).toBeTruthy(); - }); - it("should have a get and set", function () { - var descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(circle), "size"); - expect(typeof descriptor.get).toEqual("function"); - expect(typeof descriptor.set).toEqual("function"); - }); - }); - describe("read only propertyBlueprint's property", function () { - it("should not be settable", function () { - expect(function () { - circle.readOnlyPropertyDescriptor = "big"; - }).toThrow(); - }); - it("should have a get and no set", function () { - var descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(circle), "readOnlyPropertyDescriptor"); - expect(typeof descriptor.get).toEqual("function"); - expect(typeof descriptor.set).toEqual("undefined"); - }); - }); - describe("mandatory propertyBlueprint's property", function () { - it("should not be settable", function () { - expect( - function () { - circle.readOnlyPropertyDescriptor = "big"; - }).toThrow(); - }); - it("should have a get and no set", function () { - var descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(circle), "readOnlyPropertyDescriptor"); - expect(typeof descriptor.get).toEqual("function"); - expect(typeof descriptor.set).toEqual("undefined"); - }); - }); - describe("denyDelete propertyBlueprint's property", function () { - it("should not be settable to null", function () { - circle.denyDelete = "big"; - expect( - function () { - circle.denyDelete = null; - }).toThrow(); - }); - }); - }); - - describe("serializing", function () { - var companyBinder = BinderHelper.companyBinder(), - personBlueprint = companyBinder.objectDescriptorForName("Person"); - - personBlueprint.maxAge = 60; - - - it("can serialize", function () { - var serializedBinder = new Serializer().initWithRequire(require).serializeObject(companyBinder); - expect(serializedBinder).not.toBeNull(); - }); - it("can deserialize", function (done) { - var serializedBinder = new Serializer().initWithRequire(require).serializeObject(companyBinder); - var deserializer = new Deserializer().init(serializedBinder, require).deserializeObject().then(function (deserializedBinder) { - var metadata = Montage.getInfoForObject(deserializedBinder); - expect(serializedBinder).not.toBeNull(); - expect(metadata.objectName).toBe("Model"); - expect(metadata.moduleId).toBe("core/meta/model"); - var personBlueprint = deserializedBinder.objectDescriptorForName("Person"); - expect(personBlueprint).toBeTruthy(); - expect(personBlueprint.propertyDescriptorForName("phoneNumbers")).not.toBeNull(); - expect(personBlueprint.maxAge).toBe(60); - }, function (err) { - fail(err); - }).finally(function () { - done(); - }); - }); - }); - - describe("create new prototype", function () { - - it("Should be a prototype", function () { - var info = Montage.getInfoForObject(Person); - expect(info.isInstance).toBeFalsy(); - }); - - it("Should have the right moduleId and Name", function () { - var info = Montage.getInfoForObject(Person); - expect(info.moduleId).toBe("spec/meta/blueprint/person"); - expect(info.objectName).toBe("Person"); - }); - }); - - describe("createDefaultObjectDescriptorForObject", function () { - it("should always return a promise", function (done) { - var blueprint = Blueprint.createDefaultObjectDescriptorForObject({}); - expect(typeof blueprint.then).toBe("function"); - blueprint.then(function (blueprint) { - expect(Blueprint.prototype.isPrototypeOf(blueprint)).toBe(true); - }, function (err) { - fail(err); - }).finally(function () { - done(); - }); - }); - - it("has the correct module id for the parent", function (done) { - var ComponentBlueprintTest1 = require("spec/meta/component-blueprint-test/component-blueprint-test-1.reel").ComponentBlueprintTest1; - Blueprint.createDefaultObjectDescriptorForObject(ComponentBlueprintTest1).then(function (blueprint) { - var id = blueprint.parent.objectDescriptorInstanceModule.resolve(require); - expect(id === "montage/ui/component.meta" || id === "montage/ui/component.mjson").toBeTruthy(); - }, function (err) { - fail(err); - }).finally(function () { - done(); - }); - }); - - }); - - describe("blueprint descriptor", function () { - // Fixme: Spec was already broken before removing constructor compatibility (an unrelated error was raised) - // Before removing constructor compatibility, it was possible to reproduce this issue by setting a constructor descriptor. - //it("does not work for objects that aren't in a module", function () { - // var Sub = Blueprint.specialize(); - // var sub = new Sub(); - // - // expect(function () { - // var x = sub.blueprint; - // }).toThrow(); - //}); - - - it("uses the correct module ID for objects with no .meta", function () { - var Sub = Blueprint.specialize(); - // fake object loaded from module - Object.defineProperty(Sub, "_montage_metadata", { - value: { - require: require, - module: "pass", - moduleId: "pass", // deprecated - property: "Pass", - objectName: "Pass", // deprecated - isInstance: false - } - }); - - var sub = new Sub(); - sub._montage_metadata = Object.create(Sub._montage_metadata, { - isInstance: { value: true } - }); - - expect(sub.blueprintModuleId === "pass.meta" || sub.blueprintModuleId === "pass.mjson").toBeTruthy(); - }); - - it("creates a blueprint when the parent has no blueprint", function (done) { - Blueprint.blueprint.then(function (blueprint){ - expect( blueprint.objectDescriptorInstanceModule.id === "core/meta/blueprint.meta" || - blueprint.objectDescriptorInstanceModule.id === "core/meta/object-descriptor.mjson").toBeTruthy(); - }, function (err) { - fail(err); - }).finally(function () { - done(); - }); - }); - }); - - describe("events", function () { - var EventDescriptor = require("montage/core/meta/event-descriptor").EventDescriptor; - - var blueprint; - beforeEach(function () { - blueprint = new Blueprint().initWithName("test"); - }); - - describe("eventDescriptors", function () { - it("returns the same array", function () { - blueprint.addEventDescriptorNamed("event"); - var eventDescriptors = blueprint.eventDescriptors; - expect(blueprint.eventDescriptors).toBe(eventDescriptors); - }); - }); - - describe("adding", function () { - var eventBlueprint; - afterEach(function () { - expect(blueprint.eventDescriptors.length).toEqual(1); - expect(blueprint.eventDescriptors[0]).toBe(eventBlueprint); - }); - - it("adds an existing blueprint", function () { - eventBlueprint = new EventDescriptor().initWithNameAndObjectDescriptor("event"); - blueprint.addEventDescriptor(eventBlueprint); - - expect(eventBlueprint.owner).toBe(blueprint); - expect(blueprint.eventDescriptorForName("event")).toBe(eventBlueprint); - }); - - it("only adds the blueprint once", function () { - eventBlueprint = new EventDescriptor().initWithNameAndObjectDescriptor("event"); - - blueprint.addEventDescriptor(eventBlueprint); - blueprint.addEventDescriptor(eventBlueprint); - - expect(eventBlueprint.owner).toBe(blueprint); - expect(blueprint.eventDescriptorForName("event")).toBe(eventBlueprint); - }); - - it("creates a new blueprint with the given name", function () { - eventBlueprint = blueprint.addEventDescriptorNamed("event"); - - expect(eventBlueprint.owner).toBe(blueprint); - expect(eventBlueprint.name).toEqual("event"); - expect(blueprint.eventDescriptorForName("event")).toBe(eventBlueprint); - }); - }); - - it("creates a new event blueprint", function () { - var eventBlueprint = blueprint.newEventDescriptor("event"); - - expect(eventBlueprint.name).toEqual("event"); - expect(eventBlueprint.owner).toBe(blueprint); - }); - - it("removes an existing blueprint", function () { - var eventBlueprint = blueprint.addEventDescriptorNamed("event"); - blueprint.removeEventDescriptor(eventBlueprint); - - expect(eventBlueprint.owner).toBe(null); - expect(blueprint.eventDescriptorForName("event")).toBe(null); - }); - - - it("removes an existing blueprint from it's previous owner", function () { - var oldBlueprint = new Blueprint().initWithName("old"); - - var eventBlueprint = new EventDescriptor().initWithNameAndObjectDescriptor("event", oldBlueprint); - blueprint.addEventDescriptor(eventBlueprint); - - expect(eventBlueprint.owner).toBe(blueprint); - expect(blueprint.eventDescriptorForName("event")).toBe(eventBlueprint); - - expect(oldBlueprint.eventDescriptorForName("event")).toBe(null); - }); - - it("lists event blueprints of the parent", function () { - var parentBlueprint = new Blueprint().initWithName("parent"); - blueprint.parent = parentBlueprint; - - var parentEvent = parentBlueprint.addEventDescriptorNamed("parentEvent"); - var event = blueprint.addEventDescriptorNamed("event"); - - expect(blueprint.eventDescriptors.length).toEqual(2); - expect(blueprint.eventDescriptors).toEqual([event, parentEvent]); - }); - }); - }); -}); diff --git a/test/spec/meta/blueprint/binderhelper.js b/test/spec/meta/blueprint/binderhelper.js deleted file mode 100644 index f58096232b..0000000000 --- a/test/spec/meta/blueprint/binderhelper.js +++ /dev/null @@ -1,41 +0,0 @@ -/* - */ -var Montage = require("montage").Montage; -var Blueprint = require("montage/core/meta/blueprint").Blueprint; -var Model = require("montage/core/meta/model").Model; - -exports.companyBinder = function () { - return exports.BinderHelper.companyBinder(); -}; - -exports.BinderHelper = Montage.specialize( { -}, { - companyBinder: { - value: function () { - var companyBinder = new Model().initWithNameAndRequire("CompanyBinder", require); - - var personBlueprint = companyBinder.addObjectDescriptorNamed("Person", "spec/meta/blueprint/person"); - personBlueprint.addToOnePropertyDescriptorNamed("name"); - personBlueprint.addToManyPropertyDescriptorNamed("phoneNumbers"); - - var companyBlueprint = companyBinder.addObjectDescriptorNamed("Company", "spec/meta/blueprint/company"); - companyBlueprint.addToOnePropertyDescriptorNamed("name"); - - companyBlueprint.addToManyAssociationBlueprintNamed("directReports", personBlueprint.addToOneAssociationBlueprintNamed("supervisor")); - - var projectBlueprint = companyBinder.addObjectDescriptorNamed("Project", "spec/meta/blueprint/project"); - projectBlueprint.addToOnePropertyDescriptorNamed("name"); - projectBlueprint.addToOnePropertyDescriptorNamed("startDate"); - projectBlueprint.addToOnePropertyDescriptorNamed("endDate"); - - // companyBlueprint.addToManyAssociationBlueprintNamed("projects", personBlueprint.addToOneAssociationBlueprintNamed("company")); - // - // personBlueprint.addToManyAssociationBlueprintNamed("projects", projectBlueprint.addToManyAssociationBlueprintNamed("contributors")); - - Model.group.addModel(companyBinder); - - return companyBinder; - } - } - -}); diff --git a/test/spec/meta/blueprint/company.js b/test/spec/meta/blueprint/company.js index 037fd3ac1c..d755c7cbcf 100644 --- a/test/spec/meta/blueprint/company.js +++ b/test/spec/meta/blueprint/company.js @@ -2,11 +2,11 @@ */ var Montage = require("montage").Montage; -var BinderHelper = require("spec/meta/blueprint/binderhelper").BinderHelper; -var binder = BinderHelper.companyBinder(); -var blueprint = binder.objectDescriptorForName("Company"); +var ModelHelper = require("spec/meta/blueprint/model-helper").ModelHelper; +var model = ModelHelper.companyModel(); +var objectDescriptor = model.objectDescriptorForName("Company"); -var Company = exports.Company = blueprint.create(Montage, { +var Company = exports.Company = objectDescriptor.create(Montage, { // Token class diff --git a/test/spec/meta/blueprint/model-helper.js b/test/spec/meta/blueprint/model-helper.js new file mode 100644 index 0000000000..5928e938ed --- /dev/null +++ b/test/spec/meta/blueprint/model-helper.js @@ -0,0 +1,36 @@ +/* + */ +var Montage = require("montage").Montage; +var Model = require("montage/core/meta/model").Model; + +exports.companyModel = function () { + return exports.ModelHelper.companyModel(); +}; + +exports.ModelHelper = Montage.specialize( { +}, { + companyModel: { + value: function () { + var companyModel = new Model().initWithNameAndRequire("CompanyModel", require); + + var personObjectDescriptor = companyModel.addObjectDescriptorNamed("Person", "spec/meta/blueprint/person"); + personObjectDescriptor.addToOnePropertyDescriptorNamed("name"); + personObjectDescriptor.addToManyPropertyDescriptorNamed("phoneNumbers"); + + var companyObjectDescriptor = companyModel.addObjectDescriptorNamed("Company", "spec/meta/blueprint/company"); + companyObjectDescriptor.addToOnePropertyDescriptorNamed("name"); + + companyObjectDescriptor.addToManyPropertyDescriptorNamed("directReports", personObjectDescriptor.addToOnePropertyDescriptorNamed("supervisor")); + + var projectObjectDescriptor = companyModel.addObjectDescriptorNamed("Project", "spec/meta/blueprint/project"); + projectObjectDescriptor.addToOnePropertyDescriptorNamed("name"); + projectObjectDescriptor.addToOnePropertyDescriptorNamed("startDate"); + projectObjectDescriptor.addToOnePropertyDescriptorNamed("endDate"); + + Model.group.addModel(companyModel); + + return companyModel; + } + } + +}); diff --git a/test/spec/meta/blueprint/package/node_modules/dependency/node_modules/dependency2/thing.meta b/test/spec/meta/blueprint/package/node_modules/dependency/node_modules/dependency2/thing.meta index 26f24d7d84..dfbed1c890 100644 --- a/test/spec/meta/blueprint/package/node_modules/dependency/node_modules/dependency2/thing.meta +++ b/test/spec/meta/blueprint/package/node_modules/dependency/node_modules/dependency2/thing.meta @@ -1,6 +1,6 @@ { "root": { - "prototype": "montage/core/meta/module-blueprint", + "prototype": "montage/core/meta/module-object-descriptor", "values": { "name": "Thing", "module": {"%": "./thing"}, diff --git a/test/spec/meta/blueprint/package/node_modules/dependency/thing.meta b/test/spec/meta/blueprint/package/node_modules/dependency/thing.meta index 77807a7141..49bb08b5fb 100644 --- a/test/spec/meta/blueprint/package/node_modules/dependency/thing.meta +++ b/test/spec/meta/blueprint/package/node_modules/dependency/thing.meta @@ -1,16 +1,9 @@ { - "blueprint_parent": { - "prototype": "montage/core/meta/blueprint-reference", - "values": { - "valueReference": { - "blueprintName": "Thing", - "blueprintModule": {"%": "dependency2/thing.meta"}, - "prototypeName": "Thing" - } - } + "objectDescriptor_parent": { + "object": "dependency2/thing.meta" }, "root": { - "prototype": "montage/core/meta/module-blueprint", + "prototype": "montage/core/meta/module-object-descriptor", "values": { "name": "Thing", "module": { @@ -18,9 +11,9 @@ }, "exportName": "Thing", "parent": { - "@": "blueprint_parent" + "@": "objectDescriptor_parent" }, - "blueprintModule": {} + "objectDescriptorModule": {} } } } diff --git a/test/spec/meta/blueprint/package/thing.meta b/test/spec/meta/blueprint/package/thing.meta index 650c5de07c..1f420dc55c 100644 --- a/test/spec/meta/blueprint/package/thing.meta +++ b/test/spec/meta/blueprint/package/thing.meta @@ -1,16 +1,9 @@ { - "blueprint_parent": { - "prototype": "montage/core/meta/blueprint-reference", - "values": { - "valueReference": { - "blueprintName": "Thing", - "blueprintModule": {"%": "dependency/thing.meta"}, - "prototypeName": "Thing" - } - } + "objectDescriptor_parent": { + "object": "dependency/thing.meta" }, "root": { - "prototype": "montage/core/meta/module-blueprint", + "prototype": "montage/core/meta/module-object-descriptor", "values": { "name": "Thing", "module": { @@ -18,9 +11,9 @@ }, "exportName": "Thing", "parent": { - "@": "blueprint_parent" + "@": "objectDescriptor_parent" }, - "blueprintModule": {} + "objectDescriptorModule": {} } } } diff --git a/test/spec/meta/blueprint/person.js b/test/spec/meta/blueprint/person.js index 623209245d..87066ce854 100644 --- a/test/spec/meta/blueprint/person.js +++ b/test/spec/meta/blueprint/person.js @@ -2,11 +2,11 @@ */ var Montage = require("montage").Montage; -var BinderHelper = require("spec/meta/blueprint/binderhelper").BinderHelper; -var binder = BinderHelper.companyBinder(); -var blueprint = binder.objectDescriptorForName("Person"); +var ModelHelper = require("spec/meta/blueprint/model-helper").ModelHelper; +var model = ModelHelper.companyModel(); +var objectDescriptor = model.objectDescriptorForName("Person"); -var Person = exports.Person = blueprint.create(Montage, { +var Person = exports.Person = objectDescriptor.create(Montage, { // Token class diff --git a/test/spec/meta/blueprint/project.js b/test/spec/meta/blueprint/project.js index 238b768f3d..2cea7a3b89 100644 --- a/test/spec/meta/blueprint/project.js +++ b/test/spec/meta/blueprint/project.js @@ -2,11 +2,11 @@ s */ var Montage = require("montage").Montage; -var BinderHelper = require("spec/meta/blueprint/binderhelper").BinderHelper; -var binder = BinderHelper.companyBinder(); -var blueprint = binder.objectDescriptorForName("Project"); +var BinderHelper = require("spec/meta/blueprint/modelhelper").BinderHelper; +var model = BinderHelper.companyModel(); +var objectDescriptor = model.objectDescriptorForName("Project"); -var Project = exports.Project = blueprint.create(Montage, { +var Project = exports.Project = objectDescriptor.create(Montage, { // Token class diff --git a/test/spec/meta/build-in-component-blueprint-spec.js b/test/spec/meta/build-in-component-blueprint-spec.js deleted file mode 100644 index 5b3600d901..0000000000 --- a/test/spec/meta/build-in-component-blueprint-spec.js +++ /dev/null @@ -1,184 +0,0 @@ -/* - */ -/** - @module montage/data/blueprint-spec.js - @requires montage/core/core - @requires montage/core/logger - */ -var Montage = require("montage").Montage; -var Condition = require("montage/ui/condition.reel").Condition; -var Loader = require("montage/ui/loader.reel").Loader; -var Repetition = require("montage/ui/repetition.reel").Repetition; -var Slot = require("montage/ui/slot.reel").Slot; -var Substitution = require("montage/ui/substitution.reel").Substitution; -var Text = require("montage/ui/text.reel").Text; - -var Blueprint = require("montage/core/meta/blueprint").Blueprint; -var Binder = require("montage/core/meta/blueprint").Binder; -var PropertyBlueprint = require("montage/core/meta/blueprint").PropertyBlueprint; -var AssociationBlueprint = require("montage/core/meta/blueprint").AssociationBlueprint; - -var Serializer = require("montage/core/serialization/serializer/montage-serializer").MontageSerializer; - -describe("meta/build-in-component-blueprint-spec", function () { - - var textinput, - condition, - loader, - repetition, - slot, - substitution, - text; - - beforeEach(function () { -// textinput = new TextInput(); - condition = new Condition(); - loader = new Loader(); - repetition = new Repetition(); - slot = new Slot(); - substitution = new Substitution(); - text = new Text(); - }); -// -// describe("test text input blueprint", function () { -// it("should exist", function () { -// var blueprintPromise = textinput.blueprint; -// blueprintPromise.then(function (blueprint) { -// expect(blueprint).toBeTruthy(); -// var serializer = new Serializer().initWithRequire(require); -// var serializedDescription = serializer.serializeObject(blueprint); -// console.log(serializedDescription); -// }).finally(function () { -// done(); -// }); -// }); -// -// }); - - describe("test condition blueprint", function () { - it("should exist", function (done) { - var blueprintPromise = condition.blueprint; - blueprintPromise.then(function (blueprint) { - expect(blueprint).toBeTruthy(); - }).finally(function () { - done(); - }); - }); - - }); - - describe("test loader blueprint", function () { - it("should exist", function (done) { - var blueprintPromise = loader.blueprint; - blueprintPromise.then(function (blueprint) { - expect(blueprint).toBeTruthy(); - }).finally(function () { - done(); - }); - }); - - }); - - describe("test repetition blueprint", function () { - it("should exist", function (done) { - var blueprintPromise = repetition.blueprint; - blueprintPromise.then(function (blueprint) { - expect(blueprint).toBeTruthy(); - }).finally(function () { - done(); - }); - }); - - }); - - describe("test slot blueprint", function () { - it("should exist", function (done) { - var blueprintPromise = slot.blueprint; - blueprintPromise.then(function (blueprint) { - expect(blueprint).toBeTruthy(); - }).finally(function () { - done(); - }); - }); - - }); - - describe("test substitution blueprint", function () { - it("should exist", function (done) { - var blueprintPromise = substitution.blueprint; - blueprintPromise.then(function (blueprint) { - expect(blueprint).toBeTruthy(); - }).finally(function () { - done(); - }); - }); - - it("should have switchValue property blueprint", function (done) { - var blueprintPromise = substitution.blueprint; - blueprintPromise.then(function (blueprint) { - var propertyBlueprint = blueprint.propertyDescriptorForName("switchValue"); - expect(propertyBlueprint).toBeTruthy(); - expect(propertyBlueprint.valueType).toBe("string"); - }).finally(function () { - done(); - }); - }); - - it("should have shouldLoadComponentTree property blueprint", function (done) { - var blueprintPromise = substitution.blueprint; - blueprintPromise.then(function (blueprint) { - var propertyBlueprint = blueprint.propertyDescriptorForName("shouldLoadComponentTree"); - expect(propertyBlueprint).toBeTruthy(); - expect(propertyBlueprint.valueType).toBe("boolean"); - }).finally(function () { - done(); - }); - }); - - it("should have transition property blueprint", function (done) { - var blueprintPromise = substitution.blueprint; - blueprintPromise.then(function (blueprint) { - var propertyBlueprint = blueprint.propertyDescriptorForName("transition"); - expect(propertyBlueprint).toBeTruthy(); - expect(propertyBlueprint.valueType).toBe("object"); - }).finally(function () { - done(); - }); - }); - }); - - describe("test text blueprint", function () { - it("should exist", function (done) { - var blueprintPromise = text.blueprint; - blueprintPromise.then(function (blueprint) { - expect(blueprint).toBeTruthy(); - }).finally(function () { - done(); - }); - }); - - it("should have value property blueprint", function (done) { - var blueprintPromise = text.blueprint; - blueprintPromise.then(function (blueprint) { - var propertyBlueprint = blueprint.propertyDescriptorForName("value"); - expect(propertyBlueprint).toBeTruthy(); - expect(propertyBlueprint.valueType).toBe("string"); - }).finally(function () { - done(); - }); - }); - - it("should have converter association blueprint", function (done) { - var blueprintPromise = text.blueprint; - blueprintPromise.then(function (blueprint) { - var propertyBlueprint = blueprint.propertyDescriptorForName("converter"); - expect(propertyBlueprint).toBeTruthy(); - expect(propertyBlueprint.isAssociationBlueprint).toBe(true); - expect(propertyBlueprint.valueDescriptor).toBeTruthy(); - }).finally(function () { - done(); - }); - }); - }); - -}); diff --git a/test/spec/meta/build-in-component-object-descriptor-spec.js b/test/spec/meta/build-in-component-object-descriptor-spec.js new file mode 100644 index 0000000000..98e2888c5d --- /dev/null +++ b/test/spec/meta/build-in-component-object-descriptor-spec.js @@ -0,0 +1,183 @@ +/* + */ +/** + @requires montage/core/core + @requires montage/core/logger + */ +var Montage = require("montage").Montage; +var Condition = require("montage/ui/condition.reel").Condition; +var Loader = require("montage/ui/loader.reel").Loader; +var Repetition = require("montage/ui/repetition.reel").Repetition; +var Slot = require("montage/ui/slot.reel").Slot; +var Substitution = require("montage/ui/substitution.reel").Substitution; +var Text = require("montage/ui/text.reel").Text; + +var ObjectDescriptor = require("montage/core/meta/object-descriptor").ObjectDescriptor; + +var Serializer = require("montage/core/serialization/serializer/montage-serializer").MontageSerializer; + +describe("meta/build-in-component-object-descriptor-spec", function () { + + var textinput, + condition, + loader, + repetition, + slot, + substitution, + text; + + beforeEach(function () { +// textinput = new TextInput(); + condition = new Condition(); + loader = new Loader(); + repetition = new Repetition(); + slot = new Slot(); + substitution = new Substitution(); + text = new Text(); + }); + + // TODO: Why is this commented out? +// +// describe("test text input objectDescriptor", function () { +// it("should exist", function () { +// var objectDescriptorPromise = textinput.objectDescriptor; +// objectDescriptorPromise.then(function (objectDescriptor) { +// expect(objectDescriptor).toBeTruthy(); +// var serializer = new Serializer().initWithRequire(require); +// var serializedDescription = serializer.serializeObject(objectDescriptor); +// console.log(serializedDescription); +// }).finally(function () { +// done(); +// }); +// }); +// +// }); + + describe("test condition objectDescriptor", function () { + it("should exist", function (done) { + var objectDescriptorPromise = condition.objectDescriptor; + objectDescriptorPromise.then(function (objectDescriptor) { + expect(objectDescriptor).toBeTruthy(); + }).finally(function () { + done(); + }); + }); + + }); + + describe("test loader objectDescriptor", function () { + it("should exist", function (done) { + var objectDescriptorPromise = loader.objectDescriptor; + objectDescriptorPromise.then(function (objectDescriptor) { + expect(objectDescriptor).toBeTruthy(); + }).finally(function () { + done(); + }); + }); + + }); + + describe("test repetition objectDescriptor", function () { + it("should exist", function (done) { + var objectDescriptorPromise = repetition.objectDescriptor; + objectDescriptorPromise.then(function (objectDescriptor) { + expect(objectDescriptor).toBeTruthy(); + }).finally(function () { + done(); + }); + }); + + }); + + describe("test slot objectDescriptor", function () { + it("should exist", function (done) { + var objectDescriptorPromise = slot.objectDescriptor; + objectDescriptorPromise.then(function (objectDescriptor) { + expect(objectDescriptor).toBeTruthy(); + }).finally(function () { + done(); + }); + }); + + }); + + describe("test substitution objectDescriptor", function () { + it("should exist", function (done) { + var objectDescriptorPromise = substitution.objectDescriptor; + objectDescriptorPromise.then(function (objectDescriptor) { + expect(objectDescriptor).toBeTruthy(); + }).finally(function () { + done(); + }); + }); + + it("should have switchValue property objectDescriptor", function (done) { + var objectDescriptorPromise = substitution.objectDescriptor; + objectDescriptorPromise.then(function (objectDescriptor) { + var propertyDescriptor = objectDescriptor.propertyDescriptorForName("switchValue"); + expect(propertyDescriptor).toBeTruthy(); + expect(propertyDescriptor.valueType).toBe("string"); + }).finally(function () { + done(); + }); + }); + + it("should have shouldLoadComponentTree property objectDescriptor", function (done) { + var objectDescriptorPromise = substitution.objectDescriptor; + objectDescriptorPromise.then(function (objectDescriptor) { + var propertyDescriptor = objectDescriptor.propertyDescriptorForName("shouldLoadComponentTree"); + expect(propertyDescriptor).toBeTruthy(); + expect(propertyDescriptor.valueType).toBe("boolean"); + }).finally(function () { + done(); + }); + }); + + it("should have transition property objectDescriptor", function (done) { + var objectDescriptorPromise = substitution.objectDescriptor; + objectDescriptorPromise.then(function (objectDescriptor) { + var propertyDescriptor = objectDescriptor.propertyDescriptorForName("transition"); + expect(propertyDescriptor).toBeTruthy(); + expect(propertyDescriptor.valueType).toBe("object"); + }).finally(function () { + done(); + }); + }); + }); + + describe("test text objectDescriptor", function () { + it("should exist", function (done) { + var objectDescriptorPromise = text.objectDescriptor; + objectDescriptorPromise.then(function (objectDescriptor) { + expect(objectDescriptor).toBeTruthy(); + }).finally(function () { + done(); + }); + }); + + it("should have value property objectDescriptor", function (done) { + var objectDescriptorPromise = text.objectDescriptor; + objectDescriptorPromise.then(function (objectDescriptor) { + var propertyDescriptor = objectDescriptor.propertyDescriptorForName("value"); + expect(propertyDescriptor).toBeTruthy(); + expect(propertyDescriptor.valueType).toBe("string"); + }).finally(function () { + done(); + }); + }); + + it("should have converter association objectDescriptor", function (done) { + var objectDescriptorPromise = text.objectDescriptor; + objectDescriptorPromise.then(function (objectDescriptor) { + var propertyDescriptor = objectDescriptor.propertyDescriptorForName("converter"); + expect(propertyDescriptor).toBeTruthy(); + // TODO: isAssociationBlueprint is deprecated but has no equivalent + expect(propertyDescriptor.isAssociationBlueprint).toBe(true); + expect(propertyDescriptor.valueDescriptor).toBeTruthy(); + }).finally(function () { + done(); + }); + }); + }); + +}); diff --git a/test/spec/meta/component-blueprint-spec.js b/test/spec/meta/component-blueprint-spec.js deleted file mode 100644 index 527304f31f..0000000000 --- a/test/spec/meta/component-blueprint-spec.js +++ /dev/null @@ -1,161 +0,0 @@ -/* - */ -var Montage = require("montage").Montage; -var TestPageLoader = require("montage-testing/testpageloader").TestPageLoader; -var Component = require("montage/ui/component").Component; -var Selector = require("montage/core/selector").Selector; -var Blueprint = require("montage/core/meta/blueprint").Blueprint; -var Promise = require("montage/core/promise").Promise; -var Serializer = require("montage/core/serialization/serializer/montage-serializer").MontageSerializer; - -TestPageLoader.queueTest("component-blueprint-test/component-blueprint-test", function (testPage) { - describe("meta/component-blueprint-spec", function () { - var component1; - var component2; - var component3; - - - beforeEach(function () { - component1 = testPage.test.component1; - component2 = testPage.test.component2; - component3 = testPage.test.component3; - }); - - it("can create new blueprint", function (done) { - var newBlueprint = new Blueprint().initWithName(component1.identifier); - component1.blueprint = newBlueprint; - var blueprintPromise = component1.blueprint; - blueprintPromise.then(function (blueprint) { - expect(newBlueprint).toBeDefined(); - expect(blueprint).toBe(newBlueprint); - }).finally(function () { - done(); - }); - }); - - it("can create new property blueprint", function (done) { - var newBlueprint = new Blueprint().initWithName(component1.identifier); - newBlueprint.addToOnePropertyDescriptorNamed("bindableProperty"); - component1.blueprint = newBlueprint; - var blueprintPromise = component1.blueprint; - blueprintPromise.then(function (blueprint) { - var propertyBlueprint = blueprint.propertyDescriptorForName("bindableProperty"); - expect(propertyBlueprint).toBeDefined(); - }).finally(function () { - done(); - }); - }); - - it("can serialize the component blueprint", function (done) { - var serializer = new Serializer().initWithRequire(require); - - var newBlueprint = new Blueprint().initWithName(component1.identifier); - // - newBlueprint.addToOnePropertyDescriptorNamed("bindableProperty1"); - newBlueprint.addToOnePropertyDescriptorNamed("bindableProperty2"); - newBlueprint.addToOnePropertyDescriptorNamed("bindableProperty3"); - newBlueprint.addToOnePropertyDescriptorNamed("bindableProperty4"); - newBlueprint.addToOnePropertyDescriptorNamed("bindableProperty5"); - // - newBlueprint.addEventDescriptorNamed("action"); - // - newBlueprint.addPropertyDescriptorToGroupNamed(newBlueprint.addToOnePropertyDescriptorNamed("requiredBindableProperty1"), "required"); - newBlueprint.addPropertyDescriptorToGroupNamed(newBlueprint.addToOnePropertyDescriptorNamed("requiredBindableProperty2"), "required"); - newBlueprint.addPropertyDescriptorToGroupNamed(newBlueprint.addToOnePropertyDescriptorNamed("requiredBindableProperty3"), "required"); - component1.blueprint = newBlueprint; - - var blueprintPromise = component1.blueprint; - blueprintPromise.then(function (blueprint) { - var serializedDescription = serializer.serializeObject(blueprint); - expect(serializedDescription).toBeTruthy(); - }).finally(function () { - done(); - }); - }); - - xit("can load the component blueprint from the reel", function (done) { - var blueprintPromise = component2.blueprint; - blueprintPromise.then(function (blueprint) { - expect(blueprint).toBeTruthy(); - // TODO test look weird requiredBindableProperty1 vs bindableProperty1 - expect(blueprint.propertyDescriptorForName("bindableProperty1")).toBeTruthy(); - expect(blueprint.propertyDescriptorForName("required")).toBeTruthy(); - }).finally(function () { - done(); - }); - }); - - - it("can create validation rules", function (done) { - var serializer = new Serializer().initWithRequire(require); - - var newBlueprint = new Blueprint().initWithName(component3.identifier); - expect(newBlueprint).toBeTruthy(); - // - newBlueprint.addToOnePropertyDescriptorNamed("bindableProperty1"); - newBlueprint.addToOnePropertyDescriptorNamed("bindableProperty2"); - newBlueprint.addToOnePropertyDescriptorNamed("bindableProperty3"); - newBlueprint.addToOnePropertyDescriptorNamed("bindableProperty4"); - newBlueprint.addToOnePropertyDescriptorNamed("bindableProperty5"); - // - newBlueprint.addPropertyDescriptorToGroupNamed(newBlueprint.addToOnePropertyDescriptorNamed("requiredBindableProperty1"), "required"); - newBlueprint.addPropertyDescriptorToGroupNamed(newBlueprint.addToOnePropertyDescriptorNamed("requiredBindableProperty2"), "required"); - newBlueprint.addPropertyDescriptorToGroupNamed(newBlueprint.addToOnePropertyDescriptorNamed("requiredBindableProperty3"), "required"); - - newBlueprint.addPropertyValidationRule("rule1").validationSelector = null; - // newBlueprint.addPropertyValidationRule("rule1").validationSelector = Selector.property("requiredBindableProperty1").isBound; - // newBlueprint.addPropertyValidationRule("rule2").validationSelector = Selector.property("requiredBindableProperty2").isBound; - // newBlueprint.addPropertyValidationRule("rule3").validationSelector = Selector.property("requiredBindableProperty3").isBound; - - component3.blueprint = newBlueprint; - - var blueprintPromise = component3.blueprint; - blueprintPromise.then(function (blueprint) { - expect(blueprint).toBeTruthy(); - var serializedDescription = serializer.serializeObject(blueprint); - expect(serializedDescription).toBeTruthy(); - }).finally(function () { - done(); - }); - }); - - describe("test converter blueprint", function () { - var component = new Component(); - - it("should exist", function (done) { - var blueprintPromise = component.blueprint; - blueprintPromise.then(function (blueprint) { - expect(blueprint).toBeTruthy(); - }).finally(function () { - done(); - }); - }); - - it("should have element property blueprint", function (done) { - var blueprintPromise = component.blueprint; - blueprintPromise.then(function (blueprint) { - var propertyBlueprint = blueprint.propertyDescriptorForName("element"); - expect(propertyBlueprint).toBeTruthy(); - expect(propertyBlueprint.valueType).toBe("string"); - expect(propertyBlueprint.readOnly).toBe(true); - }).finally(function () { - done(); - }); - }); - - it("should have identifier property blueprint", function (done) { - var blueprintPromise = component.blueprint; - blueprintPromise.then(function (blueprint) { - var propertyBlueprint = blueprint.propertyDescriptorForName("identifier"); - expect(propertyBlueprint).toBeTruthy(); - expect(propertyBlueprint.valueType).toBe("string"); - }).finally(function () { - done(); - }); - }); - - }); - - }); - -}); diff --git a/test/spec/meta/component-object-descriptor-spec.js b/test/spec/meta/component-object-descriptor-spec.js new file mode 100644 index 0000000000..0e306a8acd --- /dev/null +++ b/test/spec/meta/component-object-descriptor-spec.js @@ -0,0 +1,161 @@ +/* + */ +var Montage = require("montage").Montage; +var TestPageLoader = require("montage-testing/testpageloader").TestPageLoader; +var Component = require("montage/ui/component").Component; +var Selector = require("montage/core/selector").Selector; +var ObjectDescriptor = require("montage/core/meta/object-descriptor").ObjectDescriptor; +var Promise = require("montage/core/promise").Promise; +var Serializer = require("montage/core/serialization/serializer/montage-serializer").MontageSerializer; + +TestPageLoader.queueTest("component-object-descriptor-test/component-object-descriptor-test", function (testPage) { + describe("meta/component-object-descriptor-spec", function () { + var component1; + var component2; + var component3; + + + beforeEach(function () { + component1 = testPage.test.component1; + component2 = testPage.test.component2; + component3 = testPage.test.component3; + }); + + it("can create new objectDescriptor", function (done) { + var newObjectDescriptor = new ObjectDescriptor().initWithName(component1.identifier); + component1.objectDescriptor = newObjectDescriptor; + var objectDescriptorPromise = component1.objectDescriptor; + objectDescriptorPromise.then(function (objectDescriptor) { + expect(newObjectDescriptor).toBeDefined(); + expect(objectDescriptor).toBe(newObjectDescriptor); + }).finally(function () { + done(); + }); + }); + + it("can create new property objectDescriptor", function (done) { + var newObjectDescriptor = new ObjectDescriptor().initWithName(component1.identifier); + newObjectDescriptor.addToOnePropertyDescriptorNamed("bindableProperty"); + component1.objectDescriptor = newObjectDescriptor; + var objectDescriptorPromise = component1.objectDescriptor; + objectDescriptorPromise.then(function (objectDescriptor) { + var propertyDescriptor = objectDescriptor.propertyDescriptorForName("bindableProperty"); + expect(propertyDescriptor).toBeDefined(); + }).finally(function () { + done(); + }); + }); + + it("can serialize the component objectDescriptor", function (done) { + var serializer = new Serializer().initWithRequire(require); + + var newObjectDescriptor = new ObjectDescriptor().initWithName(component1.identifier); + // + newObjectDescriptor.addToOnePropertyDescriptorNamed("bindableProperty1"); + newObjectDescriptor.addToOnePropertyDescriptorNamed("bindableProperty2"); + newObjectDescriptor.addToOnePropertyDescriptorNamed("bindableProperty3"); + newObjectDescriptor.addToOnePropertyDescriptorNamed("bindableProperty4"); + newObjectDescriptor.addToOnePropertyDescriptorNamed("bindableProperty5"); + // + newObjectDescriptor.addEventDescriptorNamed("action"); + // + newObjectDescriptor.addPropertyDescriptorToGroupNamed(newObjectDescriptor.addToOnePropertyDescriptorNamed("requiredBindableProperty1"), "required"); + newObjectDescriptor.addPropertyDescriptorToGroupNamed(newObjectDescriptor.addToOnePropertyDescriptorNamed("requiredBindableProperty2"), "required"); + newObjectDescriptor.addPropertyDescriptorToGroupNamed(newObjectDescriptor.addToOnePropertyDescriptorNamed("requiredBindableProperty3"), "required"); + component1.objectDescriptor = newObjectDescriptor; + + var objectDescriptorPromise = component1.objectDescriptor; + objectDescriptorPromise.then(function (objectDescriptor) { + var serializedDescription = serializer.serializeObject(objectDescriptor); + expect(serializedDescription).toBeTruthy(); + }).finally(function () { + done(); + }); + }); + + xit("can load the component objectDescriptor from the reel", function (done) { + var objectDescriptorPromise = component2.objectDescriptor; + objectDescriptorPromise.then(function (objectDescriptor) { + expect(objectDescriptor).toBeTruthy(); + // TODO test look weird requiredBindableProperty1 vs bindableProperty1 + expect(objectDescriptor.propertyDescriptorForName("bindableProperty1")).toBeTruthy(); + expect(objectDescriptor.propertyDescriptorForName("required")).toBeTruthy(); + }).finally(function () { + done(); + }); + }); + + + it("can create validation rules", function (done) { + var serializer = new Serializer().initWithRequire(require); + + var newObjectDescriptor = new ObjectDescriptor().initWithName(component3.identifier); + expect(newObjectDescriptor).toBeTruthy(); + // + newObjectDescriptor.addToOnePropertyDescriptorNamed("bindableProperty1"); + newObjectDescriptor.addToOnePropertyDescriptorNamed("bindableProperty2"); + newObjectDescriptor.addToOnePropertyDescriptorNamed("bindableProperty3"); + newObjectDescriptor.addToOnePropertyDescriptorNamed("bindableProperty4"); + newObjectDescriptor.addToOnePropertyDescriptorNamed("bindableProperty5"); + // + newObjectDescriptor.addPropertyDescriptorToGroupNamed(newObjectDescriptor.addToOnePropertyDescriptorNamed("requiredBindableProperty1"), "required"); + newObjectDescriptor.addPropertyDescriptorToGroupNamed(newObjectDescriptor.addToOnePropertyDescriptorNamed("requiredBindableProperty2"), "required"); + newObjectDescriptor.addPropertyDescriptorToGroupNamed(newObjectDescriptor.addToOnePropertyDescriptorNamed("requiredBindableProperty3"), "required"); + + newObjectDescriptor.addPropertyValidationRule("rule1").validationSelector = null; + // newObjectDescriptor.addPropertyValidationRule("rule1").validationSelector = Selector.property("requiredBindableProperty1").isBound; + // newObjectDescriptor.addPropertyValidationRule("rule2").validationSelector = Selector.property("requiredBindableProperty2").isBound; + // newObjectDescriptor.addPropertyValidationRule("rule3").validationSelector = Selector.property("requiredBindableProperty3").isBound; + + component3.objectDescriptor = newObjectDescriptor; + + var objectDescriptorPromise = component3.objectDescriptor; + objectDescriptorPromise.then(function (objectDescriptor) { + expect(objectDescriptor).toBeTruthy(); + var serializedDescription = serializer.serializeObject(objectDescriptor); + expect(serializedDescription).toBeTruthy(); + }).finally(function () { + done(); + }); + }); + + describe("test converter objectDescriptor", function () { + var component = new Component(); + + it("should exist", function (done) { + var objectDescriptorPromise = component.objectDescriptor; + objectDescriptorPromise.then(function (objectDescriptor) { + expect(objectDescriptor).toBeTruthy(); + }).finally(function () { + done(); + }); + }); + + it("should have element property objectDescriptor", function (done) { + var objectDescriptorPromise = component.objectDescriptor; + objectDescriptorPromise.then(function (objectDescriptor) { + var propertyDescriptor = objectDescriptor.propertyDescriptorForName("element"); + expect(propertyDescriptor).toBeTruthy(); + expect(propertyDescriptor.valueType).toBe("string"); + expect(propertyDescriptor.readOnly).toBe(true); + }).finally(function () { + done(); + }); + }); + + it("should have identifier property objectDescriptor", function (done) { + var objectDescriptorPromise = component.objectDescriptor; + objectDescriptorPromise.then(function (objectDescriptor) { + var propertyDescriptor = objectDescriptor.propertyDescriptorForName("identifier"); + expect(propertyDescriptor).toBeTruthy(); + expect(propertyDescriptor.valueType).toBe("string"); + }).finally(function () { + done(); + }); + }); + + }); + + }); + +}); diff --git a/test/spec/meta/component-blueprint-test/component-blueprint-test-1.reel/component-blueprint-test-1.html b/test/spec/meta/component-object-descriptor-test/component-object-descriptor-test-1.reel/component-object-descriptor-test-1.html similarity index 54% rename from test/spec/meta/component-blueprint-test/component-blueprint-test-1.reel/component-blueprint-test-1.html rename to test/spec/meta/component-object-descriptor-test/component-object-descriptor-test-1.reel/component-object-descriptor-test-1.html index af88e04cb9..3946e766d3 100644 --- a/test/spec/meta/component-blueprint-test/component-blueprint-test-1.reel/component-blueprint-test-1.html +++ b/test/spec/meta/component-object-descriptor-test/component-object-descriptor-test-1.reel/component-object-descriptor-test-1.html @@ -2,9 +2,9 @@ - ComponentBlueprintTest1 + ComponentObjectDescriptorTest1 - + - \ No newline at end of file + diff --git a/test/spec/meta/component-blueprint-test/component-blueprint-test-1.reel/component-blueprint-test-1.js b/test/spec/meta/component-object-descriptor-test/component-object-descriptor-test-1.reel/component-object-descriptor-test-1.js similarity index 51% rename from test/spec/meta/component-blueprint-test/component-blueprint-test-1.reel/component-blueprint-test-1.js rename to test/spec/meta/component-object-descriptor-test/component-object-descriptor-test-1.reel/component-object-descriptor-test-1.js index d770dae2ea..e9a28e8000 100644 --- a/test/spec/meta/component-blueprint-test/component-blueprint-test-1.reel/component-blueprint-test-1.js +++ b/test/spec/meta/component-object-descriptor-test/component-object-descriptor-test-1.reel/component-object-descriptor-test-1.js @@ -2,17 +2,17 @@ */ var Component = require("montage/ui/component").Component; -exports.ComponentBlueprintTest1 = Component.specialize( { +exports.ComponentObjectDescriptorTest1 = Component.specialize( { templateDidLoad: { value: function () { - console.log("Component Blueprint Test 1 template did load"); + console.log("Component ObjectDescriptor Test 1 template did load"); } }, deserializedFromTemplate: { value: function () { - console.log("Component Blueprint Test 1 deserialized from template"); + console.log("Component ObjectDescriptor Test 1 deserialized from template"); } } diff --git a/test/spec/meta/component-blueprint-test/component-blueprint-test-2.reel/component-blueprint-test-2.html b/test/spec/meta/component-object-descriptor-test/component-object-descriptor-test-2.reel/component-object-descriptor-test-2.html similarity index 54% rename from test/spec/meta/component-blueprint-test/component-blueprint-test-2.reel/component-blueprint-test-2.html rename to test/spec/meta/component-object-descriptor-test/component-object-descriptor-test-2.reel/component-object-descriptor-test-2.html index 0e9fb9406e..d16bdaa9ea 100644 --- a/test/spec/meta/component-blueprint-test/component-blueprint-test-2.reel/component-blueprint-test-2.html +++ b/test/spec/meta/component-object-descriptor-test/component-object-descriptor-test-2.reel/component-object-descriptor-test-2.html @@ -2,9 +2,9 @@ - ComponentBlueprintTest2 + ComponentObjectDescriptorTest2 - + - \ No newline at end of file + diff --git a/test/spec/meta/component-blueprint-test/component-blueprint-test-2.reel/component-blueprint-test-2.js b/test/spec/meta/component-object-descriptor-test/component-object-descriptor-test-2.reel/component-object-descriptor-test-2.js similarity index 51% rename from test/spec/meta/component-blueprint-test/component-blueprint-test-2.reel/component-blueprint-test-2.js rename to test/spec/meta/component-object-descriptor-test/component-object-descriptor-test-2.reel/component-object-descriptor-test-2.js index f8fbae0857..0cb472407e 100644 --- a/test/spec/meta/component-blueprint-test/component-blueprint-test-2.reel/component-blueprint-test-2.js +++ b/test/spec/meta/component-object-descriptor-test/component-object-descriptor-test-2.reel/component-object-descriptor-test-2.js @@ -3,17 +3,17 @@ var Montage = require("montage").Montage, Component = require("montage/ui/component").Component; -var ComponentBlueprintTest2 = exports.ComponentBlueprintTest2 = Component.specialize( { +var ComponentObjectDescriptorTest2 = exports.ComponentObjectDescriptorTest2 = Component.specialize( { templateDidLoad: { value: function () { - //console.log("Component Blueprint Test 2 template did load"); + //console.log("Component ObjectDescriptor Test 2 template did load"); } }, deserializedFromTemplate: { value: function () { - //console.log("Component Blueprint Test 2 deserialized from template"); + //console.log("Component ObjectDescriptor Test 2 deserialized from template"); } } diff --git a/test/spec/meta/component-blueprint-test/component-blueprint-test-2.reel/component-blueprint-test-2.meta b/test/spec/meta/component-object-descriptor-test/component-object-descriptor-test-2.reel/component-object-descriptor-test-2.meta similarity index 80% rename from test/spec/meta/component-blueprint-test/component-blueprint-test-2.reel/component-blueprint-test-2.meta rename to test/spec/meta/component-object-descriptor-test/component-object-descriptor-test-2.reel/component-object-descriptor-test-2.meta index dd0f024a81..7b021f8b73 100644 --- a/test/spec/meta/component-blueprint-test/component-blueprint-test-2.reel/component-blueprint-test-2.meta +++ b/test/spec/meta/component-object-descriptor-test/component-object-descriptor-test-2.reel/component-object-descriptor-test-2.meta @@ -1,8 +1,8 @@ { "component2_bindableProperty1": { - "prototype": "montage/core/meta/property-blueprint", + "prototype": "montage/core/meta/property-descriptor", "values": { - "blueprint": { + "objectDescriptor": { "@": "root" }, "name": "bindableProperty1", @@ -15,9 +15,9 @@ } }, "component2_bindableProperty2": { - "prototype": "montage/core/meta/property-blueprint", + "prototype": "montage/core/meta/property-descriptor", "values": { - "blueprint": { + "objectDescriptor": { "@": "root" }, "name": "bindableProperty2", @@ -30,9 +30,9 @@ } }, "component2_bindableProperty3": { - "prototype": "montage/core/meta/property-blueprint", + "prototype": "montage/core/meta/property-descriptor", "values": { - "blueprint": { + "objectDescriptor": { "@": "root" }, "name": "bindableProperty3", @@ -45,9 +45,9 @@ } }, "component2_bindableProperty4": { - "prototype": "montage/core/meta/property-blueprint", + "prototype": "montage/core/meta/property-descriptor", "values": { - "blueprint": { + "objectDescriptor": { "@": "root" }, "name": "bindableProperty4", @@ -60,9 +60,9 @@ } }, "component2_bindableProperty5": { - "prototype": "montage/core/meta/property-blueprint", + "prototype": "montage/core/meta/property-descriptor", "values": { - "blueprint": { + "objectDescriptor": { "@": "root" }, "name": "bindableProperty5", @@ -75,9 +75,9 @@ } }, "component2_requiredBindableProperty1": { - "prototype": "montage/core/meta/property-blueprint", + "prototype": "montage/core/meta/property-descriptor", "values": { - "blueprint": { + "objectDescriptor": { "@": "root" }, "name": "requiredBindableProperty1", @@ -90,9 +90,9 @@ } }, "component2_requiredBindableProperty2": { - "prototype": "montage/core/meta/property-blueprint", + "prototype": "montage/core/meta/property-descriptor", "values": { - "blueprint": { + "objectDescriptor": { "@": "root" }, "name": "requiredBindableProperty2", @@ -105,9 +105,9 @@ } }, "component2_requiredBindableProperty3": { - "prototype": "montage/core/meta/property-blueprint", + "prototype": "montage/core/meta/property-descriptor", "values": { - "blueprint": { + "objectDescriptor": { "@": "root" }, "name": "requiredBindableProperty3", @@ -120,7 +120,7 @@ } }, "root": { - "prototype": "montage/core/meta/module-blueprint", + "prototype": "montage/core/meta/module-object-descriptor", "values": { "name": "component2", "customPrototype": false, @@ -164,10 +164,10 @@ ] }, "propertyValidationRules": {}, - "blueprintModule": {}, - "exportName": "ComponentBlueprintTest2", + "objectDescriptorModule": {}, + "exportName": "ComponentObjectDescriptorTest2", "module": { - "%": "spec/test/meta/component-blueprint-test/component-blueprint-test-2.reel" + "%": "spec/test/meta/component-object-descriptor-test/component-object-descriptor-test-2.reel" } } } diff --git a/test/spec/meta/component-blueprint-test/component-blueprint-test-3.reel/component-blueprint-test-3.html b/test/spec/meta/component-object-descriptor-test/component-object-descriptor-test-3.reel/component-object-descriptor-test-3.html similarity index 54% rename from test/spec/meta/component-blueprint-test/component-blueprint-test-3.reel/component-blueprint-test-3.html rename to test/spec/meta/component-object-descriptor-test/component-object-descriptor-test-3.reel/component-object-descriptor-test-3.html index 8d4a62f029..c96e176132 100644 --- a/test/spec/meta/component-blueprint-test/component-blueprint-test-3.reel/component-blueprint-test-3.html +++ b/test/spec/meta/component-object-descriptor-test/component-object-descriptor-test-3.reel/component-object-descriptor-test-3.html @@ -2,9 +2,9 @@ - ComponentBlueprintTest3 + ComponentObjectDescriptorTest3 - + - \ No newline at end of file + diff --git a/test/spec/meta/component-blueprint-test/component-blueprint-test-3.reel/component-blueprint-test-3.js b/test/spec/meta/component-object-descriptor-test/component-object-descriptor-test-3.reel/component-object-descriptor-test-3.js similarity index 72% rename from test/spec/meta/component-blueprint-test/component-blueprint-test-3.reel/component-blueprint-test-3.js rename to test/spec/meta/component-object-descriptor-test/component-object-descriptor-test-3.reel/component-object-descriptor-test-3.js index c52af8aac4..4b666c6267 100644 --- a/test/spec/meta/component-blueprint-test/component-blueprint-test-3.reel/component-blueprint-test-3.js +++ b/test/spec/meta/component-object-descriptor-test/component-object-descriptor-test-3.reel/component-object-descriptor-test-3.js @@ -3,17 +3,17 @@ var Montage = require("montage").Montage, Component = require("montage/ui/component").Component; -var ComponentBlueprintTest3 = exports.ComponentBlueprintTest3 = Component.specialize( { +var ComponentObjectDescriptorTest3 = exports.ComponentObjectDescriptorTest3 = Component.specialize( { templateDidLoad: { value: function () { - //console.log("Component Blueprint Test 3 template did load"); + //console.log("Component ObjectDescriptor Test 3 template did load"); } }, deserializedFromTemplate: { value: function () { - //console.log("Component Blueprint Test 3 deserialized from template"); + //console.log("Component ObjectDescriptor Test 3 deserialized from template"); } }, diff --git a/test/spec/meta/component-blueprint-test/component-blueprint-test.html b/test/spec/meta/component-object-descriptor-test/component-object-descriptor-test.html similarity index 76% rename from test/spec/meta/component-blueprint-test/component-blueprint-test.html rename to test/spec/meta/component-object-descriptor-test/component-object-descriptor-test.html index 8daab61f6d..b285931803 100644 --- a/test/spec/meta/component-blueprint-test/component-blueprint-test.html +++ b/test/spec/meta/component-object-descriptor-test/component-object-descriptor-test.html @@ -7,7 +7,7 @@