Skip to content
Browse files

released version 1.5.0

  • Loading branch information...
1 parent 32d2a72 commit e1572859fd007fa0a4be05a6bba1be185ee16802 @podefr podefr committed Aug 4, 2013
Showing with 17,059 additions and 4,506 deletions.
  1. +2,920 −2,529 build/Olives-map
  2. +444 −194 build/Olives.js
  3. +28 −24 build/Olives.min.js
  4. +6 −2 build/src/Bind.plugin.js
  5. +2 −0 build/src/DomUtils.js
  6. +118 −116 build/src/Event.plugin.js
  7. +2 −0 build/src/LocalStore.js
  8. +125 −0 build/src/LocationRouter.js
  9. +4 −2 build/src/OObject.js
  10. +2 −0 build/src/Place.plugin.js
  11. +2 −0 build/src/Plugins.js
  12. +0 −172 build/src/Router.js
  13. +2 −0 build/src/SocketIOTransport.js
  14. +278 −0 build/src/Stack.js
  15. +342 −0 docs/1.5.0/files.html
  16. +285 −0 docs/1.5.0/index.html
  17. +885 −0 docs/1.5.0/symbols/BindPlugin.html
  18. +747 −0 docs/1.5.0/symbols/EventPlugin.html
  19. +412 −0 docs/1.5.0/symbols/LocalStore.html
  20. +545 −0 docs/1.5.0/symbols/LocationRouter.html
  21. +743 −0 docs/1.5.0/symbols/OObject.html
  22. +633 −0 docs/1.5.0/symbols/PlacePlugin.html
  23. +646 −0 docs/1.5.0/symbols/Plugins.html
  24. +759 −0 docs/1.5.0/symbols/SocketIOTransport.html
  25. +1,081 −0 docs/1.5.0/symbols/Stack.html
  26. +327 −0 docs/1.5.0/symbols/_global_.html
  27. +664 −0 docs/1.5.0/symbols/src/src_Bind.plugin.js.html
  28. +117 −0 docs/1.5.0/symbols/src/src_DomUtils.js.html
  29. +144 −0 docs/1.5.0/symbols/src/src_Event.plugin.js.html
  30. +112 −0 docs/1.5.0/symbols/src/src_LocalStore.js.html
  31. +133 −0 docs/1.5.0/symbols/src/src_LocationRouter.js.html
  32. +205 −0 docs/1.5.0/symbols/src/src_OObject.js.html
  33. +98 −0 docs/1.5.0/symbols/src/src_Place.plugin.js.html
  34. +165 −0 docs/1.5.0/symbols/src/src_Plugins.js.html
  35. +174 −0 docs/1.5.0/symbols/src/src_SocketIOTransport.js.html
  36. +286 −0 docs/1.5.0/symbols/src/src_Stack.js.html
  37. +29 −1 docs/latest/files.html
  38. +18 −1 docs/latest/index.html
  39. +8 −4 docs/latest/symbols/BindPlugin.html
  40. +5 −1 docs/latest/symbols/EventPlugin.html
  41. +5 −1 docs/latest/symbols/LocalStore.html
  42. +545 −0 docs/latest/symbols/LocationRouter.html
  43. +5 −1 docs/latest/symbols/OObject.html
  44. +11 −7 docs/latest/symbols/PlacePlugin.html
  45. +5 −1 docs/latest/symbols/Plugins.html
  46. +5 −1 docs/latest/symbols/SocketIOTransport.html
  47. +1,081 −0 docs/latest/symbols/Stack.html
  48. +5 −1 docs/latest/symbols/_global_.html
  49. +635 −623 docs/latest/symbols/src/src_Bind.plugin.js.html
  50. +101 −99 docs/latest/symbols/src/src_DomUtils.js.html
  51. +121 −119 docs/latest/symbols/src/src_Event.plugin.js.html
  52. +85 −83 docs/latest/symbols/src/src_LocalStore.js.html
  53. +133 −0 docs/latest/symbols/src/src_LocationRouter.js.html
  54. +179 −173 docs/latest/symbols/src/src_OObject.js.html
  55. +75 −73 docs/latest/symbols/src/src_Place.plugin.js.html
  56. +134 −132 docs/latest/symbols/src/src_Plugins.js.html
  57. +152 −146 docs/latest/symbols/src/src_SocketIOTransport.js.html
  58. +286 −0 docs/latest/symbols/src/src_Stack.js.html
  59. BIN release/Olives-1.5.0.tgz
