From 22a66cb6e243a3f1c867b62e3942fd2e828019d9 Mon Sep 17 00:00:00 2001 From: Valerio Virgillito Date: Thu, 8 Mar 2012 13:56:09 -0800 Subject: integrating v0.7 montage into ninja Signed-off-by: Valerio Virgillito --- node_modules/montage/bin/montage | 3 + node_modules/montage/core/core.js | 20 +- node_modules/montage/core/deserializer.js | 115 ++- node_modules/montage/core/serializer.js | 45 +- node_modules/montage/montage.js | 68 +- node_modules/montage/node.js | 140 +++- node_modules/montage/package.json | 33 +- node_modules/montage/require/browser.js | 90 ++- node_modules/montage/require/node.js | 49 +- node_modules/montage/require/require.js | 205 +++--- node_modules/montage/ui/application.js | 4 +- .../montage/ui/bluemoon/progress.reel/progress.js | 20 +- node_modules/montage/ui/check-input.js | 2 +- node_modules/montage/ui/checkbox.reel/checkbox.js | 2 +- node_modules/montage/ui/component.js | 115 ++- node_modules/montage/ui/composer/press-composer.js | 9 +- .../montage/ui/composer/translate-composer.js | 77 +- .../montage/ui/condition.reel/condition.js | 24 +- .../montage/ui/controller/array-controller.js | 8 +- node_modules/montage/ui/list.reel/list.html | 10 +- node_modules/montage/ui/loader.reel/loader.js | 6 +- .../ui/loading-panel.reel/loading-panel.css | 38 +- .../ui/loading-panel.reel/loading-panel.html | 6 +- node_modules/montage/ui/native-control.js | 3 - .../montage/ui/popup/confirm.reel/confirm.js | 4 +- node_modules/montage/ui/popup/popup.reel/popup.js | 159 ++-- node_modules/montage/ui/progress.reel/progress.css | 51 -- .../montage/ui/progress.reel/progress.html | 32 - node_modules/montage/ui/progress.reel/progress.js | 144 +--- node_modules/montage/ui/progress.reel/rule.png | Bin 956 -> 0 bytes node_modules/montage/ui/progress.reel/scroll.png | Bin 272 -> 0 bytes .../montage/ui/radio-button.reel/radio-button.js | 3 +- .../montage/ui/repetition.reel/repetition.js | 127 +++- node_modules/montage/ui/scroll.js | 820 --------------------- .../montage/ui/scroller.reel/scroller.html | 1 + node_modules/montage/ui/scroller.reel/scroller.js | 36 +- .../montage/ui/select-input.reel/select-input.js | 115 ++- .../ui/skeleton/range-input.reel/range-input.css | 27 + .../ui/skeleton/range-input.reel/range-input.html | 62 ++ .../ui/skeleton/range-input.reel/range-input.js | 234 ++++++ node_modules/montage/ui/slot.reel/slot.js | 19 +- node_modules/montage/ui/template.js | 4 + node_modules/montage/ui/text-input.js | 16 +- node_modules/montage/ui/textarea.reel/textarea.js | 2 +- .../montage/ui/toggle-button.reel/toggle-button.js | 9 +- .../ui/toggle-switch.reel/toggle-switch.css | 162 ++++ .../ui/toggle-switch.reel/toggle-switch.html | 16 + .../montage/ui/toggle-switch.reel/toggle-switch.js | 424 +++++++++++ 48 files changed, 1994 insertions(+), 1565 deletions(-) create mode 100755 node_modules/montage/bin/montage delete mode 100755 node_modules/montage/ui/progress.reel/progress.css delete mode 100755 node_modules/montage/ui/progress.reel/progress.html delete mode 100755 node_modules/montage/ui/progress.reel/rule.png delete mode 100755 node_modules/montage/ui/progress.reel/scroll.png delete mode 100755 node_modules/montage/ui/scroll.js create mode 100644 node_modules/montage/ui/skeleton/range-input.reel/range-input.css create mode 100644 node_modules/montage/ui/skeleton/range-input.reel/range-input.html create mode 100644 node_modules/montage/ui/skeleton/range-input.reel/range-input.js create mode 100755 node_modules/montage/ui/toggle-switch.reel/toggle-switch.css create mode 100755 node_modules/montage/ui/toggle-switch.reel/toggle-switch.html create mode 100644 node_modules/montage/ui/toggle-switch.reel/toggle-switch.js diff --git a/node_modules/montage/bin/montage b/node_modules/montage/bin/montage new file mode 100755 index 00000000..aaa84003 --- /dev/null +++ b/node_modules/montage/bin/montage @@ -0,0 +1,3 @@ +#!/usr/bin/env node +// --harmony_weakmaps --harmony_proxies +require("../montage.js").initMontage(); diff --git a/node_modules/montage/core/core.js b/node_modules/montage/core/core.js index ff94f303..8fcf7977 100755 --- a/node_modules/montage/core/core.js +++ b/node_modules/montage/core/core.js @@ -71,14 +71,14 @@ Object.defineProperty(M, "create", { var newObject = Object.create(typeof aPrototype === "undefined" ? this : aPrototype); - if (typeof newObject.didCreate === "function") { - newObject.didCreate(); - } - if (newObject._dependenciesForProperty) { newObject._dependencyListeners = {}; } + if (typeof newObject.didCreate === "function") { + newObject.didCreate(); + } + return newObject; } else { var result = Object.create(aPrototype); @@ -713,13 +713,17 @@ if (!Object.seal) { */ Object.defineProperty(M, "callDelegateMethod", { value: function(name) { - var delegate, delegateFunctionName, delegateFunction; + var delegate = this.delegate, delegateFunctionName, delegateFunction; if (typeof this.identifier === "string") { delegateFunctionName = this.identifier + name.toCapitalized(); - } else { - delegateFunctionName = name; + if (delegate && typeof (delegateFunction = delegate[delegateFunctionName]) === "function") { + // remove first argument + Array.prototype.shift.call(arguments); + return delegateFunction.apply(delegate, arguments); + } } - if ((delegate = this.delegate) && typeof (delegateFunction = delegate[delegateFunctionName]) === "function") { + + if (delegate && typeof (delegateFunction = delegate[name]) === "function") { // remove first argument Array.prototype.shift.call(arguments); return delegateFunction.apply(delegate, arguments); diff --git a/node_modules/montage/core/deserializer.js b/node_modules/montage/core/deserializer.js index 0abc924b..7e812235 100755 --- a/node_modules/montage/core/deserializer.js +++ b/node_modules/montage/core/deserializer.js @@ -18,6 +18,14 @@ var Montage = require("montage").Montage, // By rebinding eval to a new name, it loses its ability to // capture the calling scope. var globalEval = eval; +var canEval = true; + +// CSP doesn't let you eval +try { + eval(""); +} catch(ex) { + canEval = false; +} /** @class module:montage/core/deserializer.Deserializer @@ -81,6 +89,7 @@ var Deserializer = Montage.create(Montage, /** @lends module:montage/core/deseri _reset: {value: function() { this._serializationString = null; this._requiredModuleIds = null; + this._areModulesLoaded = false; this._parseFunction = null; this._serialization = null; this._compiledDeserializationFunction = null; @@ -342,7 +351,12 @@ var Deserializer = Montage.create(Montage, /** @lends module:montage/core/deseri this._parseForModules(); } - this._loadModules(this._requiredModuleIds, callback); + if (this._requiredModuleIds.length > 0) { + this._loadModules(this._requiredModuleIds, callback); + } else { + this._areModulesLoaded = true; + return callback(); + } }}, /** @@ -356,16 +370,40 @@ var Deserializer = Montage.create(Montage, /** @lends module:montage/core/deseri /** @private */ + _findObjectNameRegExp: { + value: /([^\/]+?)(\.reel)?$/ + }, + _toCamelCaseRegExp: { + value: /(?:^|-)([^-])/g + }, + _replaceToCamelCase: { + value: function(_, g1) { return g1.toUpperCase() } + }, _parseForModules: {value: function() { var serialization = this._serialization, moduleIds = this._requiredModuleIds = [], - modules = this._modules; + modules = this._modules, + desc, moduleId; for (var label in serialization) { - var desc = serialization[label]; - var moduleId = desc.module; + desc = serialization[label]; + moduleId = null; + + if ("module" in desc) { + moduleId = desc.module; + } else if (name = /*assignment*/(desc.prototype || desc.object)) { + objectLocation = name.split("["); + moduleId = objectLocation[0]; + desc.module = moduleId; + if (objectLocation.length == 2) { + desc.name = objectLocation[1].slice(0, -1); + } else { + this._findObjectNameRegExp.test(moduleId); + desc.name = RegExp.$1.replace(this._toCamelCaseRegExp, this._replaceToCamelCase); + } + } - if (moduleId && moduleIds.indexOf(moduleId) == -1 && !modules[moduleId]) { + if (moduleId && !modules[moduleId] && moduleIds.indexOf(moduleId) == -1) { moduleIds.push(moduleId); } } @@ -404,7 +442,7 @@ var Deserializer = Montage.create(Montage, /** @lends module:montage/core/deseri */ _compileAndDeserialize: {value: function(element, deserialize) { var self = this, - serialization = this._serialization, + serialization, exportsStrings = "", unitsStrings = "", objectsStrings = "", @@ -418,6 +456,12 @@ var Deserializer = Montage.create(Montage, /** @lends module:montage/core/deseri objectNamesCounter = {}, label; + if (canEval) { + serialization = this._serialization; + } else { + serialization = JSON.parse(this._serializationString); + } + for (label in serialization) { var objectDesc = serialization[label]; @@ -452,28 +496,56 @@ var Deserializer = Montage.create(Montage, /** @lends module:montage/core/deseri } } - this._compiledDeserializationFunctionString = "(function() {\n" + requireStrings.join("\n") + "\nreturn function(element) {\nvar exports = {};\n" + exportsStrings + "\n\n" + objectsStrings + "\n\n" + unitsStrings + "\n\n" + cleanupStrings + "\nreturn exports;\n}}).call(this)"; + if (canEval) { + this._compiledDeserializationFunctionString = "(function() {\n" + requireStrings.join("\n") + "\nreturn function(element) {\nvar exports = {};\n" + exportsStrings + "\n\n" + objectsStrings + "\n\n" + unitsStrings + "\n\n" + cleanupStrings + "\nreturn exports;\n}}).call(this)"; + this._serializationString = this._serialization = serialization = null; + } + if (logger.isDebug) { logger.debug(this._compiledDeserializationFunctionString); } - this._serialization = serialization = null; - return exports; function deserializeObject(label, desc) { - var moduleId = desc.module, - name = desc.name, - objectName = name, - fqn = moduleId + "." + name, + var moduleId, + name, + instance, + objectName, + fqn, properties = desc.properties, + isType, object, counter, - propertiesString; + propertiesString, + objectLocation; + + if ("module" in desc) { + moduleId = desc.module; + objectName = name = desc.name; + } else { + objectLocation = (desc.prototype || desc.object).split("["); + // this code is actually only used when canEval == false, + // module+name are added when the modules are parsed but it's + // slow to redo the _serializationString in order to keep the + // added module+name when we do JSON.parse(_serializationString) + // at canEval == false. + moduleId = objectLocation[0]; + if (objectLocation.length == 2) { + objectName = name = objectLocation[1].slice(0, -1); + } else { + self._findObjectNameRegExp.test(moduleId); + objectName = name = RegExp.$1.replace(self._toCamelCaseRegExp, function(_, g1) { return g1.toUpperCase() }); + } + } + isType = "object" in desc; + fqn = moduleId + "." + name; if (deserialize) { if (self._objectLabels[label]) { exports[label] = object = self._objectLabels[label]; + } else if (isType) { + exports[label] = object = modules[moduleId][name]; } else { if (!(name in modules[moduleId])) { console.log("Warning: Object \"" + name + "\" not found at \"" + moduleId + "\" referenced from " + self._origin + "."); @@ -492,7 +564,7 @@ var Deserializer = Montage.create(Montage, /** @lends module:montage/core/deseri } if (fqn in requireStrings) { - name = requireStrings[fqn]; + objectName = requireStrings[fqn]; } else { counter = (objectNamesCounter[name] || 0) + 1; objectNamesCounter[name] = counter; @@ -504,11 +576,15 @@ var Deserializer = Montage.create(Montage, /** @lends module:montage/core/deseri } exportsStrings += 'if (this._objectLabels["' + label + '"]) {\n'; - exportsStrings += ' var ' + label + ' = exports. ' + label + ' = this._objectLabels["' + label + '"]\n'; + exportsStrings += ' var ' + label + ' = exports.' + label + ' = this._objectLabels["' + label + '"]\n'; exportsStrings += '} else {\n'; - exportsStrings += ' var ' + label + ' = exports. ' + label + ' = ' + objectName + '.create();\n'; - exportsStrings += ' Montage.getInfoForObject(' + label + ').label = "' + label + '";\n'; - exportsStrings += ' Object.defineProperty(' + label + ', "_suuid", {enumerable: false, value: "' + self.uuid + '-' + label + '"});\n'; + if (isType) { + exportsStrings += ' var ' + label + ' = exports.' + label + ' = ' + objectName + ';\n'; + } else { + exportsStrings += ' var ' + label + ' = exports.' + label + ' = ' + objectName + '.create();\n'; + exportsStrings += ' Montage.getInfoForObject(' + label + ').label = "' + label + '";\n'; + exportsStrings += ' Object.defineProperty(' + label + ', "_suuid", {enumerable: false, value: "' + self.uuid + '-' + label + '"});\n'; + } exportsStrings += '}\n'; propertiesString = deserializeValue(properties); @@ -519,6 +595,7 @@ var Deserializer = Montage.create(Montage, /** @lends module:montage/core/deseri delete desc.module; delete desc.name; + delete desc.object; delete desc.properties; propertiesString = deserializeValue(desc); diff --git a/node_modules/montage/core/serializer.js b/node_modules/montage/core/serializer.js index 449ebf7d..28f1b1d8 100755 --- a/node_modules/montage/core/serializer.js +++ b/node_modules/montage/core/serializer.js @@ -270,11 +270,16 @@ var Serializer = Montage.create(Montage, /** @lends module:montage/serializer.Se }}, _generateLabelForObject: {value: function(object) { - var objectName = Montage.getInfoForObject(object).objectName.toLowerCase(), - index = this._objectNamesIndex[objectName] || 1; + var objectName = object.identifier || Montage.getInfoForObject(object).objectName.toLowerCase(), + index = this._objectNamesIndex[objectName]; - this._objectNamesIndex[objectName] = index + 1; - return objectName + index; + if (index) { + this._objectNamesIndex[objectName] = index + 1; + return objectName + index; + } else { + this._objectNamesIndex[objectName] = 2; + return objectName; + } }}, _applySerializationUnits: {value: function(serializedUnits, object) { @@ -292,13 +297,22 @@ var Serializer = Montage.create(Montage, /** @lends module:montage/serializer.Se /** @private */ + _findObjectNameRegExp: { + value: /([^\/]+?)(\.reel)?$/ + }, + _toCamelCaseRegExp: { + value: /(?:^|-)([^-])/g + }, + _replaceToCamelCase: { + value: function(_, g1) { return g1.toUpperCase() } + }, _serializeObject: {value: function(object, properties, type) { var uuid = object.uuid, serializedReference = this._serializedReferences[uuid], serializedUnits, propertyNames, objectInfo, - label; + label, moduleId, name, defaultName; if (serializedReference) { return serializedReference; @@ -317,11 +331,26 @@ var Serializer = Montage.create(Montage, /** @lends module:montage/serializer.Se serializedUnits = {}; objectInfo = Montage.getInfoForObject(object); - serializedUnits.module = this._serializeValue(this._require.identify( + moduleId = this._require.identify( objectInfo.moduleId, - objectInfo.require) + objectInfo.require ); - serializedUnits.name = this._serializeValue(objectInfo.objectName); + name = objectInfo.objectName; + + this._findObjectNameRegExp.test(moduleId); + defaultName = RegExp.$1.replace(this._toCamelCaseRegExp, this._replaceToCamelCase); + + if (defaultName === name) { + name = moduleId; + } else { + name = moduleId + "[" + name + "]"; + } + + if (objectInfo.isInstance) { + serializedUnits.prototype = this._serializeValue(name); + } else { + serializedUnits.object = this._serializeValue(name); + } if (typeof object.serializeSelf === "function") { this._pushContextObject(object); diff --git a/node_modules/montage/montage.js b/node_modules/montage/montage.js index 495b6c72..e9e9b455 100755 --- a/node_modules/montage/montage.js +++ b/node_modules/montage/montage.js @@ -60,22 +60,30 @@ if (typeof window !== "undefined") { var params = platform.getParams(); var config = platform.getConfig(); + var montageLocation = URL.resolve(Require.getLocation(), params.montageLocation); + // setup the reel loader config.makeLoader = function (config) { - return exports.ReelLoader(config, - Require.DefaultLoaderConstructor(config)); + return exports.ReelLoader( + config, + Require.makeLoader(config) + ); }; // setup serialization compiler config.makeCompiler = function (config) { - return exports.TemplateCompiler(config, - exports.SerializationCompiler(config, - Require.DefaultCompilerConstructor(config))); + return exports.SerializationCompiler( + config, + exports.TemplateCompiler( + config, + Require.makeCompiler(config) + ) + ); }; var location = URL.resolve(config.location, params["package"] || "."); - Require.PackageSandbox(params.montageBase, config) + Require.loadPackage(montageLocation, config) .then(function (montageRequire) { montageRequire.inject("core/promise", Promise); montageRequire.inject("core/shim/timers", {}); @@ -183,11 +191,12 @@ if (typeof window !== "undefined") { return function(module) { if (!module.location) return; - var root = module.location.match(/(.*\/)?(?=[^\/]+\.html$)/); - if (root) { + var match = module.location.match(/(.*\/)?(?=[^\/]+\.html$)/); + if (match) { module.dependencies = module.dependencies || []; module.exports = { - root: root, + directory: match[1], + root: match, // deprecated content: module.text }; return module; @@ -216,7 +225,7 @@ if (typeof window !== "undefined") { var relativeElement = document.createElement("a"); exports.resolve = function (base, relative) { base = String(base); - if (!/^[\w\-]+:/.test(base)) { + if (!/^[\w\-]+:/.test(base)) { // isAbsolute(base) throw new Error("Can't resolve from a relative location: " + JSON.stringify(base) + " " + JSON.stringify(relative)); } var restore = baseElement.href; @@ -240,6 +249,7 @@ if (typeof window !== "undefined") { var i, j, match, script, + montage, attr, name; if (!this._params) { @@ -249,8 +259,16 @@ if (typeof window !== "undefined") { var scripts = document.getElementsByTagName("script"); for (i = 0; i < scripts.length; i++) { script = scripts[i]; + montage = false; if (script.src && (match = script.src.match(/^(.*)montage.js(?:[\?\.]|$)/i))) { - this._params.montageBase = match[1]; + this._params.montageLocation = match[1]; + montage = true; + } + if (script.hasAttribute("data-montage")) { + this._params.montageLocation = script.getAttribute("data-montage"); + montage = true; + } + if (montage) { if (script.dataset) { for (name in script.dataset) { this._params[name] = script.dataset[name]; @@ -304,17 +322,20 @@ if (typeof window !== "undefined") { "core/next-tick" ]; - // load in parallel - pending.forEach(function(name) { - var url = params.montageBase + name + ".js"; - var script = document.createElement("script"); - script.src = url; - script.onload = function () { - // remove clutter - script.parentNode.removeChild(script); - }; - document.getElementsByTagName("head")[0].appendChild(script); - }); + // load in parallel, but only if we’re not using a preloaded cache. + // otherwise, these scripts will be inlined after already + if (typeof BUNDLE === "undefined") { + pending.forEach(function(name) { + var url = params.montageLocation + name + ".js"; + var script = document.createElement("script"); + script.src = url; + script.onload = function () { + // remove clutter + script.parentNode.removeChild(script); + }; + document.getElementsByTagName("head")[0].appendChild(script); + }); + } // register module definitions for deferred, // serial execution @@ -395,7 +416,8 @@ if (typeof window !== "undefined") { exports.initMontage(); } } else { - exports.getPlatform(); // may cause additional exports to be injected + // may cause additional exports to be injected: + exports.getPlatform(); } }); diff --git a/node_modules/montage/node.js b/node_modules/montage/node.js index 3d0a1edb..100acac5 100644 --- a/node_modules/montage/node.js +++ b/node_modules/montage/node.js @@ -13,6 +13,10 @@ var Require = require("./require/require"); var Promise = require("./core/promise"); var URL = require("./core/url"); +var jsdom = require("jsdom").jsdom; +var Node = require("jsdom").level(1).Node; +var domToHtml = require("jsdom/lib/jsdom/browser/domtohtml").domToHtml; + exports.bootstrap = function (callback) { var command = process.argv.slice(0, 3); var args = process.argv.slice(2); @@ -33,27 +37,6 @@ exports.bootstrap = function (callback) { }); }; -MontageBoot.loadPackage = function (location, config) { - var config = {}; - - config.location = URL.resolve('file:/', location + '/'); - - // setup the reel loader - config.makeLoader = function (config) { - return MontageBoot.ReelLoader(config, - Require.DefaultLoaderConstructor(config)); - }; - - // setup serialization compiler - config.makeCompiler = function (config) { - return MontageBoot.TemplateCompiler(config, - MontageBoot.SerializationCompiler(config, - Require.DefaultCompilerConstructor(config))); - }; - - return Require.PackageSandbox(config.location, config); -}; - var findPackage = function (path, callback) { var directory = PATH.dirname(path); if (directory === path) @@ -82,3 +65,118 @@ var loadPackagedModule = function (directory, program, command, args) { .end(); }; +MontageBoot.loadPackage = function (location, config) { + var config = {}; + + config.location = URL.resolve(Require.getLocation(), location + '/'); + + // setup the reel loader + config.makeLoader = function (config) { + return MontageBoot.ReelLoader( + config, + Require.makeLoader(config) + ); + }; + + // setup serialization compiler + config.makeCompiler = function (config) { + return MontageBoot.TemplateCompiler( + config, + MontageBoot.SerializationCompiler( + config, + Require.makeCompiler(config) + ) + ); + }; + + return Require.loadPackage(config.location, config); +}; + +MontageBoot.TemplateLoader = function (config, load) { + return function(id, module) { + var html = id.match(/(.*\/)?(?=[^\/]+\.html$)/); + var serialization = id.match(/(?=[^\/]+\.json$)/); // XXX this is not necessarily a strong indicator of a serialization alone + if (html) { + return load(id, module) + .then(function () { + module.dependencies = parseHtmlDependencies(module.text, module.location); + return module; + }); + } else if (serialization) { + return load(id, module) + .then(function () { + module.dependencies = collectSerializationDependencies(module.text, []); + return module; + }); + } else { + return load(id, module); + } + }; +}; + +// add the TemplateLoader to the middleware chain +Require.makeLoader = (function (makeLoader) { + return function (config) { + return MontageBoot.TemplateLoader(config, makeLoader(config)); + }; +})(Require.makeLoader); + +var parseHtmlDependencies = function (text, location) { + var dependencies = []; + var document = jsdom(text, null, { + "features": { + "FetchExternalResources": false, + "ProcessExternalResources": false + } + }); + collectHtmlDependencies(document, dependencies); + return dependencies; +}; + +var collectHtmlDependencies = function (document, dependencies) { + visit(document, function (element) { + if (element.nodeType == Node.ELEMENT_NODE) { + if (element.tagName === "SCRIPT") { + if (element.getAttribute("type") === "text/montage-serialization") { + collectSerializationDependencies(getText(element), dependencies); + } + } else if (element.tagName === "LINK") { + if (element.getAttribute("type") === "text/montage-serialization") { + dependencies.push(element.getAttribute("href")); + } + } + } + }); +}; + +function visit(element, visitor) { + var pruned; + var prune = function () { + pruned = true; + }; + visitor(element, prune); + if (pruned) { + return; + } + element = element.firstChild; + while (element) { + visit(element, visitor); + element = element.nextSibling; + } +} + +function getText(element) { + return domToHtml(element._childNodes, true, true); +} + +var collectSerializationDependencies = function (text, dependencies) { + var serialization = JSON.parse(text); + Object.keys(serialization).forEach(function (label) { + var description = serialization[label]; + if (typeof description.module === "string") { + dependencies.push(description.module); + } + }); + return dependencies; +}; + diff --git a/node_modules/montage/package.json b/node_modules/montage/package.json index a7e04341..6422b58d 100755 --- a/node_modules/montage/package.json +++ b/node_modules/montage/package.json @@ -1,19 +1,27 @@ { "name": "montage", - "version": "0.6.0", + "version": "0.3.1", "description": "A UI Framework", "main": "montage", - "exclude": [ - "lab/benchmarks", - "lab/sandbox", - "examples", - "require/test", - "require/tests", - "etc" - ], "overlay": { - "montage": { - "main": "core/core" + "browser": { + "main": "core/core", + "exclude": [ + "lab/benchmarks", + "lab/sandbox", + "examples", + "require/test", + "require/tests", + "etc", + "node.js" + ], + "resources": [ + "montage.js", + "require/require.js", + "require/browser.js", + "core/next-tick.js", + "core/promise.js" + ] } }, "bin": { @@ -21,5 +29,8 @@ }, "devDependencies": { "test": ">=0.2.1" + }, + "engines": { + "node": ">=0.6.0 <0.6.11" } } diff --git a/node_modules/montage/require/browser.js b/node_modules/montage/require/browser.js index 3fdd58d4..f4a11d97 100755 --- a/node_modules/montage/require/browser.js +++ b/node_modules/montage/require/browser.js @@ -47,7 +47,9 @@ Require.read = function (url) { try { request.open(GET, url, true); - request.overrideMimeType(APPLICATION_JAVASCRIPT_MIMETYPE); + if (request.overrideMimeType) { + request.overrideMimeType(APPLICATION_JAVASCRIPT_MIMETYPE); + } request.onreadystatechange = function () { if (request.readyState === 4) { onload(); @@ -76,7 +78,7 @@ var globalEval = /*this.execScript ||*/eval; // For Firebug evaled code isn't debuggable otherwise // http://code.google.com/p/fbug/issues/detail?id=2198 if (global.navigator && global.navigator.userAgent.indexOf("Firefox") >= 0) { - globalEval = new Function("evalString", "return eval(evalString)"); + globalEval = new Function("_", "return eval(_)"); } var __FILE__String = "__FILE__", @@ -89,6 +91,8 @@ Require.Compiler = function (config) { return function(module) { if (module.factory || module.text === void 0) return module; + if (config.define) + throw new Error("Can't use eval."); // Here we use a couple tricks to make debugging better in various browsers: // TODO: determine if these are all necessary / the best options @@ -117,4 +121,86 @@ Require.Compiler = function (config) { } }; +Require.XhrLoader = function (config) { + return function (url, module) { + return Require.read(url) + .then(function (text) { + module.type = "javascript"; + module.text = text; + module.location = url; + }); + }; +}; + +var definitions = {}; +var getDefinition = function (hash, id) { + definitions[hash] = definitions[hash] || {}; + definitions[hash][id] = definitions[hash][id] || Promise.defer(); + return definitions[hash][id]; +}; +define = function (hash, id, module) { + getDefinition(hash, id).resolve(module); +}; + +Require.ScriptLoader = function (config) { + var hash = config.packageDescription.hash; + return function (location, module) { + return Promise.call(function () { + + // short-cut by predefinition + if (definitions[hash] && definitions[hash][module.id]) { + return definitions[hash][module.id].promise; + } + + if (/\.js$/.test(location)) { + location = location.replace(/\.js/, ".load.js"); + } else { + location += ".load.js"; + } + + var script = document.createElement("script"); + script.onload = function() { + script.parentNode.removeChild(script); + }; + script.onerror = function (error) { + script.parentNode.removeChild(script); + }; + script.src = location; + script.defer = true; + document.getElementsByTagName("head")[0].appendChild(script); + + return getDefinition(hash, module.id).promise + }) + .then(function (definition) { + delete definitions[hash][module.id]; + for (var name in definition) { + module[name] = definition[name]; + } + module.location = location; + module.directory = URL.resolve(location, "."); + }); + }; +}; + +Require.makeLoader = function (config) { + if (config.define) { + Loader = Require.ScriptLoader; + } else { + Loader = Require.XhrLoader; + } + return Require.MappingsLoader( + config, + Require.ExtensionsLoader( + config, + Require.PathsLoader( + config, + Require.MemoizedLoader( + config, + Loader(config) + ) + ) + ) + ); +}; + }); diff --git a/node_modules/montage/require/node.js b/node_modules/montage/require/node.js index 9fcea3f5..3ba5a322 100644 --- a/node_modules/montage/require/node.js +++ b/node_modules/montage/require/node.js @@ -40,10 +40,13 @@ Require.Compiler = function (config) { var names = ["require", "exports", "module"]; var scopeNames = Object.keys(config.scope); names.push.apply(names, scopeNames); - return function(module) { - if (module.factory) + return function (module) { + if (module.factory) { return module; - if (!module.factory && module.text !== void 0) { + } else if ( + module.text !== void 0 && + module.type === "javascript" + ) { var factory = globalEval( "(function(" + names.join(",") + "){" + module.text + @@ -59,18 +62,41 @@ Require.Compiler = function (config) { // https://developer.mozilla.org/en/JavaScript/Reference/Functions_and_function_scope //module.factory = new Function("require", "exports", "module", module.text + "\n//*/\n//@ sourceURL="+module.path); } - return module; }; }; -Require.DefaultLoaderConstructor = function(config) { +Require.Loader = function (config, load) { + return function (url, module) { + return Require.read(url) + .then(function (text) { + module.type = "javascript"; + module.text = text; + module.location = url; + }, function (reason, error, rejection) { + return load(url, module); + }); + }; +}; + +Require.NodeLoader = function (config) { + return function (url, module) { + var id = url.slice(config.location.length); + return { + type: "native", + exports: require(id), + location: url + } + }; +}; + +Require.makeLoader = function(config) { return Require.MappingsLoader( config, Require.ExtensionsLoader( config, Require.PathsLoader( config, - Require.CachingLoader( + Require.MemoizedLoader( config, Require.Loader( config, @@ -82,17 +108,6 @@ Require.DefaultLoaderConstructor = function(config) { ); }; -Require.NodeLoader = function (config) { - return function (url, module) { - var id = url.slice(config.location.length); - return { - type: "native", - exports: require(id), - location: url - } - }; -} - Require.main = function () { var require = Require.Sandbox(); require.async(process.argv[2]).end(); diff --git a/node_modules/montage/require/require.js b/node_modules/montage/require/require.js index 8273b660..aad6cef7 100755 --- a/node_modules/montage/require/require.js +++ b/node_modules/montage/require/require.js @@ -33,45 +33,46 @@ if (!this) throw new Error("Require does not work in strict mode."); - var global = this; var globalEval = eval; // reassigning causes eval to not use lexical scope. // Non-CommonJS speced extensions should be marked with an "// EXTENSION" comment. - // Sandbox is an instance of the loader system. Different sandboxes will have different instances of modules. - // Returns the root "require" function. If this root "require()" function is called the loader will be in synchronous mode. - // To get asynchronous loading you MUST call the root "require.async()". In async mode all subsequent calls to "require()" will - // be asynchronously loaded, and synchronously executed. - Require.Sandbox = function(config) { + Require.makeRequire = function (config) { + var require; + // Configuration defaults: config = config || {}; config.location = URL.resolve(config.location || Require.getLocation(), "."); config.lib = URL.resolve(config.location, config.lib || "."); config.paths = config.paths || [config.lib]; config.mappings = config.mappings || {}; // EXTENSION - config.exposedConfigs = config.exposedConfigs || Require.defaultExposedConfigs; - config.makeLoader = config.makeLoader || Require.DefaultLoaderConstructor; + config.exposedConfigs = config.exposedConfigs || Require.exposedConfigs; + config.makeLoader = config.makeLoader || Require.makeLoader; config.load = config.load || config.makeLoader(config); - config.makeCompiler = config.makeCompiler || Require.DefaultCompilerConstructor; + config.makeCompiler = config.makeCompiler || Require.makeCompiler; config.compile = config.compile || config.makeCompiler(config); - // Sandbox state: // Modules: { exports, id, location, directory, factory, dependencies, dependees, text, type } var modules = config.modules = config.modules || {}; - // Mapping from canonical IDs to the initial top ID used to load module - var locationsToIds = {}; + // produces an entry in the module state table, which gets built + // up through loading and execution, ultimately serving as the + // ``module`` free variable inside the corresponding module. function getModule(id) { if (!has(modules, id)) { modules[id] = { id: id, - display: config.location + "#" + id // EXTENSION + display: config.location + "#" + id, // EXTENSION + require: require, }; } return modules[id]; } - config.module = getModule; + // for preloading modules by their id and exports, useful to + // prevent wasteful multiple instantiation if a module was loaded + // in the bootstrapping process and can be trivially injected into + // the system. function inject(id, exports) { var module = getModule(id) module.exports = exports; @@ -83,59 +84,55 @@ var load = memoize(function (topId, viaId) { var module = getModule(topId); return Promise.call(function () { - // already loaded, already instantiated, or redirection + // if not already loaded, already instantiated, or + // configured as a redirection to another module if ( - module.factory !== void 0 || - module.exports !== void 0 || - module.redirect !== void 0 + module.factory === void 0 && + module.exports === void 0 && + module.redirect === void 0 ) { - return module; - // load - } else { + // load and + // trace progress Require.progress.requiredModules.push(module.display); return Promise.call(config.load, null, topId, module) .then(function () { Require.progress.loadedModules.push(module.display); - return module; }); } }) - .then(function (module) { - // analyze dependencies + .then(function () { + // compile and analyze dependencies config.compile(module); var dependencies = module.dependencies = module.dependencies || []; if (module.redirect !== void 0) { dependencies.push(module.redirect); } - return module; }); }); // Load a module definition, and the definitions of its transitive // dependencies - function deepLoad(id, viaId, loading) { + function deepLoad(topId, viaId, loading) { + var module = getModule(topId); // this is a memo of modules already being loaded so we don’t // data-lock on a cycle of dependencies. loading = loading || {}; // has this all happened before? will it happen again? - if (has(loading, id)) + if (has(loading, topId)) return; // break the cycle of violence. - loading[id] = true; // this has happened before - return load(id, viaId) - .then(function (module) { + loading[topId] = true; // this has happened before + return load(topId, viaId) + .then(function () { // load the transitive dependencies using the magic of // recursion. return Promise.all(module.dependencies.map(function (depId) { - depId = resolve(depId, id) + depId = resolve(depId, topId) // create dependees set, purely for debug purposes var module = getModule(depId); var dependees = module.dependees = module.dependees || {}; - dependees[id] = true; - return deepLoad(depId, id, loading); + dependees[topId] = true; + return deepLoad(depId, topId, loading); })) - .then(function () { - return module; - }) }) } @@ -169,7 +166,7 @@ // Execute the factory function: var returnValue = module.factory.call( // in the context of the module: - global, // this + void 0, // this (defaults to global) makeRequire(topId), // require module.exports, // exports module // module @@ -177,7 +174,10 @@ // Modules should never have a return value. if (returnValue !== void 0) { - console.warn('require: module "'+topId+'" returned a value.'); + console.warn( + 'require: module ' + JSON.stringify(topId) + + ' returned a value.' + ); } // Update the list of modules that are ready to use @@ -262,7 +262,8 @@ return require; } - return makeRequire(""); + require = makeRequire(""); + return require; }; Require.progress = { @@ -271,7 +272,7 @@ initializedModules: [] }; - Require.PackageSandbox = function (location, config) { + Require.loadPackage = function (location, config) { location = URL.resolve(location, "."); config = config || {}; var loadingPackages = config.loadingPackages = config.loadingPackages || {}; @@ -304,7 +305,7 @@ packageDescription, config ); - var pkg = Require.Sandbox(subconfig); + var pkg = Require.makeRequire(subconfig); loadedPackages[location] = pkg; return pkg; }); @@ -312,15 +313,15 @@ return loadingPackages[location]; }; - var _require = config.loadPackage(location); - _require.location = location; - _require.async = function (id, callback) { - return _require.then(function (require) { + var pkg = config.loadPackage(location); + pkg.location = location; + pkg.async = function (id, callback) { + return pkg.then(function (require) { return require.async(id, callback); }); }; - return _require; + return pkg; }; function Dependency(dependency) { @@ -340,6 +341,7 @@ config.name = description.name; config.location = location || Require.getLocation(); config.packageDescription = description; + config.define = description.define; // explicitly mask definitions and modules, which must // not apply to child packages var modules = config.modules = config.modules || {}; @@ -418,7 +420,7 @@ function has(object, property) { return Object.prototype.hasOwnProperty.call(object, property); - }; + } // Resolves CommonJS module IDs (not paths) Require.resolve = resolve; @@ -443,27 +445,6 @@ } } return target.join("/"); - }; - - // ES5 shim: - - // ES5 15.4.3.2 - if (!Array.isArray) { - Array.isArray = function(obj) { - return Object.prototype.toString.call(obj) == "[object Array]"; - }; - } - // ES5 15.2.3.14 - if (!Object.keys) { - Object.keys = function(object) { - var keys = []; - for (var name in object) { - if (Object.prototype.hasOwnProperty.call(object, name)) { - keys.push(name); - } - } - return keys; - }; } Require.base = function (location) { @@ -475,7 +456,7 @@ // Tests whether the location or URL is a absolute. Require.isAbsolute = function(location) { - return /^\w+:/.test(location); + return /^[\w\-]+:/.test(location); }; // Extracts dependencies by parsing code and looking for "require" (currently using a simple regexp) @@ -528,49 +509,47 @@ throw error; } }; - } + }; - Require.defaultExposedConfigs = [ + Require.exposedConfigs = [ "paths", "mappings", "location", "packageDescription", "packages", - "modules", - "module" + "modules" ]; - Require.DefaultCompilerConstructor = function(config) { - return Require.ShebangCompiler( - config, - Require.DependenciesCompiler( - config, - Require.LintCompiler( - config, - Require.Compiler(config) - ) - ) - ); - }; - - // Built-in loader "middleware": - - Require.DefaultLoaderConstructor = function(config) { - return Require.MappingsLoader( + Require.makeCompiler = function(config) { + return Require.JsonCompiler( config, - Require.ExtensionsLoader( + Require.ShebangCompiler( config, - Require.PathsLoader( + Require.DependenciesCompiler( config, - Require.MemoizedLoader( + Require.LintCompiler( config, - Require.Loader(config) + Require.Compiler(config) ) ) ) ); }; + Require.JsonCompiler = function (config, compile) { + return function (module) { + var json = module.id.match(/\.json$/); + if (json) { + module.exports = JSON.parse(module.text); + return module; + } else { + return compile(module); + } + }; + }; + + // Built-in loader "middleware": + // Using mappings hash to load modules that match a mapping. Require.MappingsLoader = function(config, load) { config.mappings = config.mappings || {}; @@ -616,8 +595,12 @@ var loadWithExtension = extensions.reduceRight(function (next, extension) { return function (id, module) { return load(id + "." + extension, module) - .fail(function (error) { - return next(id, module); + .fail(function (reason, error, rejection) { + if (/^Can't find /.test(reason)) { + return next(id, module); + } else { + return rejection; + } }); }; }, function (id, module) { @@ -635,7 +618,7 @@ return loadWithExtension(id, module); } } - } + }; // Attempts to load using multiple base paths (or one absolute path) with a single loader. Require.PathsLoader = function(config, load) { @@ -643,8 +626,12 @@ return function (id, module) { var newId = URL.resolve(path, id); return load(newId, module) - .fail(function () { - return next(id, module); + .fail(function (reason, error, rejection) { + if (/^Can't find /.test(reason)) { + return next(id, module); + } else { + return rejection; + } }); }; }, function (id, module) { @@ -665,26 +652,6 @@ return memoize(load, cache); }; - Require.Loader = function (config, load) { - return function (url, module) { - return Require.read(url) - .then(function (text) { - module.type = "javascript"; - module.text = text; - module.location = url; - }, function (reason, error, rejection) { - // This is a hook that allows a Loader to be chained to a - // fallback, such as the NodeLoader, if a local module can’t be - // found. - if (load) { - return load(url, module); - } else { - return rejection; - } - }); - }; - }; - var memoize = function (callback, cache) { cache = cache || {}; return function (key, arg) { diff --git a/node_modules/montage/ui/application.js b/node_modules/montage/ui/application.js index c7b3dc73..7cb4bd97 100755 --- a/node_modules/montage/ui/application.js +++ b/node_modules/montage/ui/application.js @@ -175,7 +175,7 @@ var Application = exports.Application = Montage.create(Montage, /** @lends monta _createPopupSlot: {value: function(zIndex) { var slotEl = document.createElement('div'); document.body.appendChild(slotEl); - slotEl.style['z-index'] = zIndex; + slotEl.style.zIndex = zIndex; slotEl.style.position = 'absolute'; var popupSlot = Slot.create(); @@ -221,7 +221,7 @@ var Application = exports.Application = Montage.create(Montage, /** @lends monta } // use the new zIndex for custom popup if(!isSystemPopup) { - popupSlot.element.style['z-index'] = zIndex; + popupSlot.element.style.zIndex = zIndex; } popupSlot.content = content; diff --git a/node_modules/montage/ui/bluemoon/progress.reel/progress.js b/node_modules/montage/ui/bluemoon/progress.reel/progress.js index 8bc68b05..20c60d94 100644 --- a/node_modules/montage/ui/bluemoon/progress.reel/progress.js +++ b/node_modules/montage/ui/bluemoon/progress.reel/progress.js @@ -43,8 +43,8 @@ exports.Progress = Montage.create(Component,/** @lends module:"montage/ui/bluemo set: function(val) { if(val !== this._value) { this._value = val; - if(this._value > this._maximumValue) { - this._value = this._maximumValue; + if(this._value > this._max) { + this._value = this._max; } if(this._value < 0) { this._value = 0; @@ -57,7 +57,7 @@ exports.Progress = Montage.create(Component,/** @lends module:"montage/ui/bluemo Description TODO @private */ - _maximumValue: { + _max: { enumerable: false, value: 100 }, @@ -66,15 +66,15 @@ exports.Progress = Montage.create(Component,/** @lends module:"montage/ui/bluemo @type {Function} @default {Number} 100 */ - maximumValue: { + max: { get: function() { - return this._maximumValue; + return this._max; }, set: function(val) { - if(val !== this._maximumValue) { - this._maximumValue = val; - if(this._maximumValue <= 0) { - this._maximumValue = 1; // Prevent divide by zero errors + if(val !== this._max) { + this._max = val; + if(this._max <= 0) { + this._max = 1; // Prevent divide by zero errors } this.needsDraw = true; } @@ -120,7 +120,7 @@ exports.Progress = Montage.create(Component,/** @lends module:"montage/ui/bluemo draw: { enumerable: false, value: function() { - var ratio = this._value / this._maximumValue; + var ratio = this._value / this._max; // constrain to interval [0, 1] ratio = Math.min(Math.max(ratio, 0), 1); // map into [0, 100] diff --git a/node_modules/montage/ui/check-input.js b/node_modules/montage/ui/check-input.js index 42538c02..1621eb45 100644 --- a/node_modules/montage/ui/check-input.js +++ b/node_modules/montage/ui/check-input.js @@ -69,7 +69,7 @@ var CheckInput = exports.CheckInput = Montage.create(NativeControl, { Stores if we need to fake checking. When preventDefault is called on touchstart and touchend events (e.g. by - the scrollview component) the checkbox doesn't check itself, so we need + the scroller component) the checkbox doesn't check itself, so we need to fake it later. @default false diff --git a/node_modules/montage/ui/checkbox.reel/checkbox.js b/node_modules/montage/ui/checkbox.reel/checkbox.js index df2995c3..c6364e97 100644 --- a/node_modules/montage/ui/checkbox.reel/checkbox.js +++ b/node_modules/montage/ui/checkbox.reel/checkbox.js @@ -9,7 +9,7 @@ var Montage = require("montage").Montage, var Checkbox = exports.Checkbox = Montage.create(CheckInput, {}); Checkbox.addAttributes({ - autofocus: 'off', // on/off + autofocus: {value: false, dataType: 'boolean'}, disabled: {value: false, dataType: 'boolean'}, checked: {value: false, dataType: 'boolean'}, form: null, diff --git a/node_modules/montage/ui/component.js b/node_modules/montage/ui/component.js index d347f655..69559fc1 100755 --- a/node_modules/montage/ui/component.js +++ b/node_modules/montage/ui/component.js @@ -59,7 +59,6 @@ var Component = exports.Component = Montage.create(Montage,/** @lends module:mon value: function() { var actionEvent = document.createEvent("CustomEvent"); actionEvent.initCustomEvent("action", true, true, null); - actionEvent.type = "action"; return actionEvent; } }, @@ -162,6 +161,15 @@ var Component = exports.Component = Montage.create(Montage,/** @lends module:mon } }, + setElementWithParentComponent: { + value: function(element, parent) { + this._alternateParentComponent = parent; + if (this.element != element) { + this.element = element; + } + } + }, + // access to the Application object /** Description TODO @@ -215,6 +223,11 @@ var Component = exports.Component = Montage.create(Montage,/** @lends module:mon return targetElementController; } }, + + _alternateParentComponent: { + value: null + }, + /** Description TODO @private @@ -235,21 +248,27 @@ var Component = exports.Component = Montage.create(Montage,/** @lends module:mon get: function() { var cachedParentComponent = this._cachedParentComponent; if (cachedParentComponent == null) { - var anElement = this.element, - aParentNode, - eventManager = this.eventManager; - if (anElement) { - while ((aParentNode = anElement.parentNode) !== null && eventManager.eventHandlerForElement(aParentNode) == null) { - anElement = aParentNode; - } - return (this._cachedParentComponent = aParentNode ? eventManager.eventHandlerForElement(aParentNode) : null); - } + return (this._cachedParentComponent = this.findParentComponent()); } else { return cachedParentComponent; } } }, + findParentComponent: { + value: function() { + var anElement = this.element, + aParentNode, + eventManager = this.eventManager; + if (anElement) { + while ((aParentNode = anElement.parentNode) !== null && eventManager.eventHandlerForElement(aParentNode) == null) { + anElement = aParentNode; + } + return aParentNode ? eventManager.eventHandlerForElement(aParentNode) : this._alternateParentComponent; + } + } + }, + querySelectorComponent: { value: function(selector) { if (typeof selector !== "string") { @@ -406,19 +425,30 @@ var Component = exports.Component = Montage.create(Montage,/** @lends module:mon attachToParentComponent: { value: function() { this._cachedParentComponent = null; - - var parentComponent = this.parentComponent; - + + var parentComponent = this.parentComponent, + childComponents, + childComponent; + if (parentComponent) { + childComponents = parentComponent.childComponents; + for (var i = 0; (childComponent = childComponents[i]); i++) { + var newParentComponent = childComponent.findParentComponent(); + if (newParentComponent === this) { + parentComponent.removeChildComponent(childComponent); + newParentComponent._addChildComponent(childComponent); + } + } + parentComponent._addChildComponent(this); } } }, - + detachFromParentComponent: { value: function() { var parentComponent = this.parentComponent; - + if (parentComponent) { parentComponent.removeChildComponent(this); } @@ -438,6 +468,7 @@ var Component = exports.Component = Montage.create(Montage,/** @lends module:mon if (ix > -1) { childComponents.splice(ix, 1); childComponent._cachedParentComponent = null; + childComponent._alternateParentComponent = null; } } }, @@ -458,7 +489,6 @@ var Component = exports.Component = Montage.create(Montage,/** @lends module:mon */ ownerComponent: { enumerable: false, - serializable: true, value: null }, /** @@ -488,7 +518,7 @@ var Component = exports.Component = Montage.create(Montage,/** @lends module:mon enumerable: false, value: null }, - + /** * Remove all bindings and starts buffering the needsDraw. * @function @@ -498,23 +528,20 @@ var Component = exports.Component = Montage.create(Montage,/** @lends module:mon this.needsDraw = false; this.traverseComponentTree(function(component) { Object.deleteBindings(component); - component.canDrawGate.setField("componentTreeLoaded", false); - component.blockDrawGate.setField("element", false); - component.blockDrawGate.setField("drawRequested", false); component.needsDraw = false; }); } }, - + originalContent: { value: null }, - + _newContent: { enumerable: false, value: null }, - + content: { get: function() { if (this._element) { @@ -526,21 +553,21 @@ var Component = exports.Component = Montage.create(Montage,/** @lends module:mon set: function(value) { var components = [], childNodes; - + this._newContent = value; this.needsDraw = true; - + if (typeof this.contentWillChange === "function") { this.contentWillChange(value); } - + // cleanup current content components = this.childComponents; for (var i = 0, component; (component = components[i]); i++) { component.detachFromParentComponent(); component.cleanupDeletedComponentTree(); } - + if (value instanceof Element) { findAndDetachComponents(value); } else { @@ -548,11 +575,11 @@ var Component = exports.Component = Montage.create(Montage,/** @lends module:mon findAndDetachComponents(value[i]); } } - + // find the component fringe and detach them from the component tree function findAndDetachComponents(node) { var component = node.controller; - + if (component) { component.detachFromParentComponent(); components.push(component); @@ -563,14 +590,14 @@ var Component = exports.Component = Montage.create(Montage,/** @lends module:mon } } } - +