From c8713aca90c61fd11ca50199ac5f3909f377e049 Mon Sep 17 00:00:00 2001 From: EisenbergEffect Date: Thu, 15 Aug 2013 10:18:59 -0400 Subject: [PATCH] 2.0.0 assets pushed. --- License.txt | 21 + README.md | 55 +- bower.json | 10 + css/durandal.css | 71 +++ img/icon.png | Bin 0 -> 6251 bytes img/ios-startup-image-landscape.png | Bin 0 -> 47031 bytes img/ios-startup-image-portrait.png | Bin 0 -> 59691 bytes js/activator.js | 617 ++++++++++++++++++ js/app.js | 136 ++++ js/binder.js | 151 +++++ js/composition.js | 621 ++++++++++++++++++ js/events.js | 216 +++++++ js/plugins/dialog.js | 402 ++++++++++++ js/plugins/history.js | 321 ++++++++++ js/plugins/http.js | 78 +++ js/plugins/observable.js | 332 ++++++++++ js/plugins/router.js | 941 ++++++++++++++++++++++++++++ js/plugins/serializer.js | 138 ++++ js/plugins/widget.js | 193 ++++++ js/system.js | 427 +++++++++++++ js/transitions/entrance.js | 79 +++ js/viewEngine.js | 159 +++++ js/viewLocator.js | 158 +++++ 23 files changed, 5123 insertions(+), 3 deletions(-) create mode 100644 License.txt create mode 100644 bower.json create mode 100644 css/durandal.css create mode 100644 img/icon.png create mode 100644 img/ios-startup-image-landscape.png create mode 100644 img/ios-startup-image-portrait.png create mode 100644 js/activator.js create mode 100644 js/app.js create mode 100644 js/binder.js create mode 100644 js/composition.js create mode 100644 js/events.js create mode 100644 js/plugins/dialog.js create mode 100644 js/plugins/history.js create mode 100644 js/plugins/http.js create mode 100644 js/plugins/observable.js create mode 100644 js/plugins/router.js create mode 100644 js/plugins/serializer.js create mode 100644 js/plugins/widget.js create mode 100644 js/system.js create mode 100644 js/transitions/entrance.js create mode 100644 js/viewEngine.js create mode 100644 js/viewLocator.js diff --git a/License.txt b/License.txt new file mode 100644 index 0000000..73c1b0b --- /dev/null +++ b/License.txt @@ -0,0 +1,21 @@ +The MIT License + +Copyright (c) 2012 Blue Spire Consulting, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md index 44d8d2d..b0c9052 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,53 @@ -Durandal-Bower -============== +![Durandal](http://durandaljs.com/media/DURANDAL-FINAL-HI-RES-LOGO-HOR-WEB.png) -The bower package repo. +Durandal is a cross-device, cross-platform client framework written in JavaScript and designed to make Single Page Applications (SPAs) easy to create and maintain. We've used it to build apps for PC, Mac, Linux, iOS and Android...and now it's your turn... + +[![Build Status](https://travis-ci.org/BlueSpire/Durandal.png?branch=master)](https://travis-ci.org/BlueSpire/Durandal) + +## Features + +* Clean MV* Architecture +* JS & HTML Modularity +* Simple App Lifecycle +* Eventing, Modals, Message Boxes, etc. +* Navigation & Screen State Management +* Consistent Async Programming w/ Promises +* App Bundling and Optimization +* Use any Backend Technology +* Built on top of [jQuery](http://jquery.com/), [Knockout](http://knockoutjs.com/) & [RequireJS](http://requirejs.org/). +* Integrates with popular CSS libraries such as [Bootstrap](http://twitter.github.com/bootstrap/) and [Foundation](http://foundation.zurb.com/). +* Make your own templatable and data-bindable widgets. + +## Documentation + +All the documentation is located on [the official site](http://durandaljs.com/), so have a look there for help on how to [get started](http://durandaljs.com/pages/get-started/), [read tutorials](http://durandaljs.com/pages/docs/), [view sample descriptions](http://durandaljs.com/documentation/Understanding-the-Samples/) and peruse the module reference docs. +If you want to keep up to date with the activity that is happening on the master branch, you can [subscribe to the commit feed](https://github.com/BlueSpire/durandal/commits/master.atom). + +## Community & Support + +Need help with something that the docs aren't providing an answer to? +Visit our [google group](https://groups.google.com/forum/?fromgroups#!forum/durandaljs) and join in the conversation. We also provide [full commercial support](http://durandaljs.com/pages/support/) no matter how large or small your team is. Additionally, we offer both [on-site and remote training](http://durandaljs.com/pages/training/). + +## License + +The MIT License + +Copyright (c) 2012 Blue Spire Consulting, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/bower.json b/bower.json new file mode 100644 index 0000000..6565c83 --- /dev/null +++ b/bower.json @@ -0,0 +1,10 @@ +{ + "name": "Durandal", + "version": "2.0.0", + "dependencies": { + "jquery":"1.9.1", + "requirejs":"2.1.8", + "requirejs-text":"2.0.3", + "knockout.js":"2.3.0" + } +} \ No newline at end of file diff --git a/css/durandal.css b/css/durandal.css new file mode 100644 index 0000000..82aeab4 --- /dev/null +++ b/css/durandal.css @@ -0,0 +1,71 @@ +/*! + * Durandal 2.0.0 Copyright (c) 2012 Blue Spire Consulting, Inc. All Rights Reserved. + * Available via the MIT license. + * see: http://durandaljs.com or https://github.com/BlueSpire/Durandal for details + */ + +.modalBlockout { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: black; + opacity: 0; + + pointer-events: auto; + + -webkit-backface-visibility: hidden; + + -webkit-transition: opacity 0.1s linear; + -moz-transition: opacity 0.1s linear; + -o-transition: opacity 0.1s linear; + transition: opacity 0.1s linear; +} + +.modalHost { + top: 50%; + left: 50%; + position: fixed; + opacity: 0; + + -webkit-backface-visibility: hidden; + + -webkit-transition: opacity 0.1s linear; + -moz-transition: opacity 0.1s linear; + -o-transition: opacity 0.1s linear; + transition: opacity 0.1s linear; +} + +.messageBox { + background-color: white; + border: 1px solid #999; + border: 1px solid rgba(0, 0, 0, 0.3); + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; + outline: none; + -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + -webkit-background-clip: padding-box; + -moz-background-clip: padding-box; + background-clip: padding-box; + min-width: 300px; +} + +.durandal-view-404 { + color: red; + margin: 8px 0; + padding: 8px; + + -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + + border: 1px solid #999; + border: 1px solid rgba(0, 0, 0, 0.3); + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; +} diff --git a/img/icon.png b/img/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..6a561710767e55b59ff457b4e139c1d4146926c7 GIT binary patch literal 6251 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 B8R7r{ literal 0 HcmV?d00001 diff --git a/img/ios-startup-image-landscape.png b/img/ios-startup-image-landscape.png new file mode 100644 index 0000000000000000000000000000000000000000..319904034f3680d01124aad7ad1225de2be0320f GIT binary patch literal 47031 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 ByVC#w literal 0 HcmV?d00001 diff --git a/img/ios-startup-image-portrait.png b/img/ios-startup-image-portrait.png new file mode 100644 index 0000000000000000000000000000000000000000..05aa4ed787caa233717ff9847479ff463df440ba GIT binary patch literal 59691 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

)GUdll5E`_2QHediOF#G=5Iz(LS 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 ZS(YdD&6#Th7D@O=SIa>2iH1$+{{!4`>v;eG literal 0 HcmV?d00001 diff --git a/js/activator.js b/js/activator.js new file mode 100644 index 0000000..3960c4b --- /dev/null +++ b/js/activator.js @@ -0,0 +1,617 @@ +/** + * Durandal 2.0.0 Copyright (c) 2012 Blue Spire Consulting, Inc. All Rights Reserved. + * Available via the MIT license. + * see: http://durandaljs.com or https://github.com/BlueSpire/Durandal for details. + */ +/** + * The activator module encapsulates all logic related to screen/component activation. + * An activator is essentially an asynchronous state machine that understands a particular state transition protocol. + * The protocol ensures that the following series of events always occur: `canDeactivate` (previous state), `canActivate` (new state), `deactivate` (previous state), `activate` (new state). + * Each of the _can_ callbacks may return a boolean, affirmative value or promise for one of those. If either of the _can_ functions yields a false result, then activation halts. + * @module activator + * @requires system + * @requires knockout + */ +define(['durandal/system', 'knockout'], function (system, ko) { + var activator; + + function ensureSettings(settings) { + if (settings == undefined) { + settings = {}; + } + + if (!settings.closeOnDeactivate) { + settings.closeOnDeactivate = activator.defaults.closeOnDeactivate; + } + + if (!settings.beforeActivate) { + settings.beforeActivate = activator.defaults.beforeActivate; + } + + if (!settings.afterDeactivate) { + settings.afterDeactivate = activator.defaults.afterDeactivate; + } + + if(!settings.affirmations){ + settings.affirmations = activator.defaults.affirmations; + } + + if (!settings.interpretResponse) { + settings.interpretResponse = activator.defaults.interpretResponse; + } + + if (!settings.areSameItem) { + settings.areSameItem = activator.defaults.areSameItem; + } + + return settings; + } + + function invoke(target, method, data) { + if (system.isArray(data)) { + return target[method].apply(target, data); + } + + return target[method](data); + } + + function deactivate(item, close, settings, dfd, setter) { + if (item && item.deactivate) { + system.log('Deactivating', item); + + var result; + try { + result = item.deactivate(close); + } catch(error) { + system.error(error); + dfd.resolve(false); + return; + } + + if (result && result.then) { + result.then(function() { + settings.afterDeactivate(item, close, setter); + dfd.resolve(true); + }, function(reason) { + system.log(reason); + dfd.resolve(false); + }); + } else { + settings.afterDeactivate(item, close, setter); + dfd.resolve(true); + } + } else { + if (item) { + settings.afterDeactivate(item, close, setter); + } + + dfd.resolve(true); + } + } + + function activate(newItem, activeItem, callback, activationData) { + if (newItem) { + if (newItem.activate) { + system.log('Activating', newItem); + + var result; + try { + result = invoke(newItem, 'activate', activationData); + } catch (error) { + system.error(error); + callback(false); + return; + } + + if (result && result.then) { + result.then(function() { + activeItem(newItem); + callback(true); + }, function(reason) { + system.log(reason); + callback(false); + }); + } else { + activeItem(newItem); + callback(true); + } + } else { + activeItem(newItem); + callback(true); + } + } else { + callback(true); + } + } + + function canDeactivateItem(item, close, settings) { + settings.lifecycleData = null; + + return system.defer(function (dfd) { + if (item && item.canDeactivate) { + var resultOrPromise; + try { + resultOrPromise = item.canDeactivate(close); + } catch(error) { + system.error(error); + dfd.resolve(false); + return; + } + + if (resultOrPromise.then) { + resultOrPromise.then(function(result) { + settings.lifecycleData = result; + dfd.resolve(settings.interpretResponse(result)); + }, function(reason) { + system.error(reason); + dfd.resolve(false); + }); + } else { + settings.lifecycleData = resultOrPromise; + dfd.resolve(settings.interpretResponse(resultOrPromise)); + } + } else { + dfd.resolve(true); + } + }).promise(); + }; + + function canActivateItem(newItem, activeItem, settings, activationData) { + settings.lifecycleData = null; + + return system.defer(function (dfd) { + if (newItem == activeItem()) { + dfd.resolve(true); + return; + } + + if (newItem && newItem.canActivate) { + var resultOrPromise; + try { + resultOrPromise = invoke(newItem, 'canActivate', activationData); + } catch (error) { + system.error(error); + dfd.resolve(false); + return; + } + + if (resultOrPromise.then) { + resultOrPromise.then(function(result) { + settings.lifecycleData = result; + dfd.resolve(settings.interpretResponse(result)); + }, function(reason) { + system.error(reason); + dfd.resolve(false); + }); + } else { + settings.lifecycleData = resultOrPromise; + dfd.resolve(settings.interpretResponse(resultOrPromise)); + } + } else { + dfd.resolve(true); + } + }).promise(); + }; + + /** + * An activator is a read/write computed observable that enforces the activation lifecycle whenever changing values. + * @class Activator + */ + function createActivator(initialActiveItem, settings) { + var activeItem = ko.observable(null); + var activeData; + + settings = ensureSettings(settings); + + var computed = ko.computed({ + read: function () { + return activeItem(); + }, + write: function (newValue) { + computed.viaSetter = true; + computed.activateItem(newValue); + } + }); + + computed.__activator__ = true; + + /** + * The settings for this activator. + * @property {ActivatorSettings} settings + */ + computed.settings = settings; + settings.activator = computed; + + /** + * An observable which indicates whether or not the activator is currently in the process of activating an instance. + * @method isActivating + * @return {boolean} + */ + computed.isActivating = ko.observable(false); + + /** + * Determines whether or not the specified item can be deactivated. + * @method canDeactivateItem + * @param {object} item The item to check. + * @param {boolean} close Whether or not to check if close is possible. + * @return {promise} + */ + computed.canDeactivateItem = function (item, close) { + return canDeactivateItem(item, close, settings); + }; + + /** + * Deactivates the specified item. + * @method deactivateItem + * @param {object} item The item to deactivate. + * @param {boolean} close Whether or not to close the item. + * @return {promise} + */ + computed.deactivateItem = function (item, close) { + return system.defer(function(dfd) { + computed.canDeactivateItem(item, close).then(function(canDeactivate) { + if (canDeactivate) { + deactivate(item, close, settings, dfd, activeItem); + } else { + computed.notifySubscribers(); + dfd.resolve(false); + } + }); + }).promise(); + }; + + /** + * Determines whether or not the specified item can be activated. + * @method canActivateItem + * @param {object} item The item to check. + * @param {object} activationData Data associated with the activation. + * @return {promise} + */ + computed.canActivateItem = function (newItem, activationData) { + return canActivateItem(newItem, activeItem, settings, activationData); + }; + + /** + * Activates the specified item. + * @method activateItem + * @param {object} newItem The item to activate. + * @param {object} newActivationData Data associated with the activation. + * @return {promise} + */ + computed.activateItem = function (newItem, newActivationData) { + var viaSetter = computed.viaSetter; + computed.viaSetter = false; + + return system.defer(function (dfd) { + if (computed.isActivating()) { + dfd.resolve(false); + return; + } + + computed.isActivating(true); + + var currentItem = activeItem(); + if (settings.areSameItem(currentItem, newItem, activeData, newActivationData)) { + computed.isActivating(false); + dfd.resolve(true); + return; + } + + computed.canDeactivateItem(currentItem, settings.closeOnDeactivate).then(function (canDeactivate) { + if (canDeactivate) { + computed.canActivateItem(newItem, newActivationData).then(function (canActivate) { + if (canActivate) { + system.defer(function (dfd2) { + deactivate(currentItem, settings.closeOnDeactivate, settings, dfd2); + }).promise().then(function () { + newItem = settings.beforeActivate(newItem, newActivationData); + activate(newItem, activeItem, function (result) { + activeData = newActivationData; + computed.isActivating(false); + dfd.resolve(result); + }, newActivationData); + }); + } else { + if (viaSetter) { + computed.notifySubscribers(); + } + + computed.isActivating(false); + dfd.resolve(false); + } + }); + } else { + if (viaSetter) { + computed.notifySubscribers(); + } + + computed.isActivating(false); + dfd.resolve(false); + } + }); + }).promise(); + }; + + /** + * Determines whether or not the activator, in its current state, can be activated. + * @method canActivate + * @return {promise} + */ + computed.canActivate = function () { + var toCheck; + + if (initialActiveItem) { + toCheck = initialActiveItem; + initialActiveItem = false; + } else { + toCheck = computed(); + } + + return computed.canActivateItem(toCheck); + }; + + /** + * Activates the activator, in its current state. + * @method activate + * @return {promise} + */ + computed.activate = function () { + var toActivate; + + if (initialActiveItem) { + toActivate = initialActiveItem; + initialActiveItem = false; + } else { + toActivate = computed(); + } + + return computed.activateItem(toActivate); + }; + + /** + * Determines whether or not the activator, in its current state, can be deactivated. + * @method canDeactivate + * @return {promise} + */ + computed.canDeactivate = function (close) { + return computed.canDeactivateItem(computed(), close); + }; + + /** + * Deactivates the activator, in its current state. + * @method deactivate + * @return {promise} + */ + computed.deactivate = function (close) { + return computed.deactivateItem(computed(), close); + }; + + computed.includeIn = function (includeIn) { + includeIn.canActivate = function () { + return computed.canActivate(); + }; + + includeIn.activate = function () { + return computed.activate(); + }; + + includeIn.canDeactivate = function (close) { + return computed.canDeactivate(close); + }; + + includeIn.deactivate = function (close) { + return computed.deactivate(close); + }; + }; + + if (settings.includeIn) { + computed.includeIn(settings.includeIn); + } else if (initialActiveItem) { + computed.activate(); + } + + computed.forItems = function (items) { + settings.closeOnDeactivate = false; + + settings.determineNextItemToActivate = function (list, lastIndex) { + var toRemoveAt = lastIndex - 1; + + if (toRemoveAt == -1 && list.length > 1) { + return list[1]; + } + + if (toRemoveAt > -1 && toRemoveAt < list.length - 1) { + return list[toRemoveAt]; + } + + return null; + }; + + settings.beforeActivate = function (newItem) { + var currentItem = computed(); + + if (!newItem) { + newItem = settings.determineNextItemToActivate(items, currentItem ? items.indexOf(currentItem) : 0); + } else { + var index = items.indexOf(newItem); + + if (index == -1) { + items.push(newItem); + } else { + newItem = items()[index]; + } + } + + return newItem; + }; + + settings.afterDeactivate = function (oldItem, close) { + if (close) { + items.remove(oldItem); + } + }; + + var originalCanDeactivate = computed.canDeactivate; + computed.canDeactivate = function (close) { + if (close) { + return system.defer(function (dfd) { + var list = items(); + var results = []; + + function finish() { + for (var j = 0; j < results.length; j++) { + if (!results[j]) { + dfd.resolve(false); + return; + } + } + + dfd.resolve(true); + } + + for (var i = 0; i < list.length; i++) { + computed.canDeactivateItem(list[i], close).then(function (result) { + results.push(result); + if (results.length == list.length) { + finish(); + } + }); + } + }).promise(); + } else { + return originalCanDeactivate(); + } + }; + + var originalDeactivate = computed.deactivate; + computed.deactivate = function (close) { + if (close) { + return system.defer(function (dfd) { + var list = items(); + var results = 0; + var listLength = list.length; + + function doDeactivate(item) { + computed.deactivateItem(item, close).then(function () { + results++; + items.remove(item); + if (results == listLength) { + dfd.resolve(); + } + }); + } + + for (var i = 0; i < listLength; i++) { + doDeactivate(list[i]); + } + }).promise(); + } else { + return originalDeactivate(); + } + }; + + return computed; + }; + + return computed; + } + + /** + * @class ActivatorSettings + * @static + */ + var activatorSettings = { + /** + * The default value passed to an object's deactivate function as its close parameter. + * @property {boolean} closeOnDeactivate + * @default true + */ + closeOnDeactivate: true, + /** + * Lower-cased words which represent a truthy value. + * @property {string[]} affirmations + * @default ['yes', 'ok', 'true'] + */ + affirmations: ['yes', 'ok', 'true'], + /** + * Interprets the response of a `canActivate` or `canDeactivate` call using the known affirmative values in the `affirmations` array. + * @method interpretResponse + * @param {object} value + * @return {boolean} + */ + interpretResponse: function(value) { + if(system.isObject(value)) { + value = value.can || false; + } + + if(system.isString(value)) { + return ko.utils.arrayIndexOf(this.affirmations, value.toLowerCase()) !== -1; + } + + return value; + }, + /** + * Determines whether or not the current item and the new item are the same. + * @method areSameItem + * @param {object} currentItem + * @param {object} newItem + * @param {object} currentActivationData + * @param {object} newActivationData + * @return {boolean} + */ + areSameItem: function(currentItem, newItem, currentActivationData, newActivationData) { + return currentItem == newItem; + }, + /** + * Called immediately before the new item is activated. + * @method beforeActivate + * @param {object} newItem + */ + beforeActivate: function(newItem) { + return newItem; + }, + /** + * Called immediately after the old item is deactivated. + * @method afterDeactivate + * @param {object} oldItem The previous item. + * @param {boolean} close Whether or not the previous item was closed. + * @param {function} setter The activate item setter function. + */ + afterDeactivate: function(oldItem, close, setter) { + if(close && setter) { + setter(null); + } + } + }; + + /** + * @class ActivatorModule + * @static + */ + activator = { + /** + * The default settings used by activators. + * @property {ActivatorSettings} defaults + */ + defaults: activatorSettings, + /** + * Creates a new activator. + * @method create + * @param {object} [initialActiveItem] The item which should be immediately activated upon creation of the ativator. + * @param {ActivatorSettings} [settings] Per activator overrides of the default activator settings. + * @return {Activator} The created activator. + */ + create: createActivator, + /** + * Determines whether or not the provided object is an activator or not. + * @method isActivator + * @param {object} object Any object you wish to verify as an activator or not. + * @return {boolean} True if the object is an activator; false otherwise. + */ + isActivator:function(object){ + return object && object.__activator__; + } + }; + + return activator; +}); diff --git a/js/app.js b/js/app.js new file mode 100644 index 0000000..b6d6916 --- /dev/null +++ b/js/app.js @@ -0,0 +1,136 @@ +/** + * Durandal 2.0.0 Copyright (c) 2012 Blue Spire Consulting, Inc. All Rights Reserved. + * Available via the MIT license. + * see: http://durandaljs.com or https://github.com/BlueSpire/Durandal for details. + */ +/** + * The app module controls app startup, plugin loading/configuration and root visual display. + * @module app + * @requires system + * @requires viewEngine + * @requires composition + * @requires events + * @requires jquery + */ +define(['durandal/system', 'durandal/viewEngine', 'durandal/composition', 'durandal/events', 'jquery'], function(system, viewEngine, composition, Events, $) { + var app, + allPluginIds = [], + allPluginConfigs = []; + + function loadPlugins(){ + return system.defer(function(dfd){ + if(allPluginIds.length == 0){ + dfd.resolve(); + return; + } + + system.acquire(allPluginIds).then(function(loaded){ + for(var i = 0; i < loaded.length; i++){ + var currentModule = loaded[i]; + + if(currentModule.install){ + var config = allPluginConfigs[i]; + if(!system.isObject(config)){ + config = {}; + } + + currentModule.install(config); + system.log('Plugin:Installed ' + allPluginIds[i]); + }else{ + system.log('Plugin:Loaded ' + allPluginIds[i]); + } + } + + dfd.resolve(); + }).fail(function(err){ + system.error('Failed to load plugin(s). Details: ' + err.message); + }); + }).promise(); + } + + /** + * @class AppModule + * @static + * @uses Events + */ + app = { + /** + * The title of your application. + * @property {string} title + */ + title: 'Application', + /** + * Configures one or more plugins to be loaded and installed into the application. + * @method configurePlugins + * @param {object} config Keys are plugin names. Values can be truthy, to simply install the plugin, or a configuration object to pass to the plugin. + * @param {string} [baseUrl] The base url to load the plugins from. + */ + configurePlugins:function(config, baseUrl){ + var pluginIds = system.keys(config); + baseUrl = baseUrl || 'plugins/'; + + if(baseUrl.indexOf('/', baseUrl.length - 1) === -1){ + baseUrl += '/'; + } + + for(var i = 0; i < pluginIds.length; i++){ + var key = pluginIds[i]; + allPluginIds.push(baseUrl + key); + allPluginConfigs.push(config[key]); + } + }, + /** + * Starts the application. + * @method start + * @return {promise} + */ + start: function() { + system.log('Application:Starting'); + + if (this.title) { + document.title = this.title; + } + + return system.defer(function (dfd) { + $(function() { + loadPlugins().then(function(){ + dfd.resolve(); + system.log('Application:Started'); + }); + }); + }).promise(); + }, + /** + * Sets the root module/view for the application. + * @method setRoot + * @param {string} root The root view or module. + * @param {string} [transition] The transition to use from the previous root (or splash screen) into the new root. + * @param {string} [applicationHost] The application host element or id. By default the id 'applicationHost' will be used. + */ + setRoot: function(root, transition, applicationHost) { + var hostElement, settings = { activate:true, transition: transition }; + + if (!applicationHost || system.isString(applicationHost)) { + hostElement = document.getElementById(applicationHost || 'applicationHost'); + } else { + hostElement = applicationHost; + } + + if (system.isString(root)) { + if (viewEngine.isViewUrl(root)) { + settings.view = root; + } else { + settings.model = root; + } + } else { + settings.model = root; + } + + composition.compose(hostElement, settings); + } + }; + + Events.includeIn(app); + + return app; +}); diff --git a/js/binder.js b/js/binder.js new file mode 100644 index 0000000..4174a77 --- /dev/null +++ b/js/binder.js @@ -0,0 +1,151 @@ +/** + * Durandal 2.0.0 Copyright (c) 2012 Blue Spire Consulting, Inc. All Rights Reserved. + * Available via the MIT license. + * see: http://durandaljs.com or https://github.com/BlueSpire/Durandal for details. + */ +/** + * The binder joins an object instance and a DOM element tree by applying databinding and/or invoking binding lifecycle callbacks (binding and bindingComplete). + * @module binder + * @requires system + * @requires knockout + */ +define(['durandal/system', 'knockout'], function (system, ko) { + var binder, + insufficientInfoMessage = 'Insufficient Information to Bind', + unexpectedViewMessage = 'Unexpected View Type', + bindingInstructionKey = 'durandal-binding-instruction', + koBindingContextKey = '__ko_bindingContext__'; + + function normalizeBindingInstruction(result){ + if(result === undefined){ + return { applyBindings: true }; + } + + if(system.isBoolean(result)){ + return { applyBindings:result }; + } + + if(result.applyBindings === undefined){ + result.applyBindings = true; + } + + return result; + } + + function doBind(obj, view, bindingTarget, data){ + if (!view || !bindingTarget) { + if (binder.throwOnErrors) { + system.error(insufficientInfoMessage); + } else { + system.log(insufficientInfoMessage, view, data); + } + return; + } + + if (!view.getAttribute) { + if (binder.throwOnErrors) { + system.error(unexpectedViewMessage); + } else { + system.log(unexpectedViewMessage, view, data); + } + return; + } + + var viewName = view.getAttribute('data-view'); + + try { + var instruction; + + if (obj && obj.binding) { + instruction = obj.binding(view); + } + + instruction = normalizeBindingInstruction(instruction); + binder.binding(data, view, instruction); + + if(instruction.applyBindings){ + system.log('Binding', viewName, data); + ko.applyBindings(bindingTarget, view); + }else if(obj){ + ko.utils.domData.set(view, koBindingContextKey, { $data:obj }); + } + + binder.bindingComplete(data, view, instruction); + + if (obj && obj.bindingComplete) { + obj.bindingComplete(view); + } + + ko.utils.domData.set(view, bindingInstructionKey, instruction); + return instruction; + } catch (e) { + e.message = e.message + ';\nView: ' + viewName + ";\nModuleId: " + system.getModuleId(data); + if (binder.throwOnErrors) { + system.error(e); + } else { + system.log(e.message); + } + } + } + + /** + * @class BinderModule + * @static + */ + return binder = { + /** + * Called before every binding operation. Does nothing by default. + * @method binding + * @param {object} data The data that is about to be bound. + * @param {DOMElement} view The view that is about to be bound. + * @param {object} instruction The object that carries the binding instructions. + */ + binding: system.noop, + /** + * Called after every binding operation. Does nothing by default. + * @method bindingComplete + * @param {object} data The data that has just been bound. + * @param {DOMElement} view The view that has just been bound. + * @param {object} instruction The object that carries the binding instructions. + */ + bindingComplete: system.noop, + /** + * Indicates whether or not the binding system should throw errors or not. + * @property {boolean} throwOnErrors + * @default false The binding system will not throw errors by default. Instead it will log them. + */ + throwOnErrors: false, + /** + * Gets the binding instruction that was associated with a view when it was bound. + * @method getBindingInstruction + * @param {DOMElement} view The view that was previously bound. + * @return {object} The object that carries the binding instructions. + */ + getBindingInstruction:function(view){ + return ko.utils.domData.get(view, bindingInstructionKey); + }, + /** + * Binds the view, preserving the existing binding context. Optionally, a new context can be created, parented to the previous context. + * @method bindContext + * @param {KnockoutBindingContext} bindingContext The current binding context. + * @param {DOMElement} view The view to bind. + * @param {object} [obj] The data to bind to, causing the creation of a child binding context if present. + */ + bindContext: function(bindingContext, view, obj) { + if (obj && bindingContext) { + bindingContext = bindingContext.createChildContext(obj); + } + + return doBind(obj, view, bindingContext, obj || (bindingContext ? bindingContext.$data : null)); + }, + /** + * Binds the view, preserving the existing binding context. Optionally, a new context can be created, parented to the previous context. + * @method bind + * @param {object} obj The data to bind to. + * @param {DOMElement} view The view to bind. + */ + bind: function(obj, view) { + return doBind(obj, view, obj, obj); + } + }; +}); diff --git a/js/composition.js b/js/composition.js new file mode 100644 index 0000000..f18a4e4 --- /dev/null +++ b/js/composition.js @@ -0,0 +1,621 @@ +/** + * Durandal 2.0.0 Copyright (c) 2012 Blue Spire Consulting, Inc. All Rights Reserved. + * Available via the MIT license. + * see: http://durandaljs.com or https://github.com/BlueSpire/Durandal for details. + */ +/** + * The composition module encapsulates all functionality related to visual composition. + * @module composition + * @requires system + * @requires viewLocator + * @requires binder + * @requires viewEngine + * @requires activator + * @requires jquery + * @requires knockout + */ +define(['durandal/system', 'durandal/viewLocator', 'durandal/binder', 'durandal/viewEngine', 'durandal/activator', 'jquery', 'knockout'], function (system, viewLocator, binder, viewEngine, activator, $, ko) { + var dummyModel = {}, + activeViewAttributeName = 'data-active-view', + composition, + compositionCompleteCallbacks = [], + compositionCount = 0, + compositionDataKey = 'durandal-composition-data', + partAttributeName = 'data-part', + partAttributeSelector = '[' + partAttributeName + ']', + bindableSettings = ['model', 'view', 'transition', 'area', 'strategy', 'activationData']; + + function getHostState(parent) { + var elements = []; + var state = { + childElements: elements, + activeView: null + }; + + var child = ko.virtualElements.firstChild(parent); + + while (child) { + if (child.nodeType == 1) { + elements.push(child); + if (child.getAttribute(activeViewAttributeName)) { + state.activeView = child; + } + } + + child = ko.virtualElements.nextSibling(child); + } + + if(!state.activeView){ + state.activeView = elements[0]; + } + + return state; + } + + function endComposition() { + compositionCount--; + + if (compositionCount === 0) { + setTimeout(function(){ + var i = compositionCompleteCallbacks.length; + + while(i--) { + compositionCompleteCallbacks[i](); + } + + compositionCompleteCallbacks = []; + }, 1); + } + } + + function tryActivate(context, successCallback, skipActivation) { + if(skipActivation){ + successCallback(); + } else if (context.activate && context.model && context.model.activate) { + var result; + + if(system.isArray(context.activationData)) { + result = context.model.activate.apply(context.model, context.activationData); + } else { + result = context.model.activate(context.activationData); + } + + if(result && result.then) { + result.then(successCallback); + } else if(result || result === undefined) { + successCallback(); + } else { + endComposition(); + } + } else { + successCallback(); + } + } + + function triggerAttach() { + var context = this; + + if (context.activeView) { + context.activeView.removeAttribute(activeViewAttributeName); + } + + if (context.child) { + if (context.model && context.model.attached) { + if (context.composingNewView || context.alwaysTriggerAttach) { + context.model.attached(context.child, context.parent, context); + } + } + + if (context.attached) { + context.attached(context.child, context.parent, context); + } + + context.child.setAttribute(activeViewAttributeName, true); + + if (context.composingNewView && context.model) { + if (context.model.compositionComplete) { + composition.current.complete(function () { + context.model.compositionComplete(context.child, context.parent, context); + }); + } + + if (context.model.detached) { + ko.utils.domNodeDisposal.addDisposeCallback(context.child, function () { + context.model.detached(context.child, context.parent, context); + }); + } + } + + if (context.compositionComplete) { + composition.current.complete(function () { + context.compositionComplete(context.child, context.parent, context); + }); + } + } + + endComposition(); + context.triggerAttach = system.noop; + } + + function shouldTransition(context) { + if (system.isString(context.transition)) { + if (context.activeView) { + if (context.activeView == context.child) { + return false; + } + + if (!context.child) { + return true; + } + + if (context.skipTransitionOnSameViewId) { + var currentViewId = context.activeView.getAttribute('data-view'); + var newViewId = context.child.getAttribute('data-view'); + return currentViewId != newViewId; + } + } + + return true; + } + + return false; + } + + function cloneNodes(nodesArray) { + for (var i = 0, j = nodesArray.length, newNodesArray = []; i < j; i++) { + var clonedNode = nodesArray[i].cloneNode(true); + newNodesArray.push(clonedNode); + } + return newNodesArray; + } + + function replaceParts(context){ + var parts = cloneNodes(context.parts); + var replacementParts = composition.getParts(parts); + var standardParts = composition.getParts(context.child); + + for (var partId in replacementParts) { + $(standardParts[partId]).replaceWith(replacementParts[partId]); + } + } + + function removePreviousView(parent){ + var children = ko.virtualElements.childNodes(parent), i, len; + + if(!system.isArray(children)){ + var arrayChildren = []; + + for(i = 0, len = children.length; i < len; i++){ + arrayChildren[i] = children[i]; + } + + children = arrayChildren; + } + + for(i = 1,len = children.length; i < len; i++){ + ko.removeNode(children[i]); + } + } + + /** + * @class CompositionTransaction + * @static + */ + var compositionTransaction = { + /** + * Registers a callback which will be invoked when the current composition transaction has completed. The transaction includes all parent and children compositions. + * @method complete + * @param {function} callback The callback to be invoked when composition is complete. + */ + complete: function (callback) { + compositionCompleteCallbacks.push(callback); + } + }; + + /** + * @class CompositionModule + * @static + */ + composition = { + /** + * Converts a transition name to its moduleId. + * @method convertTransitionToModuleId + * @param {string} name The name of the transtion. + * @return {string} The moduleId. + */ + convertTransitionToModuleId: function (name) { + return 'transitions/' + name; + }, + /** + * The name of the transition to use in all compositions. + * @property {string} defaultTransitionName + * @default null + */ + defaultTransitionName: null, + /** + * Represents the currently executing composition transaction. + * @property {CompositionTransaction} current + */ + current: compositionTransaction, + /** + * Registers a binding handler that will be invoked when the current composition transaction is complete. + * @method addBindingHandler + * @param {string} name The name of the binding handler. + * @param {object} [config] The binding handler instance. If none is provided, the name will be used to look up an existing handler which will then be converted to a composition handler. + * @param {function} [initOptionsFactory] If the registered binding needs to return options from its init call back to knockout, this function will server as a factory for those options. It will receive the same parameters that the init function does. + */ + addBindingHandler:function(name, config, initOptionsFactory){ + var key, + dataKey = 'composition-handler-' + name, + handler; + + config = config || ko.bindingHandlers[name]; + initOptionsFactory = initOptionsFactory || function(){ return undefined; }; + + handler = ko.bindingHandlers[name] = { + init: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) { + var data = { + trigger:ko.observable(null) + }; + + composition.current.complete(function(){ + if(config.init){ + config.init(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext); + } + + if(config.update){ + ko.utils.domData.set(element, dataKey, config); + data.trigger('trigger'); + } + }); + + ko.utils.domData.set(element, dataKey, data); + + return initOptionsFactory(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext); + }, + update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) { + var data = ko.utils.domData.get(element, dataKey); + + if(data.update){ + return data.update(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext); + } + + data.trigger(); + } + }; + + for (key in config) { + if (key !== "init" && key !== "update") { + handler[key] = config[key]; + } + } + }, + /** + * Gets an object keyed with all the elements that are replacable parts, found within the supplied elements. The key will be the part name and the value will be the element itself. + * @method getParts + * @param {DOMElement\DOMElement[]} elements The element(s) to search for parts. + * @return {object} An object keyed by part. + */ + getParts: function(elements) { + var parts = {}; + + if (!system.isArray(elements)) { + elements = [elements]; + } + + for (var i = 0; i < elements.length; i++) { + var element = elements[i]; + + if (element.getAttribute) { + var id = element.getAttribute(partAttributeName); + if (id) { + parts[id] = element; + } + + var childParts = $(partAttributeSelector, element) + .not($('[data-bind] ' + partAttributeSelector, element)); + + for (var j = 0; j < childParts.length; j++) { + var part = childParts.get(j); + parts[part.getAttribute(partAttributeName)] = part; + } + } + } + + return parts; + }, + cloneNodes:cloneNodes, + finalize: function (context) { + context.transition = context.transition || this.defaultTransitionName; + + if(!context.child && !context.activeView){ + if (!context.cacheViews) { + ko.virtualElements.emptyNode(context.parent); + } + + context.triggerAttach(); + }else if (shouldTransition(context)) { + var transitionModuleId = this.convertTransitionToModuleId(context.transition); + + system.acquire(transitionModuleId).then(function (transition) { + context.transition = transition; + + transition(context).then(function () { + if (!context.cacheViews) { + if(!context.child){ + ko.virtualElements.emptyNode(context.parent); + }else{ + removePreviousView(context.parent); + } + }else if(context.activeView){ + var instruction = binder.getBindingInstruction(context.activeView); + if(instruction.cacheViews != undefined && !instruction.cacheViews){ + ko.removeNode(context.activeView); + } + } + + context.triggerAttach(); + }); + }).fail(function(err){ + system.error('Failed to load transition (' + transitionModuleId + '). Details: ' + err.message); + }); + } else { + if (context.child != context.activeView) { + if (context.cacheViews && context.activeView) { + var instruction = binder.getBindingInstruction(context.activeView); + if(instruction.cacheViews != undefined && !instruction.cacheViews){ + ko.removeNode(context.activeView); + }else{ + $(context.activeView).hide(); + } + } + + if (!context.child) { + if (!context.cacheViews) { + ko.virtualElements.emptyNode(context.parent); + } + } else { + if (!context.cacheViews) { + removePreviousView(context.parent); + } + + $(context.child).show(); + } + } + + context.triggerAttach(); + } + }, + bindAndShow: function (child, context, skipActivation) { + context.child = child; + + if (context.cacheViews) { + context.composingNewView = (ko.utils.arrayIndexOf(context.viewElements, child) == -1); + } else { + context.composingNewView = true; + } + + tryActivate(context, function () { + if (context.binding) { + context.binding(context.child, context.parent, context); + } + + if (context.preserveContext && context.bindingContext) { + if (context.composingNewView) { + if(context.parts){ + replaceParts(context); + } + + $(child).hide(); + ko.virtualElements.prepend(context.parent, child); + + binder.bindContext(context.bindingContext, child, context.model); + } + } else if (child) { + var modelToBind = context.model || dummyModel; + var currentModel = ko.dataFor(child); + + if (currentModel != modelToBind) { + if (!context.composingNewView) { + $(child).remove(); + viewEngine.createView(child.getAttribute('data-view')).then(function(recreatedView) { + composition.bindAndShow(recreatedView, context, true); + }); + return; + } + + if(context.parts){ + replaceParts(context); + } + + $(child).hide(); + ko.virtualElements.prepend(context.parent, child); + + binder.bind(modelToBind, child); + } + } + + composition.finalize(context); + }, skipActivation); + }, + /** + * Eecutes the default view location strategy. + * @method defaultStrategy + * @param {object} context The composition context containing the model and possibly existing viewElements. + * @return {promise} A promise for the view. + */ + defaultStrategy: function (context) { + return viewLocator.locateViewForObject(context.model, context.area, context.viewElements); + }, + getSettings: function (valueAccessor, element) { + var value = valueAccessor(), + settings = ko.utils.unwrapObservable(value) || {}, + activatorPresent = activator.isActivator(value), + moduleId; + + if (system.isString(settings)) { + if (viewEngine.isViewUrl(settings)) { + settings = { + view: settings + }; + } else { + settings = { + model: settings, + activate: true + }; + } + + return settings; + } + + moduleId = system.getModuleId(settings); + if (moduleId) { + settings = { + model: settings, + activate: true + }; + + return settings; + } + + if(!activatorPresent && settings.model) { + activatorPresent = activator.isActivator(settings.model); + } + + for (var attrName in settings) { + if (ko.utils.arrayIndexOf(bindableSettings, attrName) != -1) { + settings[attrName] = ko.utils.unwrapObservable(settings[attrName]); + } else { + settings[attrName] = settings[attrName]; + } + } + + if (activatorPresent) { + settings.activate = false; + } else if (settings.activate === undefined) { + settings.activate = true; + } + + return settings; + }, + executeStrategy: function (context) { + context.strategy(context).then(function (child) { + composition.bindAndShow(child, context); + }); + }, + inject: function (context) { + if (!context.model) { + this.bindAndShow(null, context); + return; + } + + if (context.view) { + viewLocator.locateView(context.view, context.area, context.viewElements).then(function (child) { + composition.bindAndShow(child, context); + }); + return; + } + + if (!context.strategy) { + context.strategy = this.defaultStrategy; + } + + if (system.isString(context.strategy)) { + system.acquire(context.strategy).then(function (strategy) { + context.strategy = strategy; + composition.executeStrategy(context); + }).fail(function(err){ + system.error('Failed to load view strategy (' + context.strategy + '). Details: ' + err.message); + }); + } else { + this.executeStrategy(context); + } + }, + /** + * Initiates a composition. + * @method compose + * @param {DOMElement} element The DOMElement or knockout virtual element that serves as the parent for the composition. + * @param {object} settings The composition settings. + * @param {object} [bindingContext] The current binding context. + */ + compose: function (element, settings, bindingContext, fromBinding) { + compositionCount++; + + if(!fromBinding){ + settings = composition.getSettings(function() { return settings; }, element); + } + + var hostState = getHostState(element); + + settings.activeView = hostState.activeView; + settings.parent = element; + settings.triggerAttach = triggerAttach; + settings.bindingContext = bindingContext; + + if (settings.cacheViews && !settings.viewElements) { + settings.viewElements = hostState.childElements; + } + + if (!settings.model) { + if (!settings.view) { + this.bindAndShow(null, settings); + } else { + settings.area = settings.area || 'partial'; + settings.preserveContext = true; + + viewLocator.locateView(settings.view, settings.area, settings.viewElements).then(function (child) { + composition.bindAndShow(child, settings); + }); + } + } else if (system.isString(settings.model)) { + system.acquire(settings.model).then(function (module) { + settings.model = system.resolveObject(module); + composition.inject(settings); + }).fail(function(err){ + system.error('Failed to load composed module (' + settings.model + '). Details: ' + err.message); + }); + } else { + composition.inject(settings); + } + } + }; + + ko.bindingHandlers.compose = { + init: function() { + return { controlsDescendantBindings: true }; + }, + update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) { + var settings = composition.getSettings(valueAccessor, element); + if(settings.mode){ + var data = ko.utils.domData.get(element, compositionDataKey); + if(!data){ + var childNodes = ko.virtualElements.childNodes(element); + data = {}; + + if(settings.mode === 'inline'){ + data.view = viewEngine.ensureSingleElement(childNodes); + }else if(settings.mode === 'templated'){ + data.parts = cloneNodes(childNodes); + } + + ko.virtualElements.emptyNode(element); + ko.utils.domData.set(element, compositionDataKey, data); + } + + if(settings.mode === 'inline'){ + settings.view = data.view.cloneNode(true); + }else if(settings.mode === 'templated'){ + settings.parts = data.parts; + } + + settings.preserveContext = true; + } + + composition.compose(element, settings, bindingContext, true); + } + }; + + ko.virtualElements.allowedBindings.compose = true; + + return composition; +}); diff --git a/js/events.js b/js/events.js new file mode 100644 index 0000000..67967fd --- /dev/null +++ b/js/events.js @@ -0,0 +1,216 @@ +/** + * Durandal 2.0.0 Copyright (c) 2012 Blue Spire Consulting, Inc. All Rights Reserved. + * Available via the MIT license. + * see: http://durandaljs.com or https://github.com/BlueSpire/Durandal for details. + */ +/** + * Durandal events originate from backbone.js but also combine some ideas from signals.js as well as some additional improvements. + * Events can be installed into any object and are installed into the `app` module by default for convenient app-wide eventing. + * @module events + * @requires system + */ +define(['durandal/system'], function (system) { + var eventSplitter = /\s+/; + var Events = function() { }; + + /** + * Represents an event subscription. + * @class Subscription + */ + var Subscription = function(owner, events) { + this.owner = owner; + this.events = events; + }; + + /** + * Attaches a callback to the event subscription. + * @method then + * @param {function} callback The callback function to invoke when the event is triggered. + * @param {object} [context] An object to use as `this` when invoking the `callback`. + * @chainable + */ + Subscription.prototype.then = function (callback, context) { + this.callback = callback || this.callback; + this.context = context || this.context; + + if (!this.callback) { + return this; + } + + this.owner.on(this.events, this.callback, this.context); + return this; + }; + + /** + * Attaches a callback to the event subscription. + * @method on + * @param {function} [callback] The callback function to invoke when the event is triggered. If `callback` is not provided, the previous callback will be re-activated. + * @param {object} [context] An object to use as `this` when invoking the `callback`. + * @chainable + */ + Subscription.prototype.on = Subscription.prototype.then; + + /** + * Cancels the subscription. + * @method off + * @chainable + */ + Subscription.prototype.off = function () { + this.owner.off(this.events, this.callback, this.context); + return this; + }; + + /** + * Creates an object with eventing capabilities. + * @class Events + */ + + /** + * Creates a subscription or registers a callback for the specified event. + * @method on + * @param {string} events One or more events, separated by white space. + * @param {function} [callback] The callback function to invoke when the event is triggered. If `callback` is not provided, a subscription instance is returned. + * @param {object} [context] An object to use as `this` when invoking the `callback`. + * @return {Subscription|Events} A subscription is returned if no callback is supplied, otherwise the events object is returned for chaining. + */ + Events.prototype.on = function(events, callback, context) { + var calls, event, list; + + if (!callback) { + return new Subscription(this, events); + } else { + calls = this.callbacks || (this.callbacks = {}); + events = events.split(eventSplitter); + + while (event = events.shift()) { + list = calls[event] || (calls[event] = []); + list.push(callback, context); + } + + return this; + } + }; + + /** + * Removes the callbacks for the specified events. + * @method off + * @param {string} [events] One or more events, separated by white space to turn off. If no events are specified, then the callbacks will be removed. + * @param {function} [callback] The callback function to remove. If `callback` is not provided, all callbacks for the specified events will be removed. + * @param {object} [context] The object that was used as `this`. Callbacks with this context will be removed. + * @chainable + */ + Events.prototype.off = function(events, callback, context) { + var event, calls, list, i; + + // No events + if (!(calls = this.callbacks)) { + return this; + } + + //removing all + if (!(events || callback || context)) { + delete this.callbacks; + return this; + } + + events = events ? events.split(eventSplitter) : system.keys(calls); + + // Loop through the callback list, splicing where appropriate. + while (event = events.shift()) { + if (!(list = calls[event]) || !(callback || context)) { + delete calls[event]; + continue; + } + + for (i = list.length - 2; i >= 0; i -= 2) { + if (!(callback && list[i] !== callback || context && list[i + 1] !== context)) { + list.splice(i, 2); + } + } + } + + return this; + }; + + /** + * Triggers the specified events. + * @method trigger + * @param {string} [events] One or more events, separated by white space to trigger. + * @chainable + */ + Events.prototype.trigger = function(events) { + var event, calls, list, i, length, args, all, rest; + if (!(calls = this.callbacks)) { + return this; + } + + rest = []; + events = events.split(eventSplitter); + for (i = 1, length = arguments.length; i < length; i++) { + rest[i - 1] = arguments[i]; + } + + // For each event, walk through the list of callbacks twice, first to + // trigger the event, then to trigger any `"all"` callbacks. + while (event = events.shift()) { + // Copy callback lists to prevent modification. + if (all = calls.all) { + all = all.slice(); + } + + if (list = calls[event]) { + list = list.slice(); + } + + // Execute event callbacks. + if (list) { + for (i = 0, length = list.length; i < length; i += 2) { + list[i].apply(list[i + 1] || this, rest); + } + } + + // Execute "all" callbacks. + if (all) { + args = [event].concat(rest); + for (i = 0, length = all.length; i < length; i += 2) { + all[i].apply(all[i + 1] || this, args); + } + } + } + + return this; + }; + + /** + * Creates a function that will trigger the specified events when called. Simplifies proxying jQuery (or other) events through to the events object. + * @method proxy + * @param {string} events One or more events, separated by white space to trigger by invoking the returned function. + * @return {function} Calling the function will invoke the previously specified events on the events object. + */ + Events.prototype.proxy = function(events) { + var that = this; + return (function(arg) { + that.trigger(events, arg); + }); + }; + + /** + * Creates an object with eventing capabilities. + * @class EventsModule + * @static + */ + + /** + * Adds eventing capabilities to the specified object. + * @method includeIn + * @param {object} targetObject The object to add eventing capabilities to. + */ + Events.includeIn = function(targetObject) { + targetObject.on = Events.prototype.on; + targetObject.off = Events.prototype.off; + targetObject.trigger = Events.prototype.trigger; + targetObject.proxy = Events.prototype.proxy; + }; + + return Events; +}); diff --git a/js/plugins/dialog.js b/js/plugins/dialog.js new file mode 100644 index 0000000..4a8e56a --- /dev/null +++ b/js/plugins/dialog.js @@ -0,0 +1,402 @@ +/** + * Durandal 2.0.0 Copyright (c) 2012 Blue Spire Consulting, Inc. All Rights Reserved. + * Available via the MIT license. + * see: http://durandaljs.com or https://github.com/BlueSpire/Durandal for details. + */ +/** + * The dialog module enables the display of message boxes, custom modal dialogs and other overlays or slide-out UI abstractions. Dialogs are constructed by the composition system which interacts with a user defined dialog context. The dialog module enforced the activator lifecycle. + * @module dialog + * @requires system + * @requires app + * @requires composition + * @requires activator + * @requires viewEngine + * @requires jquery + * @requires knockout + */ +define(['durandal/system', 'durandal/app', 'durandal/composition', 'durandal/activator', 'durandal/viewEngine', 'jquery', 'knockout'], function (system, app, composition, activator, viewEngine, $, ko) { + var contexts = {}, + dialogCount = 0, + dialog; + + /** + * Models a message box's message, title and options. + * @class MessageBox + */ + var MessageBox = function(message, title, options) { + this.message = message; + this.title = title || MessageBox.defaultTitle; + this.options = options || MessageBox.defaultOptions; + }; + + /** + * Selects an option and closes the message box, returning the selected option through the dialog system's promise. + * @method selectOption + * @param {string} dialogResult The result to select. + */ + MessageBox.prototype.selectOption = function (dialogResult) { + dialog.close(this, dialogResult); + }; + + /** + * Provides the view to the composition system. + * @method getView + * @return {DOMElement} The view of the message box. + */ + MessageBox.prototype.getView = function(){ + return viewEngine.processMarkup(MessageBox.defaultViewMarkup); + }; + + /** + * Configures a custom view to use when displaying message boxes. + * @method setViewUrl + * @param {string} viewUrl The view url relative to the base url which the view locator will use to find the message box's view. + * @static + */ + MessageBox.setViewUrl = function(viewUrl){ + delete MessageBox.prototype.getView; + MessageBox.prototype.viewUrl = viewUrl; + }; + + /** + * The title to be used for the message box if one is not provided. + * @property {string} defaultTitle + * @default Application + * @static + */ + MessageBox.defaultTitle = app.title || 'Application'; + + /** + * The options to display in the message box of none are specified. + * @property {string[]} defaultOptions + * @default ['Ok'] + * @static + */ + MessageBox.defaultOptions = ['Ok']; + + /** + * The markup for the message box's view. + * @property {string} defaultViewMarkup + * @static + */ + MessageBox.defaultViewMarkup = [ + '

', + '', + '', + '', + '
' + ].join('\n'); + + function ensureDialogInstance(objOrModuleId) { + return system.defer(function(dfd) { + if (system.isString(objOrModuleId)) { + system.acquire(objOrModuleId).then(function (module) { + dfd.resolve(system.resolveObject(module)); + }).fail(function(err){ + system.error('Failed to load dialog module (' + objOrModuleId + '). Details: ' + err.message); + }); + } else { + dfd.resolve(objOrModuleId); + } + }).promise(); + } + + /** + * @class DialogModule + * @static + */ + dialog = { + /** + * The constructor function used to create message boxes. + * @property {MessageBox} MessageBox + */ + MessageBox:MessageBox, + /** + * The css zIndex that the last dialog was displayed at. + * @property {number} currentZIndex + */ + currentZIndex: 1050, + /** + * Gets the next css zIndex at which a dialog should be displayed. + * @method getNextZIndex + * @return {number} The next usable zIndex. + */ + getNextZIndex: function () { + return ++this.currentZIndex; + }, + /** + * Determines whether or not there are any dialogs open. + * @method isOpen + * @return {boolean} True if a dialog is open. false otherwise. + */ + isOpen: function() { + return dialogCount > 0; + }, + /** + * Gets the dialog context by name or returns the default context if no name is specified. + * @method getContext + * @param {string} [name] The name of the context to retrieve. + * @return {DialogContext} True context. + */ + getContext: function(name) { + return contexts[name || 'default']; + }, + /** + * Adds (or replaces) a dialog context. + * @method addContext + * @param {string} name The name of the context to add. + * @param {DialogContext} dialogContext The context to add. + */ + addContext: function(name, dialogContext) { + dialogContext.name = name; + contexts[name] = dialogContext; + + var helperName = 'show' + name.substr(0, 1).toUpperCase() + name.substr(1); + this[helperName] = function (obj, activationData) { + return this.show(obj, activationData, name); + }; + }, + createCompositionSettings: function(obj, dialogContext) { + var settings = { + model:obj, + activate:false + }; + + if (dialogContext.attached) { + settings.attached = dialogContext.attached; + } + + if (dialogContext.compositionComplete) { + settings.compositionComplete = dialogContext.compositionComplete; + } + + return settings; + }, + /** + * Gets the dialog model that is associated with the specified object. + * @method getDialog + * @param {object} obj The object for whom to retrieve the dialog. + * @return {Dialog} The dialog model. + */ + getDialog:function(obj){ + if(obj){ + return obj.__dialog__; + } + + return undefined; + }, + /** + * Closes the dialog associated with the specified object. + * @method close + * @param {object} obj The object whose dialog should be closed. + * @param {object} result* The results to return back to the dialog caller after closing. + */ + close:function(obj){ + var theDialog = this.getDialog(obj); + if(theDialog){ + var rest = Array.prototype.slice.call(arguments, 1); + theDialog.close.apply(theDialog, rest); + } + }, + /** + * Shows a dialog. + * @method show + * @param {object|string} obj The object (or moduleId) to display as a dialog. + * @param {object} [activationData] The data that should be passed to the object upon activation. + * @param {string} [context] The name of the dialog context to use. Uses the default context if none is specified. + * @return {Promise} A promise that resolves when the dialog is closed and returns any data passed at the time of closing. + */ + show: function(obj, activationData, context) { + var that = this; + var dialogContext = contexts[context || 'default']; + + return system.defer(function(dfd) { + ensureDialogInstance(obj).then(function(instance) { + var dialogActivator = activator.create(); + + dialogActivator.activateItem(instance, activationData).then(function (success) { + if (success) { + var theDialog = instance.__dialog__ = { + owner: instance, + context: dialogContext, + activator: dialogActivator, + close: function () { + var args = arguments; + dialogActivator.deactivateItem(instance, true).then(function (closeSuccess) { + if (closeSuccess) { + dialogCount--; + dialogContext.removeHost(theDialog); + delete instance.__dialog__; + + if(args.length == 0){ + dfd.resolve(); + }else if(args.length == 1){ + dfd.resolve(args[0]) + }else{ + dfd.resolve.apply(dfd, args); + } + } + }); + } + }; + + theDialog.settings = that.createCompositionSettings(instance, dialogContext); + dialogContext.addHost(theDialog); + + dialogCount++; + composition.compose(theDialog.host, theDialog.settings); + } else { + dfd.resolve(false); + } + }); + }); + }).promise(); + }, + /** + * Shows a message box. + * @method showMessage + * @param {string} message The message to display in the dialog. + * @param {string} [title] The title message. + * @param {string[]} [options] The options to provide to the user. + * @return {Promise} A promise that resolves when the message box is closed and returns the selected option. + */ + showMessage:function(message, title, options){ + if(system.isString(this.MessageBox)){ + return dialog.show(this.MessageBox, [ + message, + title || MessageBox.defaultTitle, + options || MessageBox.defaultOptions + ]); + } + + return dialog.show(new this.MessageBox(message, title, options)); + }, + /** + * Installs this module into Durandal; called by the framework. Adds `app.showDialog` and `app.showMessage` convenience methods. + * @method install + * @param {object} [config] Add a `messageBox` property to supply a custom message box constructor. Add a `messageBoxView` property to supply custom view markup for the built-in message box. + */ + install:function(config){ + app.showDialog = function(obj, activationData, context) { + return dialog.show(obj, activationData, context); + }; + + app.showMessage = function(message, title, options) { + return dialog.showMessage(message, title, options); + }; + + if(config.messageBox){ + dialog.MessageBox = config.messageBox; + } + + if(config.messageBoxView){ + dialog.MessageBox.prototype.getView = function(){ + return config.messageBoxView; + }; + } + } + }; + + /** + * @class DialogContext + */ + dialog.addContext('default', { + blockoutOpacity: .2, + removeDelay: 200, + /** + * In this function, you are expected to add a DOM element to the tree which will serve as the "host" for the modal's composed view. You must add a property called host to the modalWindow object which references the dom element. It is this host which is passed to the composition module. + * @method addHost + * @param {Dialog} theDialog The dialog model. + */ + addHost: function(theDialog) { + var body = $('body'); + var blockout = $('
') + .css({ 'z-index': dialog.getNextZIndex(), 'opacity': this.blockoutOpacity }) + .appendTo(body); + + var host = $('
') + .css({ 'z-index': dialog.getNextZIndex() }) + .appendTo(body); + + theDialog.host = host.get(0); + theDialog.blockout = blockout.get(0); + + if (!dialog.isOpen()) { + theDialog.oldBodyMarginRight = body.css("margin-right"); + theDialog.oldInlineMarginRight = body.get(0).style.marginRight; + + var html = $("html"); + var oldBodyOuterWidth = body.outerWidth(true); + var oldScrollTop = html.scrollTop(); + $("html").css("overflow-y", "hidden"); + var newBodyOuterWidth = $("body").outerWidth(true); + body.css("margin-right", (newBodyOuterWidth - oldBodyOuterWidth + parseInt(theDialog.oldBodyMarginRight)) + "px"); + html.scrollTop(oldScrollTop); // necessary for Firefox + } + }, + /** + * This function is expected to remove any DOM machinery associated with the specified dialog and do any other necessary cleanup. + * @method removeHost + * @param {Dialog} theDialog The dialog model. + */ + removeHost: function(theDialog) { + $(theDialog.host).css('opacity', 0); + $(theDialog.blockout).css('opacity', 0); + + setTimeout(function() { + ko.removeNode(theDialog.host); + ko.removeNode(theDialog.blockout); + }, this.removeDelay); + + if (!dialog.isOpen()) { + var html = $("html"); + var oldScrollTop = html.scrollTop(); // necessary for Firefox. + html.css("overflow-y", "").scrollTop(oldScrollTop); + + if(theDialog.oldInlineMarginRight) { + $("body").css("margin-right", theDialog.oldBodyMarginRight); + } else { + $("body").css("margin-right", ''); + } + } + }, + /** + * This function is called after the modal is fully composed into the DOM, allowing your implementation to do any final modifications, such as positioning or animation. You can obtain the original dialog object by using `getDialog` on context.model. + * @method compositionComplete + * @param {DOMElement} child The dialog view. + * @param {DOMElement} parent The parent view. + * @param {object} context The composition context. + */ + compositionComplete: function (child, parent, context) { + var $child = $(child); + var width = $child.width(); + var height = $child.height(); + var theDialog = dialog.getDialog(context.model); + + $child.css({ + 'margin-top': (-height / 2).toString() + 'px', + 'margin-left': (-width / 2).toString() + 'px' + }); + + $(theDialog.host).css('opacity', 1); + + if ($(child).hasClass('autoclose')) { + $(theDialog.blockout).click(function() { + theDialog.close(); + }); + } + + $('.autofocus', child).each(function() { + $(this).focus(); + }); + } + }); + + return dialog; +}); diff --git a/js/plugins/history.js b/js/plugins/history.js new file mode 100644 index 0000000..ec5c751 --- /dev/null +++ b/js/plugins/history.js @@ -0,0 +1,321 @@ +/** + * Durandal 2.0.0 Copyright (c) 2012 Blue Spire Consulting, Inc. All Rights Reserved. + * Available via the MIT license. + * see: http://durandaljs.com or https://github.com/BlueSpire/Durandal for details. + */ +/** + * This module is based on Backbone's core history support. It abstracts away the low level details of working with browser history and url changes in order to provide a solid foundation for a router. + * @module history + * @requires system + * @requires jquery + */ +define(['durandal/system', 'jquery'], function (system, $) { + // Cached regex for stripping a leading hash/slash and trailing space. + var routeStripper = /^[#\/]|\s+$/g; + + // Cached regex for stripping leading and trailing slashes. + var rootStripper = /^\/+|\/+$/g; + + // Cached regex for detecting MSIE. + var isExplorer = /msie [\w.]+/; + + // Cached regex for removing a trailing slash. + var trailingSlash = /\/$/; + + // Update the hash location, either replacing the current entry, or adding + // a new one to the browser history. + function updateHash(location, fragment, replace) { + if (replace) { + var href = location.href.replace(/(javascript:|#).*$/, ''); + location.replace(href + '#' + fragment); + } else { + // Some browsers require that `hash` contains a leading #. + location.hash = '#' + fragment; + } + }; + + /** + * @class HistoryModule + * @static + */ + var history = { + /** + * The setTimeout interval used when the browser does not support hash change events. + * @property {string} interval + * @default 50 + */ + interval: 50, + /** + * Indicates whether or not the history module is actively tracking history. + * @property {string} active + */ + active: false + }; + + // Ensure that `History` can be used outside of the browser. + if (typeof window !== 'undefined') { + history.location = window.location; + history.history = window.history; + } + + /** + * Gets the true hash value. Cannot use location.hash directly due to a bug in Firefox where location.hash will always be decoded. + * @method getHash + * @param {string} [window] The optional window instance + * @return {string} The hash. + */ + history.getHash = function(window) { + var match = (window || history).location.href.match(/#(.*)$/); + return match ? match[1] : ''; + }; + + /** + * Get the cross-browser normalized URL fragment, either from the URL, the hash, or the override. + * @method getFragment + * @param {string} fragment The fragment. + * @param {boolean} forcePushState Should we force push state? + * @return {string} he fragment. + */ + history.getFragment = function(fragment, forcePushState) { + if (fragment == null) { + if (history._hasPushState || !history._wantsHashChange || forcePushState) { + fragment = history.location.pathname; + var root = history.root.replace(trailingSlash, ''); + if (!fragment.indexOf(root)) { + fragment = fragment.substr(root.length); + } + } else { + fragment = history.getHash(); + } + } + + return fragment.replace(routeStripper, ''); + }; + + /** + * Activate the hash change handling, returning `true` if the current URL matches an existing route, and `false` otherwise. + * @method activate + * @param {HistoryOptions} options. + * @return {boolean|undefined} Returns true/false from loading the url unless the silent option was selected. + */ + history.activate = function(options) { + if (history.active) { + system.error("History has already been activated."); + } + + history.active = true; + + // Figure out the initial configuration. Do we need an iframe? + // Is pushState desired ... is it available? + history.options = system.extend({}, { root: '/' }, history.options, options); + history.root = history.options.root; + history._wantsHashChange = history.options.hashChange !== false; + history._wantsPushState = !!history.options.pushState; + history._hasPushState = !!(history.options.pushState && history.history && history.history.pushState); + + var fragment = history.getFragment(); + var docMode = document.documentMode; + var oldIE = (isExplorer.exec(navigator.userAgent.toLowerCase()) && (!docMode || docMode <= 7)); + + // Normalize root to always include a leading and trailing slash. + history.root = ('/' + history.root + '/').replace(rootStripper, '/'); + + if (oldIE && history._wantsHashChange) { + history.iframe = $('