View
5,449 build/Olives-map
2,920 additions, 2,529 deletions not shown because the diff is too large. Please use a local Git client to view these changes.
View
638 build/Olives.js
@@ -12,6 +12,8 @@
define('DomUtils',["Tools"], function (Tools) {
+
+
return {
/**
* Returns a NodeList including the given dom node,
@@ -127,6 +129,8 @@ define('Bind.plugin',["Store", "Observable", "Tools", "DomUtils"],
*/
function BindPlugin(Store, Observable, Tools, DomUtils) {
+
+
return function BindPluginConstructor($model, $bindings) {
/**
@@ -312,7 +316,8 @@ function BindPlugin(Store, Observable, Tools, DomUtils) {
* @returns the value
*/
this.setStart = function setStart(start) {
- return _start = parseInt(start, 10);
+ _start = parseInt(start, 10);
+ return _start;
};
/**
@@ -331,7 +336,8 @@ function BindPlugin(Store, Observable, Tools, DomUtils) {
* @returns the value
*/
this.setNb = function setNb(nb) {
- return _nb = nb == "*" ? nb : parseInt(nb, 10);
+ _nb = nb == "*" ? nb : parseInt(nb, 10);
+ return _nb;
};
/**
@@ -781,122 +787,124 @@ define('Event.plugin',["DomUtils"],
*/
function EventPlugin(Utils) {
- /**
- * The event plugin constructor.
- * ex: new EventPlugin({method: function(){} ...}, false);
- * @param {Object} the object that has the event handling methods
- * @param {Boolean} $isMobile if the event handler has to map with touch events
- */
- return function EventPluginConstructor($parent, $isMobile) {
+
- /**
- * The parent callback
- * @private
- */
- var _parent = null,
+ /**
+ * The event plugin constructor.
+ * ex: new EventPlugin({method: function(){} ...}, false);
+ * @param {Object} the object that has the event handling methods
+ * @param {Boolean} $isMobile if the event handler has to map with touch events
+ */
+ return function EventPluginConstructor($parent, $isMobile) {
- /**
- * The mapping object.
- * @private
- */
- _map = {
- "mousedown" : "touchstart",
- "mouseup" : "touchend",
- "mousemove" : "touchmove"
- },
+ /**
+ * The parent callback
+ * @private
+ */
+ var _parent = null,
- /**
- * Is touch device.
- * @private
- */
- _isMobile = !!$isMobile;
+ /**
+ * The mapping object.
+ * @private
+ */
+ _map = {
+ "mousedown" : "touchstart",
+ "mouseup" : "touchend",
+ "mousemove" : "touchmove"
+ },
- /**
- * Add mapped event listener (for testing purpose).
- * @private
- */
- this.addEventListener = function addEventListener(node, event, callback, useCapture) {
- node.addEventListener(this.map(event), callback, !!useCapture);
- };
+ /**
+ * Is touch device.
+ * @private
+ */
+ _isMobile = !!$isMobile;
- /**
- * Listen to DOM events.
- * @param {Object} node DOM node
- * @param {String} name event's name
- * @param {String} listener callback's name
- * @param {String} useCapture string
- */
- this.listen = function listen(node, name, listener, useCapture) {
- this.addEventListener(node, name, function(e){
- _parent[listener].call(_parent, e, node);
- }, !!useCapture);
- };
+ /**
+ * Add mapped event listener (for testing purpose).
+ * @private
+ */
+ this.addEventListener = function addEventListener(node, event, callback, useCapture) {
+ node.addEventListener(this.map(event), callback, !!useCapture);
+ };
- /**
- * Delegate the event handling to a parent DOM element
- * @param {Object} node DOM node
- * @param {String} selector CSS3 selector to the element that listens to the event
- * @param {String} name event's name
- * @param {String} listener callback's name
- * @param {String} useCapture string
- */
- this.delegate = function delegate(node, selector, name, listener, useCapture) {
- this.addEventListener(node, name, function(event){
- if (Utils.matches(node, selector, event.target)) {
- _parent[listener].call(_parent, event, node);
- }
- }, !!useCapture);
- };
+ /**
+ * Listen to DOM events.
+ * @param {Object} node DOM node
+ * @param {String} name event's name
+ * @param {String} listener callback's name
+ * @param {String} useCapture string
+ */
+ this.listen = function listen(node, name, listener, useCapture) {
+ this.addEventListener(node, name, function(e){
+ _parent[listener].call(_parent, e, node);
+ }, !!useCapture);
+ };
- /**
- * Get the parent object.
- * @return {Object} the parent object
- */
- this.getParent = function getParent() {
- return _parent;
- };
+ /**
+ * Delegate the event handling to a parent DOM element
+ * @param {Object} node DOM node
+ * @param {String} selector CSS3 selector to the element that listens to the event
+ * @param {String} name event's name
+ * @param {String} listener callback's name
+ * @param {String} useCapture string
+ */
+ this.delegate = function delegate(node, selector, name, listener, useCapture) {
+ this.addEventListener(node, name, function(event){
+ if (Utils.matches(node, selector, event.target)) {
+ _parent[listener].call(_parent, event, node);
+ }
+ }, !!useCapture);
+ };
- /**
- * Set the parent object.
- * The parent object is an object which the functions are called by node listeners.
- * @param {Object} the parent object
- * @return true if object has been set
- */
- this.setParent = function setParent(parent) {
- if (parent instanceof Object){
- _parent = parent;
- return true;
- }
- return false;
- };
+ /**
+ * Get the parent object.
+ * @return {Object} the parent object
+ */
+ this.getParent = function getParent() {
+ return _parent;
+ };
- /**
- * Get event mapping.
- * @param {String} event's name
- * @return the mapped event's name
- */
- this.map = function map(name) {
- return _isMobile ? (_map[name] || name) : name;
- };
+ /**
+ * Set the parent object.
+ * The parent object is an object which the functions are called by node listeners.
+ * @param {Object} the parent object
+ * @return true if object has been set
+ */
+ this.setParent = function setParent(parent) {
+ if (parent instanceof Object){
+ _parent = parent;
+ return true;
+ }
+ return false;
+ };
- /**
- * Set event mapping.
- * @param {String} event's name
- * @param {String} event's value
- * @return true if mapped
- */
- this.setMap = function setMap(name, value) {
- if (typeof name == "string" &&
- typeof value == "string") {
- _map[name] = value;
- return true;
- }
- return false;
- };
+ /**
+ * Get event mapping.
+ * @param {String} event's name
+ * @return the mapped event's name
+ */
+ this.map = function map(name) {
+ return _isMobile ? (_map[name] || name) : name;
+ };
- //init
- this.setParent($parent);
- };
+ /**
+ * Set event mapping.
+ * @param {String} event's name
+ * @param {String} event's value
+ * @return true if mapped
+ */
+ this.setMap = function setMap(name, value) {
+ if (typeof name == "string" &&
+ typeof value == "string") {
+ _map[name] = value;
+ return true;
+ }
+ return false;
+ };
+
+ //init
+ this.setParent($parent);
+ };
});
@@ -917,6 +925,8 @@ define('LocalStore',["Store", "Tools"],
*/
function LocalStore(Store, Tools) {
+
+
function LocalStoreConstructor() {
/**
@@ -1022,6 +1032,8 @@ define('Plugins',["Tools", "DomUtils"],
*/
function Plugins(Tools, DomUtils) {
+
+
return function PluginsConstructor($plugins) {
/**
@@ -1174,6 +1186,8 @@ define('OObject',["StateMachine", "Store", "Plugins", "DomUtils", "Tools"],
*/
function OObject(StateMachine, Store, Plugins, DomUtils, Tools) {
+
+
return function OObjectConstructor(otherStore) {
/**
@@ -1206,7 +1220,7 @@ function OObject(StateMachine, Store, Plugins, DomUtils, Tools) {
// as it wouldn't be possible to know which node would belong to which UI
// This is probably a DOM limitation.
if (baseNode.childNodes.length > 1) {
- throw Error("UI.template should have only one parent node");
+ throw new Error("UI.template should have only one parent node");
} else {
UI.dom = baseNode.childNodes[0];
}
@@ -1215,7 +1229,7 @@ function OObject(StateMachine, Store, Plugins, DomUtils, Tools) {
} else {
// An explicit message I hope
- throw Error("UI.template must be set prior to render");
+ throw new Error("UI.template must be set prior to render");
}
},
@@ -1369,6 +1383,8 @@ define('Place.plugin',["OObject", "Tools"],
*/
function PlacePlugin(OObject, Tools) {
+
+
/**
* Intilialize a Place.plugin with a list of OObjects
* @param {Object} $uis a list of OObjects such as:
@@ -1458,6 +1474,8 @@ define('SocketIOTransport',["Observable", "Tools"],
*/
function SocketIOTransport(Observable, Tools) {
+
+
/**
* Defines the SocketIOTransport
* @private
@@ -1610,174 +1628,406 @@ function SocketIOTransport(Observable, Tools) {
});
/**
- * https://github.com/flams/Olives-services
+ * Olives http://flams.github.com/olives
* The MIT License (MIT)
- * Copyright (c) 2012 Olivier Scherrer <pode.fr@gmail.com>
+ * Copyright (c) 2012-2013 Olivier Scherrer <pode.fr@gmail.com> - Olivier Wietrich <olivier.wietrich@gmail.com>
*/
-define('Router',["Observable", "Store"],
+define('Stack',[],
/**
* @class
- * Routing allows for navigating in an application by defining routes.
+ * A Stack is a tool for managing DOM elements as groups. Within a group, dom elements
+ * can be added, removed, moved around. The group can be moved to another parent node
+ * while keeping the DOM elements in the same order, excluding the parent dom elements's
+ * children that are not in the Stack.
*/
-function Router(Observable, Store) {
+function Stack() {
- return function RouterConstructor() {
+
+
+ return function StackConstructor($parent) {
/**
- * The routes observable (the applications use it)
+ * The parent DOM element is a documentFragment by default
* @private
*/
- var _routes = new Observable(),
+ var _parent = document.createDocumentFragment(),
/**
- * The events observable (used by Routing)
+ * The place where the dom elements hide
* @private
*/
- _events = new Observable(),
+ _hidePlace = document.createDocumentFragment(),
/**
- * The routing history
+ * The list of dom elements that are part of the stack
+ * Helps for excluding elements that are not part of it
* @private
*/
- _history = new Store([]),
+ _childNodes = [];
/**
- * For navigating through the history, remembers the current position
- * @private
+ * Add a DOM element to the stack. It will be appended.
+ * @param {HTMLElement} dom the DOM element to add
+ * @returns {HTMLElement} dom
*/
- _currentPos = 0;
+ this.add = function add(dom) {
+ if (!this.has(dom) && dom instanceof HTMLElement) {
+ _parent.appendChild(dom);
+ _childNodes.push(dom);
+ return dom;
+ } else {
+ return false;
+ }
+ };
/**
- * Only for debugging
- * @private
+ * Remove a DOM element from the stack.
+ * @param {HTMLElement} dom the DOM element to remove
+ * @returns {HTMLElement} dom
*/
- this.getRoutesObservable = function getRoutesObservable() {
- return _routes;
+ this.remove = function remove(dom) {
+ var index;
+ if (this.has(dom)) {
+ index = _childNodes.indexOf(dom);
+ _parent.removeChild(dom);
+ _childNodes.splice(index, 1);
+ return dom;
+ } else {
+ return false;
+ }
};
/**
- * Only for debugging
- * @private
+ * Place a stack by appending its DOM elements to a new parent
+ * @param {HTMLElement} newParentDom the new DOM element to append the stack to
+ * @returns {HTMLElement} newParentDom
+ */
+ this.place = function place(newParentDom) {
+ if (newParentDom instanceof HTMLElement) {
+ [].slice.call(_parent.childNodes).forEach(function (childDom) {
+ if (this.has(childDom)) {
+ newParentDom.appendChild(childDom);
+ }
+ }, this);
+ return this._setParent(newParentDom);
+ } else {
+ return false;
+ }
+ };
+
+ /**
+ * Move an element up in the stack
+ * @param {HTMLElement} dom the dom element to move up
+ * @returns {HTMLElement} dom
*/
- this.getEventsObservable = function getEventsObservable() {
- return _events;
+ this.up = function up(dom) {
+ if (this.has(dom)) {
+ var domPosition = this.getPosition(dom);
+ this.move(dom, domPosition + 2);
+ return dom;
+ } else {
+ return false;
+ }
};
/**
- * Set a new route
- * @param {String} route the name of the route
- * @param {Function} func the function to be execute when navigating to the route
- * @param {Object} scope the scope in which to execute the function
- * @returns a handle to remove the route
+ * Move an element down in the stack
+ * @param {HTMLElement} dom the dom element to move down
+ * @returns {HTMLElement} dom
*/
- this.set = function set() {
- return _routes.watch.apply(_routes, arguments);
+ this.down = function down(dom) {
+ if (this.has(dom)) {
+ var domPosition = this.getPosition(dom);
+ this.move(dom, domPosition - 1);
+ return dom;
+ } else {
+ return false;
+ }
};
/**
- * Remove a route
- * @param {Object} handle the handle provided by the set method
- * @returns true if successfully removed
+ * Move an element that is already in the stack to a new position
+ * @param {HTMLElement} dom the dom element to move
+ * @param {Number} position the position to which to move the DOM element
+ * @returns {HTMLElement} dom
*/
- this.unset = function unset(handle) {
- return _routes.unwatch(handle);
+ this.move = function move(dom, position) {
+ if (this.has(dom)) {
+ var domIndex = _childNodes.indexOf(dom);
+ _childNodes.splice(domIndex, 1);
+ _childNodes.splice(position, 0, dom);
+ // Preventing a bug in IE when insertBefore is not given a valid
+ // second argument
+ var nextElement = _childNodes[position +1];
+ if (nextElement) {
+ _parent.insertBefore(dom, nextElement);
+ } else {
+ _parent.appendChild(dom);
+ }
+ return dom;
+ } else {
+ return false;
+ }
};
/**
- * Navigate to a route
- * @param {String} route the route to navigate to
- * @param {*} *params
- * @returns
+ * Insert a new element at a specific position in the stack
+ * @param {HTMLElement} dom the dom element to insert
+ * @param {Number} position the position to which to insert the DOM element
+ * @returns {HTMLElement} dom
*/
- this.navigate = function get(route, params) {
- if (this.load(route, params)) {
- _history.alter("push", {
- route: route,
- params: params
- });
- _currentPos = _history.getNbItems();
- return true;
+ this.insert = function insert(dom, position) {
+ if (!this.has(dom) && dom instanceof HTMLElement) {
+ _childNodes.splice(position, 0, dom);
+ _parent.insertBefore(dom, _parent.childNodes[position]);
+ return dom;
} else {
return false;
}
+ };
+
+ /**
+ * Get the position of an element in the stack
+ * @param {HTMLElement} dom the dom to get the position from
+ * @returns {HTMLElement} dom
+ */
+ this.getPosition = function getPosition(dom) {
+ return _childNodes.indexOf(dom);
+ };
+ /**
+ * Count the number of elements in a stack
+ * @returns {Number} the number of items
+ */
+ this.count = function count() {
+ return _parent.childNodes.length;
};
/**
- * Actually loads the route
- * @private
+ * Tells if a DOM element is in the stack
+ * @param {HTMLElement} dom the dom to tell if its in the stack
+ * @returns {HTMLElement} dom
*/
- this.load = function load(route, params) {
- if (_routes.notify(route, params)) {
- _events.notify("route", route);
+ this.has = function has(childDom) {
+ return this.getPosition(childDom) >= 0;
+ };
+
+ /**
+ * Hide a dom element that was previously added to the stack
+ * It will be taken out of the dom until displayed again
+ * @param {HTMLElement} dom the dom to hide
+ * @return {boolean} if dom element is in the stack
+ */
+ this.hide = function hide(dom) {
+ if (this.has(dom)) {
+ _hidePlace.appendChild(dom);
return true;
} else {
return false;
}
};
/**
- * Watch for route changes
- * @param {Function} func the func to execute when the route changes
- * @param {Object} scope the scope in which to execute the function
- * @returns {Object} the handle to unwatch for route changes
+ * Show a dom element that was previously hidden
+ * It will be added back to the dom
+ * @param {HTMLElement} dom the dom to show
+ * @return {boolean} if dom element is current hidden
*/
- this.watch = function watch(func, scope) {
- return _events.watch("route", func, scope);
+ this.show = function show(dom) {
+ if (this.has(dom) && dom.parentNode === _hidePlace) {
+ this.move(dom, _childNodes.indexOf(dom));
+ return true;
+ } else {
+ return false;
+ }
};
/**
- * Unwatch routes changes
- * @param {Object} handle the handle was returned by the watch function
- * @returns true if unwatch
+ * Helper function for hiding all the dom elements
*/
- this.unwatch = function unwatch(handle) {
- return _events.unwatch(handle);
+ this.hideAll = function hideAll() {
+ _childNodes.forEach(this.hide, this);
};
/**
- * Get the history store, for debugging only
- * @private
+ * Helper function for showing all the dom elements
*/
- this.getHistoryStore = function getHistoryStore() {
- return _history;
+ this.showAll = function showAll() {
+ _childNodes.forEach(this.show, this);
};
/**
- * Go back and forth in the history
- * @param {Number} nb the amount of history to rewind/forward
- * @returns true if history exists
+ * Get the parent node that a stack is currently attached to
+ * @returns {HTMLElement} parent node
*/
- this.go = function go(nb) {
- var history = _history.get(_currentPos + nb);
+ this.getParent = function _getParent() {
+ return _parent;
+ };
- if (history) {
- this.load(history.route, history.params);
- _currentPos += nb;
- return true;
+ /**
+ * Set the parent element (without appending the stacks dom elements to)
+ * @private
+ */
+ this._setParent = function _setParent(parent) {
+ if (parent instanceof HTMLElement) {
+ _parent = parent;
+ return _parent;
} else {
return false;
}
};
/**
- * Go back in the history, short for go(-1)
- * @returns
+ * Get the place where the DOM elements are hidden
+ * @private
*/
- this.back = function back() {
- return this.go(-1);
+ this.getHidePlace = function getHidePlace() {
+ return _hidePlace;
};
/**
- * Go forward in the history, short for go(1)
- * @returns
+ * Set the place where the DOM elements are hidden
+ * @private
*/
- this.forward = function forward() {
- return this.go(1);
+ this.setHidePlace = function setHidePlace(hidePlace) {
+ if (hidePlace instanceof HTMLElement) {
+ _hidePlace = hidePlace;
+ return true;
+ } else {
+ return false;
+ }
};
+ this._setParent($parent);
+
};
-});
+});
+
+/**
+ * Olives http://flams.github.com/olives
+ * The MIT License (MIT)
+ * Copyright (c) 2012-2013 Olivier Scherrer <pode.fr@gmail.com> - Olivier Wietrich <olivier.wietrich@gmail.com>
+ */
+
+define('LocationRouter',["Router", "Tools"],
+
+/**
+ * @class
+ * A locationRouter is a router which navigates to the route defined in the URL and updates this URL
+ * while navigating. It's a subtype of Emily's Router
+ */
+function LocationRouter(Router, Tools) {
+
+
+
+ function LocationRouterConstructor() {
+
+ /**
+ * The handle on the watch
+ * @private
+ */
+ var _watchHandle;
+
+ /**
+ * The function that parses the url to determine the route to navigate to.
+ * It has a default behavior explained below, but can be overriden as long as
+ * it has the same contract.
+ * @param {String} hash the hash coming from window.location.has
+ * @returns {Array} has to return an array with the list of arguments to call
+ * navigate with. The first item of the array must be the name of the route.
+ *
+ * Example: #album/holiday/2013
+ * will navigate to the route "album" and give two arguments "holiday" and "2013"
+ */
+ this.parse = function parse(hash) {
+ return hash.split("#").pop().split("/");
+ };
+
+ /**
+ * The function that converts, or serialises the route and its arguments to a valid URL.
+ * It has a default behavior below, but can be overriden as long as it has the same contract.
+ * @param {Array} args the list of arguments to serialize
+ * @returns {String} the serialized arguments to add to the url hashmark
+ *
+ * Example:
+ * ["album", "holiday", "2013"];
+ * will give "album/holiday/2013"
+ *
+ */
+ this.toUrl = function toUrl(args) {
+ return args.join("/");
+ };
+
+ /**
+ * When all the routes and handlers have been defined, start the location router
+ * so it parses the URL and navigates to the corresponding route.
+ * It will also start listening to route changes and hashmark changes to navigate.
+ * While navigating, the hashmark itself will also change to reflect the current route state
+ */
+ this.start = function start() {
+ var parsedHash = this.parse(window.location.hash);
+ this.navigate.apply(this, parsedHash);
+ this.bindOnHashChange();
+ this.bindOnRouteChange();
+ };
+
+ /**
+ * Remove the events handler for cleaning.
+ */
+ this.destroy = function destroy() {
+ this.unwatch(_watchHandle);
+ window.removeEventListener("hashchange", this.boundOnHashChange, true);
+ };
+
+ /**
+ * Parse the hash and navigate to the corresponding url
+ * @private
+ */
+ this.onHashChange = function onHashChange(event) {
+ var parsedHash = this.parse(event.newUrl.split("#").pop());
+ this.navigate.apply(this, parsedHash);
+ };
+
+ /**
+ * The bound version of onHashChange for add/removeEventListener
+ * @private
+ */
+ this.boundOnHashChange = this.onHashChange.bind(this);
+
+ /**
+ * Add an event listener to hashchange to navigate to the corresponding route
+ * when it changes
+ * @private
+ */
+ this.bindOnHashChange = function bindOnHashChange() {
+ window.addEventListener("hashchange", this.boundOnHashChange, true);
+ };
+
+ /**
+ * Watch route change events from the router to update the location
+ * @private
+ */
+ this.bindOnRouteChange = function bindOnRouteChange() {
+ _watchHandle = this.watch("route", this.onRouteChange, this);
+ };
+
+ /**
+ * The handler for when the route changes
+ * It updates the location
+ * @private
+ */
+ this.onRouteChange = function onRouteChange() {
+ window.location.hash = this.toUrl(Tools.toArray(arguments));
+ };
+
+ }
+
+ return function LocationRouterFactory() {
+ LocationRouterConstructor.prototype = new Router();
+ return new LocationRouterConstructor();
+ };
+
+});
View
52 build/Olives.min.js
@@ -3,27 +3,31 @@
The MIT License (MIT)
Copyright (c) 2012-2013 Olivier Scherrer <pode.fr@gmail.com> - Olivier Wietrich <olivier.wietrich@gmail.com>
*/
-define("DomUtils",["Tools"],function(e){return{getNodes:function(d,c){return this.isAcceptedType(d)?(d.parentNode||document.createDocumentFragment().appendChild(d),d.parentNode.querySelectorAll(c||"*")):false},getDataset:function(d){var c=0,b,f={},g,a;if(this.isAcceptedType(d))if(d.hasOwnProperty("dataset"))return d.dataset;else{for(b=d.attributes.length;c<b;c++)g=d.attributes[c].name.split("-"),g.shift()=="data"&&(f[a=g.join("-")]=d.getAttribute("data-"+a));return f}else return false},isAcceptedType:function(d){return d instanceof
-HTMLElement||d instanceof SVGElement?true:false},setAttribute:function(d,c,b){return d instanceof HTMLElement?(d[c]=b,true):d instanceof SVGElement?(d.setAttribute(c,b),true):false},matches:function(d,c,b){return e.toArray(this.getNodes(d,c)).indexOf(b)>-1}}});
-define("Bind.plugin",["Store","Observable","Tools","DomUtils"],function(e,d,c,b){return function(d,g){function a(a){h[a]&&(h[a].forEach(function(a){k.unwatchValue(a)}),delete h[a])}var k=null,j={},l={},h={};this.observers=h;this.setModel=function(a){return a instanceof e?(k=a,true):false};this.getModel=function(){return k};this.ItemRenderer=function(i,d){var h=null,f=null,g=null,j=null,e=null;this.setRenderer=function(a){h=a;return true};this.getRenderer=function(){return h};this.setRootNode=function(a){return b.isAcceptedType(a)?
-(g=a,a=g.querySelector("*"),this.setRenderer(a),a&&g.removeChild(a),true):false};this.getRootNode=function(){return g};this.setPlugins=function(a){f=a;return true};this.getPlugins=function(){return f};this.items={};this.setStart=function(a){return j=parseInt(a,10)};this.getStart=function(){return j};this.setNb=function(a){return e=a=="*"?a:parseInt(a,10)};this.getNb=function(){return e};this.addItem=function(a){var i;return typeof a=="number"&&!this.items[a]?(i=this.getNextItem(a),(a=this.create(a))?
-(i?g.insertBefore(a,i):g.appendChild(a),true):false):false};this.getNextItem=function(a){var i=Object.keys(this.items).map(function(a){return Number(a)}),b=c.closestGreater(a,i),i=i[b];if(i!=a)return this.items[i]};this.removeItem=function(i){var b=this.items[i];return b?(g.removeChild(b),delete this.items[i],a(i),true):false};this.create=function(a){if(k.has(a)){var i=h.cloneNode(true),d=b.getNodes(i);c.toArray(d).forEach(function(i){i.setAttribute("data-"+f.name+"_id",a)});this.items[a]=i;f.apply(i);
-return i}};this.render=function(){var a=e=="*"?k.getNbItems():e,i=[];if(e!==null&&j!==null){c.loop(this.items,function(b,c){c=Number(c);(c<j||c>=j+a||!k.has(c))&&i.push(c)},this);i.sort(c.compareNumbers).reverse().forEach(this.removeItem,this);for(var b=j,d=a+j;b<d;b++)this.addItem(b);return true}else return false};this.setPlugins(i);this.setRootNode(d)};this.setItemRenderer=function(a,b){l[a||"default"]=b};this.getItemRenderer=function(a){return l[a]};this.foreach=function(i,b,c,d){var h=new this.ItemRenderer(this.plugins,
-i);h.setStart(c||0);h.setNb(d||"*");h.render();k.watch("added",h.render,h);k.watch("deleted",function(i){h.render();a(i)},this);this.setItemRenderer(b,h)};this.updateStart=function(a,b){var c=this.getItemRenderer(a);return c?(c.setStart(b),true):false};this.updateNb=function(a,b){var c=this.getItemRenderer(a);return c?(c.setNb(b),true):false};this.refresh=function(a){return(a=this.getItemRenderer(a))?(a.render(),true):false};this.bind=function(a,d,h){var h=h||"",f=a.getAttribute("data-"+this.plugins.name+
-"_id"),g=h.split("."),j=f||g.shift(),e=f?h:g.join("."),f=c.getNestedProperty(k.get(j),e),l=c.toArray(arguments).slice(3);if(f||f===0||f===false)this.execBinding.apply(this,[a,d,f].concat(l))||b.setAttribute(a,d,f);this.hasBinding(d)||a.addEventListener("change",function(){k.has(j)&&(e?k.update(j,h,a[d]):k.set(j,a[d]))},true);this.observers[j]=this.observers[j]||[];this.observers[j].push(k.watchValue(j,function(h){this.execBinding.apply(this,[a,d,c.getNestedProperty(h,e)].concat(l))||b.setAttribute(a,
-d,c.getNestedProperty(h,e))},this))};this.set=function(a){return b.isAcceptedType(a)&&a.name?(k.set(a.name,a.value),true):false};this.getItemIndex=function(a){return(a=b.getDataset(a))&&typeof a[this.plugins.name+"_id"]!="undefined"?+a[this.plugins.name+"_id"]:false};this.form=function(a){if(a&&a.nodeName=="FORM"){var b=this;a.addEventListener("submit",function(d){c.toArray(a.querySelectorAll("[name]")).forEach(b.set,b);d.preventDefault()},true);return true}else return false};this.addBinding=function(a,
-b){return a&&typeof a=="string"&&typeof b=="function"?(j[a]=b,true):false};this.execBinding=function(a,b){return this.hasBinding(b)?(j[b].apply(a,Array.prototype.slice.call(arguments,2)),true):false};this.hasBinding=function(a){return j.hasOwnProperty(a)};this.getBinding=function(a){return j[a]};this.addBindings=function(a){return c.loop(a,function(a,b){this.addBinding(b,a)},this)};this.setModel(d);this.addBindings(g)}});
-define("Event.plugin",["DomUtils"],function(e){return function(d,c){var b=null,f={mousedown:"touchstart",mouseup:"touchend",mousemove:"touchmove"},g=!!c;this.addEventListener=function(a,b,c,d){a.addEventListener(this.map(b),c,!!d)};this.listen=function(a,c,d,f){this.addEventListener(a,c,function(c){b[d].call(b,c,a)},!!f)};this.delegate=function(a,c,d,f,h){this.addEventListener(a,d,function(d){e.matches(a,c,d.target)&&b[f].call(b,d,a)},!!h)};this.getParent=function(){return b};this.setParent=function(a){return a instanceof
-Object?(b=a,true):false};this.map=function(a){return g?f[a]||a:a};this.setMap=function(a,b){return typeof a=="string"&&typeof b=="string"?(f[a]=b,true):false};this.setParent(d)}});
-define("LocalStore",["Store","Tools"],function(e,d){function c(){var b=null,c=localStorage,g=function(){c.setItem(b,this.toJSON())};this.setLocalStorage=function(a){return a&&a.setItem instanceof Function?(c=a,true):false};this.getLocalStorage=function(){return c};this.sync=function(a){return typeof a=="string"?(b=a,a=JSON.parse(c.getItem(a)),d.loop(a,function(a,b){this.has(b)||this.set(b,a)},this),g.call(this),this.watch("added",g,this),this.watch("updated",g,this),this.watch("deleted",g,this),true):
-false}}return function(b){c.prototype=new e(b);return new c}});
-define("Plugins",["Tools","DomUtils"],function(e,d){return function(c){var b={},f=function(a){return a.trim()},g=function(a,c,d){c.split(";").forEach(function(c){var h=c.split(":"),c=h[0].trim(),h=h[1]?h[1].split(",").map(f):[];h.unshift(a);b[d]&&b[d][c]&&b[d][c].apply(b[d],h)})};this.add=function(a,c){var d=this;return typeof a=="string"&&typeof c=="object"&&c?(b[a]=c,c.plugins={name:a,apply:function(){return d.apply.apply(d,arguments)}},true):false};this.addAll=function(a){return e.loop(a,function(a,
-b){this.add(b,a)},this)};this.get=function(a){return b[a]};this.del=function(a){return delete b[a]};this.apply=function(a){var b;return d.isAcceptedType(a)?(b=d.getNodes(a),e.loop(e.toArray(b),function(a){e.loop(d.getDataset(a),function(b,c){g(a,b,c)})}),a):false};this.addAll(c)}});
-define("OObject",["StateMachine","Store","Plugins","DomUtils","Tools"],function(e,d,c,b,f){return function(g){var a=function(a){var c=j||document.createElement("div");if(a.template){typeof a.template=="string"?c.innerHTML=a.template.trim():b.isAcceptedType(a.template)&&c.appendChild(a.template);if(c.childNodes.length>1)throw Error("UI.template should have only one parent node");else a.dom=c.childNodes[0];a.plugins.apply(a.dom)}else throw Error("UI.template must be set prior to render");},k=function(a,
-b,c){b&&(c?b.insertBefore(a.dom,c):b.appendChild(a.dom),j=b)},j=null,l=new e("Init",{Init:[["render",a,this,"Rendered"],["place",function(b,c){a(b);k.apply(null,f.toArray(arguments))},this,"Rendered"]],Rendered:[["place",k,this],["render",a,this]]});this.model=g instanceof d?g:new d;this.plugins=new c;this.dom=this.template=null;this.place=function(a,b){l.event("place",this,a,b)};this.render=function(){l.event("render",this)};this.setTemplateFromDom=function(a){return b.isAcceptedType(a)?(this.template=
-a,true):false};this.alive=function(a){return b.isAcceptedType(a)?(this.setTemplateFromDom(a),this.place(a.parentNode,a.nextElementSibling),true):false};this.getCurrentPlace=function(){return j}}});
-define("Place.plugin",["OObject","Tools"],function(e,d){return function(c){var b={};this.place=function(c,d){if(b[d]instanceof e)b[d].place(c);else throw Error(d+" is not an OObject UI in place:"+d);};this.set=function(c,d){return typeof c=="string"&&d instanceof e?(b[c]=d,true):false};this.setAll=function(b){d.loop(b,function(b,a){this.set(a,b)},this)};this.get=function(c){return b[c]};this.setAll(c)}});
-define("SocketIOTransport",["Observable","Tools"],function(){return function(e){var d=null;this.setSocket=function(c){return c&&typeof c.emit=="function"?(d=c,true):false};this.getSocket=function(){return d};this.on=function(c,b){return d.on(c,b)};this.once=function(c,b){return d.once(c,b)};this.emit=function(c,b,f){return d.emit(c,b,f)};this.removeListener=function(c,b,f){return d.removeListener(c,b,f)};this.request=function(c,b,d,g){return typeof c=="string"&&typeof b!="undefined"?(b={eventId:Date.now()+
-Math.floor(Math.random()*1E6),data:b},this.once(b.eventId,function(){d&&d.apply(g||null,arguments)}),this.emit(c,b),true):false};this.listen=function(c,b,d,g){if(typeof c=="string"&&typeof b!="undefined"&&typeof d=="function"){var a={eventId:Date.now()+Math.floor(Math.random()*1E6),data:b,keepAlive:true},e=function(){d&&d.apply(g||null,arguments)},j=this;this.on(a.eventId,e);this.emit(c,a);return function(){j.emit("disconnect-"+a.eventId);j.removeListener(a.eventId,e)}}else return false};this.setSocket(e)}});
-define("Router",["Observable","Store"],function(e,d){return function(){var c=new e,b=new e,f=new d([]),g=0;this.getRoutesObservable=function(){return c};this.getEventsObservable=function(){return b};this.set=function(){return c.watch.apply(c,arguments)};this.unset=function(a){return c.unwatch(a)};this.navigate=function(a,b){return this.load(a,b)?(f.alter("push",{route:a,params:b}),g=f.getNbItems(),true):false};this.load=function(a,d){return c.notify(a,d)?(b.notify("route",a),true):false};this.watch=
-function(a,c){return b.watch("route",a,c)};this.unwatch=function(a){return b.unwatch(a)};this.getHistoryStore=function(){return f};this.go=function(a){var b=f.get(g+a);return b?(this.load(b.route,b.params),g+=a,true):false};this.back=function(){return this.go(-1)};this.forward=function(){return this.go(1)}}});
+define("DomUtils",["Tools"],function(g){return{getNodes:function(c,e){return this.isAcceptedType(c)?(c.parentNode||document.createDocumentFragment().appendChild(c),c.parentNode.querySelectorAll(e||"*")):false},getDataset:function(c){var e=0,b,a={},d,f;if(this.isAcceptedType(c))if(c.hasOwnProperty("dataset"))return c.dataset;else{for(b=c.attributes.length;e<b;e++)d=c.attributes[e].name.split("-"),d.shift()=="data"&&(a[f=d.join("-")]=c.getAttribute("data-"+f));return a}else return false},isAcceptedType:function(c){return c instanceof
+HTMLElement||c instanceof SVGElement?true:false},setAttribute:function(c,e,b){return c instanceof HTMLElement?(c[e]=b,true):c instanceof SVGElement?(c.setAttribute(e,b),true):false},matches:function(c,e,b){return g.toArray(this.getNodes(c,e)).indexOf(b)>-1}}});
+define("Bind.plugin",["Store","Observable","Tools","DomUtils"],function(g,c,e,b){return function(a,c){function f(a){i[a]&&(i[a].forEach(function(a){j.unwatchValue(a)}),delete i[a])}var j=null,h={},k={},i={};this.observers=i;this.setModel=function(a){return a instanceof g?(j=a,true):false};this.getModel=function(){return j};this.ItemRenderer=function(a,c){var d=null,i=null,h=null,g=null,k=null;this.setRenderer=function(a){d=a;return true};this.getRenderer=function(){return d};this.setRootNode=function(a){return b.isAcceptedType(a)?
+(h=a,a=h.querySelector("*"),this.setRenderer(a),a&&h.removeChild(a),true):false};this.getRootNode=function(){return h};this.setPlugins=function(a){i=a;return true};this.getPlugins=function(){return i};this.items={};this.setStart=function(a){return g=parseInt(a,10)};this.getStart=function(){return g};this.setNb=function(a){return k=a=="*"?a:parseInt(a,10)};this.getNb=function(){return k};this.addItem=function(a){var b;return typeof a=="number"&&!this.items[a]?(b=this.getNextItem(a),(a=this.create(a))?
+(b?h.insertBefore(a,b):h.appendChild(a),true):false):false};this.getNextItem=function(a){var b=Object.keys(this.items).map(function(a){return Number(a)}),f=e.closestGreater(a,b),b=b[f];if(b!=a)return this.items[b]};this.removeItem=function(a){var b=this.items[a];return b?(h.removeChild(b),delete this.items[a],f(a),true):false};this.create=function(a){if(j.has(a)){var f=d.cloneNode(true),l=b.getNodes(f);e.toArray(l).forEach(function(b){b.setAttribute("data-"+i.name+"_id",a)});this.items[a]=f;i.apply(f);
+return f}};this.render=function(){var a=k=="*"?j.getNbItems():k,b=[];if(k!==null&&g!==null){e.loop(this.items,function(f,l){l=Number(l);(l<g||l>=g+a||!j.has(l))&&b.push(l)},this);b.sort(e.compareNumbers).reverse().forEach(this.removeItem,this);for(var f=g,l=a+g;f<l;f++)this.addItem(f);return true}else return false};this.setPlugins(a);this.setRootNode(c)};this.setItemRenderer=function(a,b){k[a||"default"]=b};this.getItemRenderer=function(a){return k[a]};this.foreach=function(a,b,c,e){var d=new this.ItemRenderer(this.plugins,
+a);d.setStart(c||0);d.setNb(e||"*");d.render();j.watch("added",d.render,d);j.watch("deleted",function(a){d.render();f(a)},this);this.setItemRenderer(b,d)};this.updateStart=function(a,b){var f=this.getItemRenderer(a);return f?(f.setStart(b),true):false};this.updateNb=function(a,b){var f=this.getItemRenderer(a);return f?(f.setNb(b),true):false};this.refresh=function(a){return(a=this.getItemRenderer(a))?(a.render(),true):false};this.bind=function(a,f,c){var c=c||"",d=a.getAttribute("data-"+this.plugins.name+
+"_id"),i=c.split("."),h=d||i.shift(),g=d?c:i.join("."),d=e.getNestedProperty(j.get(h),g),k=e.toArray(arguments).slice(3);if(d||d===0||d===false)this.execBinding.apply(this,[a,f,d].concat(k))||b.setAttribute(a,f,d);this.hasBinding(f)||a.addEventListener("change",function(){j.has(h)&&(g?j.update(h,c,a[f]):j.set(h,a[f]))},true);this.observers[h]=this.observers[h]||[];this.observers[h].push(j.watchValue(h,function(c){this.execBinding.apply(this,[a,f,e.getNestedProperty(c,g)].concat(k))||b.setAttribute(a,
+f,e.getNestedProperty(c,g))},this))};this.set=function(a){return b.isAcceptedType(a)&&a.name?(j.set(a.name,a.value),true):false};this.getItemIndex=function(a){return(a=b.getDataset(a))&&typeof a[this.plugins.name+"_id"]!="undefined"?+a[this.plugins.name+"_id"]:false};this.form=function(a){if(a&&a.nodeName=="FORM"){var b=this;a.addEventListener("submit",function(f){e.toArray(a.querySelectorAll("[name]")).forEach(b.set,b);f.preventDefault()},true);return true}else return false};this.addBinding=function(a,
+b){return a&&typeof a=="string"&&typeof b=="function"?(h[a]=b,true):false};this.execBinding=function(a,b){return this.hasBinding(b)?(h[b].apply(a,Array.prototype.slice.call(arguments,2)),true):false};this.hasBinding=function(a){return h.hasOwnProperty(a)};this.getBinding=function(a){return h[a]};this.addBindings=function(a){return e.loop(a,function(a,b){this.addBinding(b,a)},this)};this.setModel(a);this.addBindings(c)}});
+define("Event.plugin",["DomUtils"],function(g){return function(c,e){var b=null,a={mousedown:"touchstart",mouseup:"touchend",mousemove:"touchmove"},d=!!e;this.addEventListener=function(a,b,c,d){a.addEventListener(this.map(b),c,!!d)};this.listen=function(a,c,d,e){this.addEventListener(a,c,function(c){b[d].call(b,c,a)},!!e)};this.delegate=function(a,c,d,e,i){this.addEventListener(a,d,function(d){g.matches(a,c,d.target)&&b[e].call(b,d,a)},!!i)};this.getParent=function(){return b};this.setParent=function(a){return a instanceof
+Object?(b=a,true):false};this.map=function(b){return d?a[b]||b:b};this.setMap=function(b,c){return typeof b=="string"&&typeof c=="string"?(a[b]=c,true):false};this.setParent(c)}});
+define("LocalStore",["Store","Tools"],function(g,c){function e(){var b=null,a=localStorage,d=function(){a.setItem(b,this.toJSON())};this.setLocalStorage=function(b){return b&&b.setItem instanceof Function?(a=b,true):false};this.getLocalStorage=function(){return a};this.sync=function(f){return typeof f=="string"?(b=f,f=JSON.parse(a.getItem(f)),c.loop(f,function(a,b){this.has(b)||this.set(b,a)},this),d.call(this),this.watch("added",d,this),this.watch("updated",d,this),this.watch("deleted",d,this),true):
+false}}return function(b){e.prototype=new g(b);return new e}});
+define("Plugins",["Tools","DomUtils"],function(g,c){return function(e){var b={},a=function(a){return a.trim()},d=function(c,d,e){d.split(";").forEach(function(d){var i=d.split(":"),d=i[0].trim(),i=i[1]?i[1].split(",").map(a):[];i.unshift(c);b[e]&&b[e][d]&&b[e][d].apply(b[e],i)})};this.add=function(a,c){var d=this;return typeof a=="string"&&typeof c=="object"&&c?(b[a]=c,c.plugins={name:a,apply:function(){return d.apply.apply(d,arguments)}},true):false};this.addAll=function(a){return g.loop(a,function(a,
+b){this.add(b,a)},this)};this.get=function(a){return b[a]};this.del=function(a){return delete b[a]};this.apply=function(a){var b;return c.isAcceptedType(a)?(b=c.getNodes(a),g.loop(g.toArray(b),function(a){g.loop(c.getDataset(a),function(b,c){d(a,b,c)})}),a):false};this.addAll(e)}});
+define("OObject",["StateMachine","Store","Plugins","DomUtils","Tools"],function(g,c,e,b,a){return function(d){var f=function(a){var c=h||document.createElement("div");if(a.template){typeof a.template=="string"?c.innerHTML=a.template.trim():b.isAcceptedType(a.template)&&c.appendChild(a.template);if(c.childNodes.length>1)throw Error("UI.template should have only one parent node");else a.dom=c.childNodes[0];a.plugins.apply(a.dom)}else throw Error("UI.template must be set prior to render");},j=function(a,
+b,c){b&&(c?b.insertBefore(a.dom,c):b.appendChild(a.dom),h=b)},h=null,k=new g("Init",{Init:[["render",f,this,"Rendered"],["place",function(b,c){f(b);j.apply(null,a.toArray(arguments))},this,"Rendered"]],Rendered:[["place",j,this],["render",f,this]]});this.model=d instanceof c?d:new c;this.plugins=new e;this.dom=this.template=null;this.place=function(a,b){k.event("place",this,a,b)};this.render=function(){k.event("render",this)};this.setTemplateFromDom=function(a){return b.isAcceptedType(a)?(this.template=
+a,true):false};this.alive=function(a){return b.isAcceptedType(a)?(this.setTemplateFromDom(a),this.place(a.parentNode,a.nextElementSibling),true):false};this.getCurrentPlace=function(){return h}}});
+define("Place.plugin",["OObject","Tools"],function(g,c){return function(e){var b={};this.place=function(a,c){if(b[c]instanceof g)b[c].place(a);else throw Error(c+" is not an OObject UI in place:"+c);};this.set=function(a,c){return typeof a=="string"&&c instanceof g?(b[a]=c,true):false};this.setAll=function(a){c.loop(a,function(a,b){this.set(b,a)},this)};this.get=function(a){return b[a]};this.setAll(e)}});
+define("SocketIOTransport",["Observable","Tools"],function(){return function(g){var c=null;this.setSocket=function(e){return e&&typeof e.emit=="function"?(c=e,true):false};this.getSocket=function(){return c};this.on=function(e,b){return c.on(e,b)};this.once=function(e,b){return c.once(e,b)};this.emit=function(e,b,a){return c.emit(e,b,a)};this.removeListener=function(e,b,a){return c.removeListener(e,b,a)};this.request=function(c,b,a,d){return typeof c=="string"&&typeof b!="undefined"?(b={eventId:Date.now()+
+Math.floor(Math.random()*1E6),data:b},this.once(b.eventId,function(){a&&a.apply(d||null,arguments)}),this.emit(c,b),true):false};this.listen=function(c,b,a,d){if(typeof c=="string"&&typeof b!="undefined"&&typeof a=="function"){var f={eventId:Date.now()+Math.floor(Math.random()*1E6),data:b,keepAlive:true},g=function(){a&&a.apply(d||null,arguments)},h=this;this.on(f.eventId,g);this.emit(c,f);return function(){h.emit("disconnect-"+f.eventId);h.removeListener(f.eventId,g)}}else return false};this.setSocket(g)}});
+define("Stack",[],function(){return function(g){var c=document.createDocumentFragment(),e=document.createDocumentFragment(),b=[];this.add=function(a){return!this.has(a)&&a instanceof HTMLElement?(c.appendChild(a),b.push(a),a):false};this.remove=function(a){var d;return this.has(a)?(d=b.indexOf(a),c.removeChild(a),b.splice(d,1),a):false};this.place=function(a){return a instanceof HTMLElement?([].slice.call(c.childNodes).forEach(function(b){this.has(b)&&a.appendChild(b)},this),this._setParent(a)):false};
+this.up=function(a){if(this.has(a)){var b=this.getPosition(a);this.move(a,b+2);return a}else return false};this.down=function(a){if(this.has(a)){var b=this.getPosition(a);this.move(a,b-1);return a}else return false};this.move=function(a,d){if(this.has(a)){var e=b.indexOf(a);b.splice(e,1);b.splice(d,0,a);(e=b[d+1])?c.insertBefore(a,e):c.appendChild(a);return a}else return false};this.insert=function(a,d){return!this.has(a)&&a instanceof HTMLElement?(b.splice(d,0,a),c.insertBefore(a,c.childNodes[d]),
+a):false};this.getPosition=function(a){return b.indexOf(a)};this.count=function(){return c.childNodes.length};this.has=function(a){return this.getPosition(a)>=0};this.hide=function(a){return this.has(a)?(e.appendChild(a),true):false};this.show=function(a){return this.has(a)&&a.parentNode===e?(this.move(a,b.indexOf(a)),true):false};this.hideAll=function(){b.forEach(this.hide,this)};this.showAll=function(){b.forEach(this.show,this)};this.getParent=function(){return c};this._setParent=function(a){return a instanceof
+HTMLElement?c=a:false};this.getHidePlace=function(){return e};this.setHidePlace=function(a){return a instanceof HTMLElement?(e=a,true):false};this._setParent(g)}});
+define("LocationRouter",["Router","Tools"],function(g,c){function e(){var b;this.parse=function(a){return a.split("#").pop().split("/")};this.toUrl=function(a){return a.join("/")};this.start=function(){this.navigate.apply(this,this.parse(window.location.hash));this.bindOnHashChange();this.bindOnRouteChange()};this.destroy=function(){this.unwatch(b);window.removeEventListener("hashchange",this.boundOnHashChange,true)};this.onHashChange=function(a){this.navigate.apply(this,this.parse(a.newUrl.split("#").pop()))};
+this.boundOnHashChange=this.onHashChange.bind(this);this.bindOnHashChange=function(){window.addEventListener("hashchange",this.boundOnHashChange,true)};this.bindOnRouteChange=function(){b=this.watch("route",this.onRouteChange,this)};this.onRouteChange=function(){window.location.hash=this.toUrl(c.toArray(arguments))}}return function(){e.prototype=new g;return new e}});
View
8 build/src/Bind.plugin.js
@@ -13,6 +13,8 @@ define(["Store", "Observable", "Tools", "DomUtils"],
*/
function BindPlugin(Store, Observable, Tools, DomUtils) {
+ "use strict";
+
return function BindPluginConstructor($model, $bindings) {
/**
@@ -198,7 +200,8 @@ function BindPlugin(Store, Observable, Tools, DomUtils) {
* @returns the value
*/
this.setStart = function setStart(start) {
- return _start = parseInt(start, 10);
+ _start = parseInt(start, 10);
+ return _start;
};
/**
@@ -217,7 +220,8 @@ function BindPlugin(Store, Observable, Tools, DomUtils) {
* @returns the value
*/
this.setNb = function setNb(nb) {
- return _nb = nb == "*" ? nb : parseInt(nb, 10);
+ _nb = nb == "*" ? nb : parseInt(nb, 10);
+ return _nb;
};
/**
View
2 build/src/DomUtils.js
@@ -6,6 +6,8 @@
define(["Tools"], function (Tools) {
+ "use strict";
+
return {
/**
* Returns a NodeList including the given dom node,
View
234 build/src/Event.plugin.js
@@ -14,121 +14,123 @@ define(["DomUtils"],
*/
function EventPlugin(Utils) {
- /**
- * The event plugin constructor.
- * ex: new EventPlugin({method: function(){} ...}, false);
- * @param {Object} the object that has the event handling methods
- * @param {Boolean} $isMobile if the event handler has to map with touch events
- */
- return function EventPluginConstructor($parent, $isMobile) {
-
- /**
- * The parent callback
- * @private
- */
- var _parent = null,
-
- /**
- * The mapping object.
- * @private
- */
- _map = {
- "mousedown" : "touchstart",
- "mouseup" : "touchend",
- "mousemove" : "touchmove"
- },
-
- /**
- * Is touch device.
- * @private
- */
- _isMobile = !!$isMobile;
-
- /**
- * Add mapped event listener (for testing purpose).
- * @private
- */
- this.addEventListener = function addEventListener(node, event, callback, useCapture) {
- node.addEventListener(this.map(event), callback, !!useCapture);
- };
-
- /**
- * Listen to DOM events.
- * @param {Object} node DOM node
- * @param {String} name event's name
- * @param {String} listener callback's name
- * @param {String} useCapture string
- */
- this.listen = function listen(node, name, listener, useCapture) {
- this.addEventListener(node, name, function(e){
- _parent[listener].call(_parent, e, node);
- }, !!useCapture);
- };
-
- /**
- * Delegate the event handling to a parent DOM element
- * @param {Object} node DOM node
- * @param {String} selector CSS3 selector to the element that listens to the event
- * @param {String} name event's name
- * @param {String} listener callback's name
- * @param {String} useCapture string
- */
- this.delegate = function delegate(node, selector, name, listener, useCapture) {
- this.addEventListener(node, name, function(event){
- if (Utils.matches(node, selector, event.target)) {
- _parent[listener].call(_parent, event, node);
- }
- }, !!useCapture);
- };
-
- /**
- * Get the parent object.
- * @return {Object} the parent object
- */
- this.getParent = function getParent() {
- return _parent;
- };
-
- /**
- * Set the parent object.
- * The parent object is an object which the functions are called by node listeners.
- * @param {Object} the parent object
- * @return true if object has been set
- */
- this.setParent = function setParent(parent) {
- if (parent instanceof Object){
- _parent = parent;
- return true;
- }
- return false;
- };
-
- /**
- * Get event mapping.
- * @param {String} event's name
- * @return the mapped event's name
- */
- this.map = function map(name) {
- return _isMobile ? (_map[name] || name) : name;
- };
-
- /**
- * Set event mapping.
- * @param {String} event's name
- * @param {String} event's value
- * @return true if mapped
- */
- this.setMap = function setMap(name, value) {
- if (typeof name == "string" &&
- typeof value == "string") {
- _map[name] = value;
- return true;
- }
- return false;
- };
-
- //init
- this.setParent($parent);
- };
+ "use strict";
+
+ /**
+ * The event plugin constructor.
+ * ex: new EventPlugin({method: function(){} ...}, false);
+ * @param {Object} the object that has the event handling methods
+ * @param {Boolean} $isMobile if the event handler has to map with touch events
+ */
+ return function EventPluginConstructor($parent, $isMobile) {
+
+ /**
+ * The parent callback
+ * @private
+ */
+ var _parent = null,
+
+ /**
+ * The mapping object.
+ * @private
+ */
+ _map = {
+ "mousedown" : "touchstart",
+ "mouseup" : "touchend",
+ "mousemove" : "touchmove"
+ },
+
+ /**
+ * Is touch device.
+ * @private
+ */
+ _isMobile = !!$isMobile;
+
+ /**
+ * Add mapped event listener (for testing purpose).
+ * @private
+ */
+ this.addEventListener = function addEventListener(node, event, callback, useCapture) {
+ node.addEventListener(this.map(event), callback, !!useCapture);
+ };
+
+ /**
+ * Listen to DOM events.
+ * @param {Object} node DOM node
+ * @param {String} name event's name
+ * @param {String} listener callback's name
+ * @param {String} useCapture string
+ */
+ this.listen = function listen(node, name, listener, useCapture) {
+ this.addEventListener(node, name, function(e){
+ _parent[listener].call(_parent, e, node);
+ }, !!useCapture);
+ };
+
+ /**
+ * Delegate the event handling to a parent DOM element
+ * @param {Object} node DOM node
+ * @param {String} selector CSS3 selector to the element that listens to the event
+ * @param {String} name event's name
+ * @param {String} listener callback's name
+ * @param {String} useCapture string
+ */
+ this.delegate = function delegate(node, selector, name, listener, useCapture) {
+ this.addEventListener(node, name, function(event){
+ if (Utils.matches(node, selector, event.target)) {
+ _parent[listener].call(_parent, event, node);
+ }
+ }, !!useCapture);
+ };
+
+ /**
+ * Get the parent object.
+ * @return {Object} the parent object
+ */
+ this.getParent = function getParent() {
+ return _parent;
+ };
+
+ /**
+ * Set the parent object.
+ * The parent object is an object which the functions are called by node listeners.
+ * @param {Object} the parent object
+ * @return true if object has been set
+ */
+ this.setParent = function setParent(parent) {
+ if (parent instanceof Object){
+ _parent = parent;
+ return true;
+ }
+ return false;
+ };
+
+ /**
+ * Get event mapping.
+ * @param {String} event's name
+ * @return the mapped event's name
+ */
+ this.map = function map(name) {
+ return _isMobile ? (_map[name] || name) : name;
+ };
+
+ /**
+ * Set event mapping.
+ * @param {String} event's name
+ * @param {String} event's value
+ * @return true if mapped
+ */
+ this.setMap = function setMap(name, value) {
+ if (typeof name == "string" &&
+ typeof value == "string") {
+ _map[name] = value;
+ return true;
+ }
+ return false;
+ };
+
+ //init
+ this.setParent($parent);
+ };
});
View
2 build/src/LocalStore.js
@@ -15,6 +15,8 @@ define(["Store", "Tools"],
*/
function LocalStore(Store, Tools) {
+ "use strict";
+
function LocalStoreConstructor() {
/**
View
125 build/src/LocationRouter.js
@@ -0,0 +1,125 @@
+/**
+ * Olives http://flams.github.com/olives
+ * The MIT License (MIT)
+ * Copyright (c) 2012-2013 Olivier Scherrer <pode.fr@gmail.com> - Olivier Wietrich <olivier.wietrich@gmail.com>
+ */
+
+define(["Router", "Tools"],
+
+/**
+ * @class
+ * A locationRouter is a router which navigates to the route defined in the URL and updates this URL
+ * while navigating. It's a subtype of Emily's Router
+ */
+function LocationRouter(Router, Tools) {
+
+ "use strict";
+
+ function LocationRouterConstructor() {
+
+ /**
+ * The handle on the watch
+ * @private
+ */
+ var _watchHandle;
+
+ /**
+ * The function that parses the url to determine the route to navigate to.
+ * It has a default behavior explained below, but can be overriden as long as
+ * it has the same contract.
+ * @param {String} hash the hash coming from window.location.has
+ * @returns {Array} has to return an array with the list of arguments to call
+ * navigate with. The first item of the array must be the name of the route.
+ *
+ * Example: #album/holiday/2013
+ * will navigate to the route "album" and give two arguments "holiday" and "2013"
+ */
+ this.parse = function parse(hash) {
+ return hash.split("#").pop().split("/");
+ };
+
+ /**
+ * The function that converts, or serialises the route and its arguments to a valid URL.
+ * It has a default behavior below, but can be overriden as long as it has the same contract.
+ * @param {Array} args the list of arguments to serialize
+ * @returns {String} the serialized arguments to add to the url hashmark
+ *
+ * Example:
+ * ["album", "holiday", "2013"];
+ * will give "album/holiday/2013"
+ *
+ */
+ this.toUrl = function toUrl(args) {
+ return args.join("/");
+ };
+
+ /**
+ * When all the routes and handlers have been defined, start the location router
+ * so it parses the URL and navigates to the corresponding route.
+ * It will also start listening to route changes and hashmark changes to navigate.
+ * While navigating, the hashmark itself will also change to reflect the current route state
+ */
+ this.start = function start() {
+ var parsedHash = this.parse(window.location.hash);
+ this.navigate.apply(this, parsedHash);
+ this.bindOnHashChange();
+ this.bindOnRouteChange();
+ };
+
+ /**
+ * Remove the events handler for cleaning.
+ */
+ this.destroy = function destroy() {
+ this.unwatch(_watchHandle);
+ window.removeEventListener("hashchange", this.boundOnHashChange, true);
+ };
+
+ /**
+ * Parse the hash and navigate to the corresponding url
+ * @private
+ */
+ this.onHashChange = function onHashChange(event) {
+ var parsedHash = this.parse(event.newUrl.split("#").pop());
+ this.navigate.apply(this, parsedHash);
+ };
+
+ /**
+ * The bound version of onHashChange for add/removeEventListener
+ * @private
+ */
+ this.boundOnHashChange = this.onHashChange.bind(this);
+
+ /**
+ * Add an event listener to hashchange to navigate to the corresponding route
+ * when it changes
+ * @private
+ */
+ this.bindOnHashChange = function bindOnHashChange() {
+ window.addEventListener("hashchange", this.boundOnHashChange, true);
+ };
+
+ /**
+ * Watch route change events from the router to update the location
+ * @private
+ */
+ this.bindOnRouteChange = function bindOnRouteChange() {
+ _watchHandle = this.watch("route", this.onRouteChange, this);
+ };
+
+ /**
+ * The handler for when the route changes
+ * It updates the location
+ * @private
+ */
+ this.onRouteChange = function onRouteChange() {
+ window.location.hash = this.toUrl(Tools.toArray(arguments));
+ };
+
+ }
+
+ return function LocationRouterFactory() {
+ LocationRouterConstructor.prototype = new Router();
+ return new LocationRouterConstructor();
+ };
+
+});
View
6 build/src/OObject.js
@@ -13,6 +13,8 @@ define(["StateMachine", "Store", "Plugins", "DomUtils", "Tools"],
*/
function OObject(StateMachine, Store, Plugins, DomUtils, Tools) {
+ "use strict";
+
return function OObjectConstructor(otherStore) {
/**
@@ -45,7 +47,7 @@ function OObject(StateMachine, Store, Plugins, DomUtils, Tools) {
// as it wouldn't be possible to know which node would belong to which UI
// This is probably a DOM limitation.
if (baseNode.childNodes.length > 1) {
- throw Error("UI.template should have only one parent node");
+ throw new Error("UI.template should have only one parent node");
} else {
UI.dom = baseNode.childNodes[0];
}
@@ -54,7 +56,7 @@ function OObject(StateMachine, Store, Plugins, DomUtils, Tools) {
} else {
// An explicit message I hope
- throw Error("UI.template must be set prior to render");
+ throw new Error("UI.template must be set prior to render");
}
},
View
2 build/src/Place.plugin.js
@@ -12,6 +12,8 @@ define(["OObject", "Tools"],
*/
function PlacePlugin(OObject, Tools) {
+ "use strict";
+
/**
* Intilialize a Place.plugin with a list of OObjects
* @param {Object} $uis a list of OObjects such as:
View
2 build/src/Plugins.js
@@ -17,6 +17,8 @@ define(["Tools", "DomUtils"],
*/
function Plugins(Tools, DomUtils) {
+ "use strict";
+
return function PluginsConstructor($plugins) {
/**
View
172 build/src/Router.js
@@ -1,172 +0,0 @@
-/**
- * https://github.com/flams/Olives-services
- * The MIT License (MIT)
- * Copyright (c) 2012 Olivier Scherrer <pode.fr@gmail.com>
- */
-
-define(["Observable", "Store"],
-
-/**
- * @class
- * Routing allows for navigating in an application by defining routes.
- */
-function Router(Observable, Store) {
-
- return function RouterConstructor() {
-
- /**
- * The routes observable (the applications use it)
- * @private
- */
- var _routes = new Observable(),
-
- /**
- * The events observable (used by Routing)
- * @private
- */
- _events = new Observable(),
-
- /**
- * The routing history
- * @private
- */
- _history = new Store([]),
-
- /**
- * For navigating through the history, remembers the current position
- * @private
- */
- _currentPos = 0;
-
- /**
- * Only for debugging
- * @private
- */
- this.getRoutesObservable = function getRoutesObservable() {
- return _routes;
- };
-
- /**
- * Only for debugging
- * @private
- */
- this.getEventsObservable = function getEventsObservable() {
- return _events;
- };
-
- /**
- * Set a new route
- * @param {String} route the name of the route
- * @param {Function} func the function to be execute when navigating to the route
- * @param {Object} scope the scope in which to execute the function
- * @returns a handle to remove the route
- */
- this.set = function set() {
- return _routes.watch.apply(_routes, arguments);
- };
-
- /**
- * Remove a route
- * @param {Object} handle the handle provided by the set method
- * @returns true if successfully removed
- */
- this.unset = function unset(handle) {
- return _routes.unwatch(handle);
- };
-
- /**
- * Navigate to a route
- * @param {String} route the route to navigate to
- * @param {*} *params
- * @returns
- */
- this.navigate = function get(route, params) {
- if (this.load(route, params)) {
- _history.alter("push", {
- route: route,
- params: params
- });
- _currentPos = _history.getNbItems();
- return true;
- } else {
- return false;
- }
-
- };
-
- /**
- * Actually loads the route
- * @private
- */
- this.load = function load(route, params) {
- if (_routes.notify(route, params)) {
- _events.notify("route", route);
- return true;
- } else {
- return false;
- }
- };
-
- /**
- * Watch for route changes
- * @param {Function} func the func to execute when the route changes
- * @param {Object} scope the scope in which to execute the function
- * @returns {Object} the handle to unwatch for route changes
- */
- this.watch = function watch(func, scope) {
- return _events.watch("route", func, scope);
- };
-
- /**
- * Unwatch routes changes
- * @param {Object} handle the handle was returned by the watch function
- * @returns true if unwatch
- */
- this.unwatch = function unwatch(handle) {
- return _events.unwatch(handle);
- };
-
- /**
- * Get the history store, for debugging only
- * @private
- */
- this.getHistoryStore = function getHistoryStore() {
- return _history;
- };
-
- /**
- * Go back and forth in the history
- * @param {Number} nb the amount of history to rewind/forward
- * @returns true if history exists
- */
- this.go = function go(nb) {
- var history = _history.get(_currentPos + nb);
-
- if (history) {
- this.load(history.route, history.params);
- _currentPos += nb;
- return true;
- } else {
- return false;
- }
- };
-
- /**
- * Go back in the history, short for go(-1)
- * @returns
- */
- this.back = function back() {
- return this.go(-1);
- };
-
- /**
- * Go forward in the history, short for go(1)
- * @returns
- */
- this.forward = function forward() {
- return this.go(1);
- };
-
- };
-
-});
View
2 build/src/SocketIOTransport.js
@@ -12,6 +12,8 @@ define(["Observable", "Tools"],
*/
function SocketIOTransport(Observable, Tools) {
+ "use strict";
+
/**
* Defines the SocketIOTransport
* @private
View
278 build/src/Stack.js
@@ -0,0 +1,278 @@
+/**
+ * Olives http://flams.github.com/olives
+ * The MIT License (MIT)
+ * Copyright (c) 2012-2013 Olivier Scherrer <pode.fr@gmail.com> - Olivier Wietrich <olivier.wietrich@gmail.com>
+ */
+
+define(
+
+/**
+ * @class
+ * A Stack is a tool for managing DOM elements as groups. Within a group, dom elements
+ * can be added, removed, moved around. The group can be moved to another parent node
+ * while keeping the DOM elements in the same order, excluding the parent dom elements's
+ * children that are not in the Stack.
+ */
+function Stack() {
+
+ "use strict";
+
+ return function StackConstructor($parent) {
+
+ /**
+ * The parent DOM element is a documentFragment by default
+ * @private
+ */
+ var _parent = document.createDocumentFragment(),
+
+ /**
+ * The place where the dom elements hide
+ * @private
+ */
+ _hidePlace = document.createDocumentFragment(),
+
+ /**
+ * The list of dom elements that are part of the stack
+ * Helps for excluding elements that are not part of it
+ * @private
+ */
+ _childNodes = [];
+
+ /**
+ * Add a DOM element to the stack. It will be appended.
+ * @param {HTMLElement} dom the DOM element to add
+ * @returns {HTMLElement} dom
+ */
+ this.add = function add(dom) {
+ if (!this.has(dom) && dom instanceof HTMLElement) {
+ _parent.appendChild(dom);
+ _childNodes.push(dom);
+ return dom;
+ } else {
+ return false;
+ }
+ };
+
+ /**
+ * Remove a DOM element from the stack.
+ * @param {HTMLElement} dom the DOM element to remove
+ * @returns {HTMLElement} dom
+ */
+ this.remove = function remove(dom) {
+ var index;
+ if (this.has(dom)) {
+ index = _childNodes.indexOf(dom);
+ _parent.removeChild(dom);
+ _childNodes.splice(index, 1);
+ return dom;
+ } else {
+ return false;
+ }
+ };
+
+ /**
+ * Place a stack by appending its DOM elements to a new parent
+ * @param {HTMLElement} newParentDom the new DOM element to append the stack to
+ * @returns {HTMLElement} newParentDom
+ */
+ this.place = function place(newParentDom) {
+ if (newParentDom instanceof HTMLElement) {
+ [].slice.call(_parent.childNodes).forEach(function (childDom) {
+ if (this.has(childDom)) {
+ newParentDom.appendChild(childDom);
+ }
+ }, this);
+ return this._setParent(newParentDom);
+ } else {
+ return false;
+ }
+ };
+
+ /**
+ * Move an element up in the stack
+ * @param {HTMLElement} dom the dom element to move up
+ * @returns {HTMLElement} dom
+ */
+ this.up = function up(dom) {
+ if (this.has(dom)) {
+ var domPosition = this.getPosition(dom);
+ this.move(dom, domPosition + 2);
+ return dom;
+ } else {
+ return false;
+ }
+ };
+
+ /**
+ * Move an element down in the stack
+ * @param {HTMLElement} dom the dom element to move down
+ * @returns {HTMLElement} dom
+ */
+ this.down = function down(dom) {
+ if (this.has(dom)) {
+ var domPosition = this.getPosition(dom);
+ this.move(dom, domPosition - 1);
+ return dom;
+ } else {
+ return false;
+ }
+ };
+
+ /**
+ * Move an element that is already in the stack to a new position
+ * @param {HTMLElement} dom the dom element to move
+ * @param {Number} position the position to which to move the DOM element
+ * @returns {HTMLElement} dom
+ */
+ this.move = function move(dom, position) {
+ if (this.has(dom)) {
+ var domIndex = _childNodes.indexOf(dom);
+ _childNodes.splice(domIndex, 1);
+ _childNodes.splice(position, 0, dom);
+ // Preventing a bug in IE when insertBefore is not given a valid
+ // second argument
+ var nextElement = _childNodes[position +1];
+ if (nextElement) {
+ _parent.insertBefore(dom, nextElement);
+ } else {
+ _parent.appendChild(dom);
+ }
+ return dom;
+ } else {
+ return false;
+ }
+ };
+
+ /**
+ * Insert a new element at a specific position in the stack
+ * @param {HTMLElement} dom the dom element to insert
+ * @param {Number} position the position to which to insert the DOM element
+ * @returns {HTMLElement} dom
+ */
+ this.insert = function insert(dom, position) {
+ if (!this.has(dom) && dom instanceof HTMLElement) {
+ _childNodes.splice(position, 0, dom);
+ _parent.insertBefore(dom, _parent.childNodes[position]);
+ return dom;
+ } else {
+ return false;
+ }
+ };
+
+ /**
+ * Get the position of an element in the stack
+ * @param {HTMLElement} dom the dom to get the position from
+ * @returns {HTMLElement} dom
+ */
+ this.getPosition = function getPosition(dom) {
+ return _childNodes.indexOf(dom);
+ };
+
+ /**
+ * Count the number of elements in a stack
+ * @returns {Number} the number of items
+ */
+ this.count = function count() {
+ return _parent.childNodes.length;
+ };
+
+ /**
+ * Tells if a DOM element is in the stack
+ * @param {HTMLElement} dom the dom to tell if its in the stack
+ * @returns {HTMLElement} dom
+ */
+ this.has = function has(childDom) {
+ return this.getPosition(childDom) >= 0;
+ };
+
+ /**
+ * Hide a dom element that was previously added to the stack
+ * It will be taken out of the dom until displayed again
+ * @param {HTMLElement} dom the dom to hide
+ * @return {boolean} if dom element is in the stack
+ */
+ this.hide = function hide(dom) {
+ if (this.has(dom)) {
+ _hidePlace.appendChild(dom);
+ return true;
+ } else {
+ return false;
+ }
+ };
+
+ /**
+ * Show a dom element that was previously hidden
+ * It will be added back to the dom
+ * @param {HTMLElement} dom the dom to show
+ * @return {boolean} if dom element is current hidden
+ */
+ this.show = function show(dom) {
+ if (this.has(dom) && dom.parentNode === _hidePlace) {
+ this.move(dom, _childNodes.indexOf(dom));
+ return true;
+ } else {
+ return false;
+ }
+ };
+
+ /**
+ * Helper function for hiding all the dom elements
+ */
+ this.hideAll = function hideAll() {
+ _childNodes.forEach(this.hide, this);
+ };
+
+ /**
+ * Helper function for showing all the dom elements
+ */
+ this.showAll = function showAll() {
+ _childNodes.forEach(this.show, this);
+ };
+
+ /**
+ * Get the parent node that a stack is currently attached to
+ * @returns {HTMLElement} parent node
+ */
+ this.getParent = function _getParent() {
+ return _parent;
+ };
+
+ /**
+ * Set the parent element (without appending the stacks dom elements to)
+ * @private
+ */
+ this._setParent = function _setParent(parent) {
+ if (parent instanceof HTMLElement) {
+ _parent = parent;
+ return _parent;
+ } else {
+ return false;
+ }
+ };
+
+ /**
+ * Get the place where the DOM elements are hidden
+ * @private
+ */
+ this.getHidePlace = function getHidePlace() {
+ return _hidePlace;
+ };
+
+ /**
+ * Set the place where the DOM elements are hidden
+ * @private
+ */
+ this.setHidePlace = function setHidePlace(hidePlace) {
+ if (hidePlace instanceof HTMLElement) {
+ _hidePlace = hidePlace;
+ return true;
+ } else {
+ return false;
+ }
+ };
+
+ this._setParent($parent);
+
+ };
+
+});
View
342 docs/1.5.0/files.html
@@ -0,0 +1,342 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+ <head>
+ <meta http-equiv="content-type" content="text/html; charset=utf-8" />
+
+ <title>JsDoc Reference - File Index</title>
+ <meta name="generator" content="JsDoc Toolkit" />
+
+ <style type="text/css">
+ /* default.css */
+body
+{
+ font: 12px "Lucida Grande", Tahoma, Arial, Helvetica, sans-serif;
+ width: 800px;
+}
+
+.header
+{
+ clear: both;
+ background-color: #ccc;
+ padding: 8px;
+}
+
+h1
+{
+ font-size: 150%;
+ font-weight: bold;
+ padding: 0;
+ margin: 1em 0 0 .3em;
+}
+
+hr
+{
+ border: none 0;
+ border-top: 1px solid #7F8FB1;
+ height: 1px;
+}
+
+pre.code
+{
+ display: block;
+ padding: 8px;
+ border: 1px dashed #ccc;
+}
+
+#index
+{
+ margin-top: 24px;
+ float: left;
+ width: 160px;
+ position: absolute;
+ left: 8px;
+ background-color: #F3F3F3;
+ padding: 8px;
+}
+
+#content
+{
+ margin-left: 190px;
+ width: 600px;
+}
+
+.classList
+{