summaryrefslogtreecommitdiff
path: root/javascripts
diff options
context:
space:
mode:
authorDaniel Beauchamp <daniel.beauchamp@shopify.com>2012-10-30 05:16:35 -0400
committerDaniel Beauchamp <daniel.beauchamp@shopify.com>2012-10-30 05:16:35 -0400
commita4a4564f760bb1bcd541366186cd46488d5a569b (patch)
tree3737ae6d233464482482880bd858665866686f10 /javascripts
parent3a77d19282f2055559c63468c574b824138464ac (diff)
Added new widgets, and made them more flexible. Ready for 0.1.3!
Diffstat (limited to 'javascripts')
-rw-r--r--javascripts/batman.jquery.js52
-rw-r--r--javascripts/batman.js4970
-rw-r--r--javascripts/dashing.coffee2
3 files changed, 2816 insertions, 2208 deletions
diff --git a/javascripts/batman.jquery.js b/javascripts/batman.jquery.js
index 6407098..0716b0e 100644
--- a/javascripts/batman.jquery.js
+++ b/javascripts/batman.jquery.js
@@ -1,5 +1,57 @@
(function() {
+ Batman.extend(Batman.DOM, {
+ querySelectorAll: function(node, selector) {
+ return jQuery(selector, node);
+ },
+ querySelector: function(node, selector) {
+ return jQuery(selector, node)[0];
+ },
+ setInnerHTML: function(node, html) {
+ var child, childNodes, result, _i, _j, _len, _len1;
+ childNodes = (function() {
+ var _i, _len, _ref, _results;
+ _ref = node.childNodes;
+ _results = [];
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ child = _ref[_i];
+ _results.push(child);
+ }
+ return _results;
+ })();
+ for (_i = 0, _len = childNodes.length; _i < _len; _i++) {
+ child = childNodes[_i];
+ Batman.DOM.willRemoveNode(child);
+ }
+ result = jQuery(node).html(html);
+ for (_j = 0, _len1 = childNodes.length; _j < _len1; _j++) {
+ child = childNodes[_j];
+ Batman.DOM.didRemoveNode(child);
+ }
+ return result;
+ },
+ removeNode: function(node) {
+ var _ref;
+ Batman.DOM.willRemoveNode(node);
+ if ((_ref = node.parentNode) != null) {
+ _ref.removeChild(node);
+ }
+ return Batman.DOM.didRemoveNode(node);
+ },
+ destroyNode: function(node) {
+ Batman.DOM.willDestroyNode(node);
+ Batman.DOM.willRemoveNode(node);
+ jQuery(node).remove();
+ Batman.DOM.didRemoveNode(node);
+ return Batman.DOM.didDestroyNode(node);
+ },
+ appendChild: function(parent, child) {
+ Batman.DOM.willInsertNode(child);
+ jQuery(parent).append(child);
+ return Batman.DOM.didInsertNode(child);
+ }
+ });
+
Batman.Request.prototype._parseResponseHeaders = function(xhr) {
var headers;
return headers = xhr.getAllResponseHeaders().split('\n').reduce(function(acc, header) {
diff --git a/javascripts/batman.js b/javascripts/batman.js
index 22c7b3a..c4e5f34 100644
--- a/javascripts/batman.js
+++ b/javascripts/batman.js
@@ -12,10 +12,12 @@
})(Batman.Object, mixins, function(){});
};
- Batman.version = '0.10.0';
+ Batman.version = '0.13.0';
Batman.config = {
pathPrefix: '/',
+ viewPrefix: 'views',
+ fetchRemoteViews: true,
usePushState: false,
minificationErrors: true
};
@@ -47,6 +49,325 @@
}).call(this);
(function() {
+ var _implementImmediates, _objectToString,
+ __slice = [].slice,
+ __hasProp = {}.hasOwnProperty,
+ __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
+
+ Batman.typeOf = function(object) {
+ if (typeof object === 'undefined') {
+ return "Undefined";
+ }
+ return _objectToString.call(object).slice(8, -1);
+ };
+
+ _objectToString = Object.prototype.toString;
+
+ Batman.extend = function() {
+ var key, object, objects, to, value, _i, _len;
+ to = arguments[0], objects = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
+ for (_i = 0, _len = objects.length; _i < _len; _i++) {
+ object = objects[_i];
+ for (key in object) {
+ value = object[key];
+ to[key] = value;
+ }
+ }
+ return to;
+ };
+
+ Batman.mixin = function() {
+ var hasSet, key, mixin, mixins, to, value, _i, _len;
+ to = arguments[0], mixins = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
+ hasSet = typeof to.set === 'function';
+ for (_i = 0, _len = mixins.length; _i < _len; _i++) {
+ mixin = mixins[_i];
+ if (Batman.typeOf(mixin) !== 'Object') {
+ continue;
+ }
+ for (key in mixin) {
+ if (!__hasProp.call(mixin, key)) continue;
+ value = mixin[key];
+ if (key === 'initialize' || key === 'uninitialize' || key === 'prototype') {
+ continue;
+ }
+ if (hasSet) {
+ to.set(key, value);
+ } else if (to.nodeName != null) {
+ Batman.data(to, key, value);
+ } else {
+ to[key] = value;
+ }
+ }
+ if (typeof mixin.initialize === 'function') {
+ mixin.initialize.call(to);
+ }
+ }
+ return to;
+ };
+
+ Batman.unmixin = function() {
+ var from, key, mixin, mixins, _i, _len;
+ from = arguments[0], mixins = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
+ for (_i = 0, _len = mixins.length; _i < _len; _i++) {
+ mixin = mixins[_i];
+ for (key in mixin) {
+ if (key === 'initialize' || key === 'uninitialize') {
+ continue;
+ }
+ delete from[key];
+ }
+ if (typeof mixin.uninitialize === 'function') {
+ mixin.uninitialize.call(from);
+ }
+ }
+ return from;
+ };
+
+ Batman._functionName = Batman.functionName = function(f) {
+ var _ref;
+ if (f.__name__) {
+ return f.__name__;
+ }
+ if (f.name) {
+ return f.name;
+ }
+ return (_ref = f.toString().match(/\W*function\s+([\w\$]+)\(/)) != null ? _ref[1] : void 0;
+ };
+
+ Batman._isChildOf = Batman.isChildOf = function(parentNode, childNode) {
+ var node;
+ node = childNode.parentNode;
+ while (node) {
+ if (node === parentNode) {
+ return true;
+ }
+ node = node.parentNode;
+ }
+ return false;
+ };
+
+ Batman.setImmediate = Batman.clearImmediate = null;
+
+ _implementImmediates = function(container) {
+ var canUsePostMessage, count, functions, getHandle, handler, prefix, tasks;
+ canUsePostMessage = function() {
+ var async, oldMessage;
+ if (!container.postMessage) {
+ return false;
+ }
+ async = true;
+ oldMessage = container.onmessage;
+ container.onmessage = function() {
+ return async = false;
+ };
+ container.postMessage("", "*");
+ container.onmessage = oldMessage;
+ return async;
+ };
+ tasks = new Batman.SimpleHash;
+ count = 0;
+ getHandle = function() {
+ return "go" + (++count);
+ };
+ if (container.setImmediate) {
+ Batman.setImmediate = container.setImmediate;
+ Batman.clearImmediate = container.clearImmediate;
+ } else if (container.msSetImmediate) {
+ Batman.setImmediate = msSetImmediate;
+ Batman.clearImmediate = msClearImmediate;
+ } else if (canUsePostMessage()) {
+ prefix = 'com.batman.';
+ functions = new Batman.SimpleHash;
+ handler = function(e) {
+ var handle, _base;
+ if (!~e.data.search(prefix)) {
+ return;
+ }
+ handle = e.data.substring(prefix.length);
+ return typeof (_base = tasks.unset(handle)) === "function" ? _base() : void 0;
+ };
+ if (container.addEventListener) {
+ container.addEventListener('message', handler, false);
+ } else {
+ container.attachEvent('onmessage', handler);
+ }
+ Batman.setImmediate = function(f) {
+ var handle;
+ tasks.set(handle = getHandle(), f);
+ container.postMessage(prefix + handle, "*");
+ return handle;
+ };
+ Batman.clearImmediate = function(handle) {
+ return tasks.unset(handle);
+ };
+ } else if (typeof document !== 'undefined' && __indexOf.call(document.createElement("script"), "onreadystatechange") >= 0) {
+ Batman.setImmediate = function(f) {
+ var handle, script;
+ handle = getHandle();
+ script = document.createElement("script");
+ script.onreadystatechange = function() {
+ var _base;
+ if (typeof (_base = tasks.get(handle)) === "function") {
+ _base();
+ }
+ script.onreadystatechange = null;
+ script.parentNode.removeChild(script);
+ return script = null;
+ };
+ document.documentElement.appendChild(script);
+ return handle;
+ };
+ Batman.clearImmediate = function(handle) {
+ return tasks.unset(handle);
+ };
+ } else if (typeof process !== "undefined" && process !== null ? process.nextTick : void 0) {
+ functions = {};
+ Batman.setImmediate = function(f) {
+ var handle;
+ handle = getHandle();
+ functions[handle] = f;
+ process.nextTick(function() {
+ if (typeof functions[handle] === "function") {
+ functions[handle]();
+ }
+ return delete functions[handle];
+ });
+ return handle;
+ };
+ Batman.clearImmediate = function(handle) {
+ return delete functions[handle];
+ };
+ } else {
+ Batman.setImmediate = function(f) {
+ return setTimeout(f, 0);
+ };
+ Batman.clearImmediate = function(handle) {
+ return clearTimeout(handle);
+ };
+ }
+ Batman.setImmediate = Batman.setImmediate;
+ return Batman.clearImmediate = Batman.clearImmediate;
+ };
+
+ Batman.setImmediate = function() {
+ _implementImmediates(Batman.container);
+ return Batman.setImmediate.apply(this, arguments);
+ };
+
+ Batman.clearImmediate = function() {
+ _implementImmediates(Batman.container);
+ return Batman.clearImmediate.apply(this, arguments);
+ };
+
+ Batman.forEach = function(container, iterator, ctx) {
+ var e, i, k, v, _i, _len, _results, _results1;
+ if (container.forEach) {
+ return container.forEach(iterator, ctx);
+ } else if (container.indexOf) {
+ _results = [];
+ for (i = _i = 0, _len = container.length; _i < _len; i = ++_i) {
+ e = container[i];
+ _results.push(iterator.call(ctx, e, i, container));
+ }
+ return _results;
+ } else {
+ _results1 = [];
+ for (k in container) {
+ v = container[k];
+ _results1.push(iterator.call(ctx, k, v, container));
+ }
+ return _results1;
+ }
+ };
+
+ Batman.objectHasKey = function(object, key) {
+ if (typeof object.hasKey === 'function') {
+ return object.hasKey(key);
+ } else {
+ return key in object;
+ }
+ };
+
+ Batman.contains = function(container, item) {
+ if (container.indexOf) {
+ return __indexOf.call(container, item) >= 0;
+ } else if (typeof container.has === 'function') {
+ return container.has(item);
+ } else {
+ return Batman.objectHasKey(container, item);
+ }
+ };
+
+ Batman.get = function(base, key) {
+ if (typeof base.get === 'function') {
+ return base.get(key);
+ } else {
+ return Batman.Property.forBaseAndKey(base, key).getValue();
+ }
+ };
+
+ Batman.getPath = function(base, segments) {
+ var segment, _i, _len;
+ for (_i = 0, _len = segments.length; _i < _len; _i++) {
+ segment = segments[_i];
+ if (base != null) {
+ base = Batman.get(base, segment);
+ if (base == null) {
+ return base;
+ }
+ } else {
+ return void 0;
+ }
+ }
+ return base;
+ };
+
+ Batman.escapeHTML = (function() {
+ var replacements;
+ replacements = {
+ "&": "&amp;",
+ "<": "&lt;",
+ ">": "&gt;",
+ "\"": "&#34;",
+ "'": "&#39;"
+ };
+ return function(s) {
+ return ("" + s).replace(/[&<>'"]/g, function(c) {
+ return replacements[c];
+ });
+ };
+ })();
+
+ Batman.translate = function(x, values) {
+ if (values == null) {
+ values = {};
+ }
+ return Batman.helpers.interpolate(Batman.get(Batman.translate.messages, x), values);
+ };
+
+ Batman.translate.messages = {};
+
+ Batman.t = function() {
+ return Batman.translate.apply(Batman, arguments);
+ };
+
+ Batman.redirect = function(url) {
+ var _ref;
+ return (_ref = Batman.navigator) != null ? _ref.redirect(url) : void 0;
+ };
+
+ Batman.initializeObject = function(object) {
+ if (object._batman != null) {
+ return object._batman.check(object);
+ } else {
+ return object._batman = new Batman._Batman(object);
+ }
+ };
+
+}).call(this);
+
+(function() {
var __slice = [].slice,
__indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
@@ -370,325 +691,6 @@
}).call(this);
(function() {
- var _implementImmediates, _objectToString,
- __slice = [].slice,
- __hasProp = {}.hasOwnProperty,
- __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
-
- Batman.typeOf = function(object) {
- if (typeof object === 'undefined') {
- return "Undefined";
- }
- return _objectToString.call(object).slice(8, -1);
- };
-
- _objectToString = Object.prototype.toString;
-
- Batman.extend = function() {
- var key, object, objects, to, value, _i, _len;
- to = arguments[0], objects = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
- for (_i = 0, _len = objects.length; _i < _len; _i++) {
- object = objects[_i];
- for (key in object) {
- value = object[key];
- to[key] = value;
- }
- }
- return to;
- };
-
- Batman.mixin = function() {
- var hasSet, key, mixin, mixins, to, value, _i, _len;
- to = arguments[0], mixins = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
- hasSet = typeof to.set === 'function';
- for (_i = 0, _len = mixins.length; _i < _len; _i++) {
- mixin = mixins[_i];
- if (Batman.typeOf(mixin) !== 'Object') {
- continue;
- }
- for (key in mixin) {
- if (!__hasProp.call(mixin, key)) continue;
- value = mixin[key];
- if (key === 'initialize' || key === 'uninitialize' || key === 'prototype') {
- continue;
- }
- if (hasSet) {
- to.set(key, value);
- } else if (to.nodeName != null) {
- Batman.data(to, key, value);
- } else {
- to[key] = value;
- }
- }
- if (typeof mixin.initialize === 'function') {
- mixin.initialize.call(to);
- }
- }
- return to;
- };
-
- Batman.unmixin = function() {
- var from, key, mixin, mixins, _i, _len;
- from = arguments[0], mixins = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
- for (_i = 0, _len = mixins.length; _i < _len; _i++) {
- mixin = mixins[_i];
- for (key in mixin) {
- if (key === 'initialize' || key === 'uninitialize') {
- continue;
- }
- delete from[key];
- }
- if (typeof mixin.uninitialize === 'function') {
- mixin.uninitialize.call(from);
- }
- }
- return from;
- };
-
- Batman._functionName = Batman.functionName = function(f) {
- var _ref;
- if (f.__name__) {
- return f.__name__;
- }
- if (f.name) {
- return f.name;
- }
- return (_ref = f.toString().match(/\W*function\s+([\w\$]+)\(/)) != null ? _ref[1] : void 0;
- };
-
- Batman._isChildOf = Batman.isChildOf = function(parentNode, childNode) {
- var node;
- node = childNode.parentNode;
- while (node) {
- if (node === parentNode) {
- return true;
- }
- node = node.parentNode;
- }
- return false;
- };
-
- Batman.setImmediate = Batman.clearImmediate = null;
-
- _implementImmediates = function(container) {
- var canUsePostMessage, count, functions, getHandle, handler, prefix, tasks;
- canUsePostMessage = function() {
- var async, oldMessage;
- if (!container.postMessage) {
- return false;
- }
- async = true;
- oldMessage = container.onmessage;
- container.onmessage = function() {
- return async = false;
- };
- container.postMessage("", "*");
- container.onmessage = oldMessage;
- return async;
- };
- tasks = new Batman.SimpleHash;
- count = 0;
- getHandle = function() {
- return "go" + (++count);
- };
- if (container.setImmediate) {
- Batman.setImmediate = container.setImmediate;
- Batman.clearImmediate = container.clearImmediate;
- } else if (container.msSetImmediate) {
- Batman.setImmediate = msSetImmediate;
- Batman.clearImmediate = msClearImmediate;
- } else if (canUsePostMessage()) {
- prefix = 'com.batman.';
- functions = new Batman.SimpleHash;
- handler = function(e) {
- var handle, _base;
- if (!~e.data.search(prefix)) {
- return;
- }
- handle = e.data.substring(prefix.length);
- return typeof (_base = tasks.unset(handle)) === "function" ? _base() : void 0;
- };
- if (container.addEventListener) {
- container.addEventListener('message', handler, false);
- } else {
- container.attachEvent('onmessage', handler);
- }
- Batman.setImmediate = function(f) {
- var handle;
- tasks.set(handle = getHandle(), f);
- container.postMessage(prefix + handle, "*");
- return handle;
- };
- Batman.clearImmediate = function(handle) {
- return tasks.unset(handle);
- };
- } else if (typeof document !== 'undefined' && __indexOf.call(document.createElement("script"), "onreadystatechange") >= 0) {
- Batman.setImmediate = function(f) {
- var handle, script;
- handle = getHandle();
- script = document.createElement("script");
- script.onreadystatechange = function() {
- var _base;
- if (typeof (_base = tasks.get(handle)) === "function") {
- _base();
- }
- script.onreadystatechange = null;
- script.parentNode.removeChild(script);
- return script = null;
- };
- document.documentElement.appendChild(script);
- return handle;
- };
- Batman.clearImmediate = function(handle) {
- return tasks.unset(handle);
- };
- } else if (typeof process !== "undefined" && process !== null ? process.nextTick : void 0) {
- functions = {};
- Batman.setImmediate = function(f) {
- var handle;
- handle = getHandle();
- functions[handle] = f;
- process.nextTick(function() {
- if (typeof functions[handle] === "function") {
- functions[handle]();
- }
- return delete functions[handle];
- });
- return handle;
- };
- Batman.clearImmediate = function(handle) {
- return delete functions[handle];
- };
- } else {
- Batman.setImmediate = function(f) {
- return setTimeout(f, 0);
- };
- Batman.clearImmediate = function(handle) {
- return clearTimeout(handle);
- };
- }
- Batman.setImmediate = Batman.setImmediate;
- return Batman.clearImmediate = Batman.clearImmediate;
- };
-
- Batman.setImmediate = function() {
- _implementImmediates(Batman.container);
- return Batman.setImmediate.apply(this, arguments);
- };
-
- Batman.clearImmediate = function() {
- _implementImmediates(Batman.container);
- return Batman.clearImmediate.apply(this, arguments);
- };
-
- Batman.forEach = function(container, iterator, ctx) {
- var e, i, k, v, _i, _len, _results, _results1;
- if (container.forEach) {
- return container.forEach(iterator, ctx);
- } else if (container.indexOf) {
- _results = [];
- for (i = _i = 0, _len = container.length; _i < _len; i = ++_i) {
- e = container[i];
- _results.push(iterator.call(ctx, e, i, container));
- }
- return _results;
- } else {
- _results1 = [];
- for (k in container) {
- v = container[k];
- _results1.push(iterator.call(ctx, k, v, container));
- }
- return _results1;
- }
- };
-
- Batman.objectHasKey = function(object, key) {
- if (typeof object.hasKey === 'function') {
- return object.hasKey(key);
- } else {
- return key in object;
- }
- };
-
- Batman.contains = function(container, item) {
- if (container.indexOf) {
- return __indexOf.call(container, item) >= 0;
- } else if (typeof container.has === 'function') {
- return container.has(item);
- } else {
- return Batman.objectHasKey(container, item);
- }
- };
-
- Batman.get = function(base, key) {
- if (typeof base.get === 'function') {
- return base.get(key);
- } else {
- return Batman.Property.forBaseAndKey(base, key).getValue();
- }
- };
-
- Batman.getPath = function(base, segments) {
- var segment, _i, _len;
- for (_i = 0, _len = segments.length; _i < _len; _i++) {
- segment = segments[_i];
- if (base != null) {
- base = Batman.get(base, segment);
- if (base == null) {
- return base;
- }
- } else {
- return void 0;
- }
- }
- return base;
- };
-
- Batman.escapeHTML = (function() {
- var replacements;
- replacements = {
- "&": "&amp;",
- "<": "&lt;",
- ">": "&gt;",
- "\"": "&#34;",
- "'": "&#39;"
- };
- return function(s) {
- return ("" + s).replace(/[&<>'"]/g, function(c) {
- return replacements[c];
- });
- };
- })();
-
- Batman.translate = function(x, values) {
- if (values == null) {
- values = {};
- }
- return Batman.helpers.interpolate(Batman.get(Batman.translate.messages, x), values);
- };
-
- Batman.translate.messages = {};
-
- Batman.t = function() {
- return Batman.translate.apply(Batman, arguments);
- };
-
- Batman.redirect = function(url) {
- var _ref;
- return (_ref = Batman.navigator) != null ? _ref.redirect(url) : void 0;
- };
-
- Batman.initializeObject = function(object) {
- if (object._batman != null) {
- return object._batman.check(object);
- } else {
- return object._batman = new Batman._Batman(object);
- }
- };
-
-}).call(this);
-
-(function() {
var developer;
Batman.developer = {
@@ -1067,17 +1069,24 @@
return newEvent;
}
},
- on: function(key, handler) {
- return this.event(key).addHandler(handler);
+ on: function() {
+ var handler, key, keys, _i, _j, _len, _results;
+ keys = 2 <= arguments.length ? __slice.call(arguments, 0, _i = arguments.length - 1) : (_i = 0, []), handler = arguments[_i++];
+ _results = [];
+ for (_j = 0, _len = keys.length; _j < _len; _j++) {
+ key = keys[_j];
+ _results.push(this.event(key).addHandler(handler));
+ }
+ return _results;
},
- once: function(key, originalHandler) {
- var event, handler;
+ once: function(key, handler) {
+ var event, handlerWrapper;
event = this.event(key);
- handler = function() {
- originalHandler.apply(this, arguments);
- return event.removeHandler(handler);
+ handlerWrapper = function() {
+ handler.apply(this, arguments);
+ return event.removeHandler(handlerWrapper);
};
- return event.addHandler(handler);
+ return event.addHandler(handlerWrapper);
},
registerAsMutableSource: function() {
return Batman.Property.registerSource(this);
@@ -2262,20 +2271,6 @@
var _ref;
return (_ref = document.getElementById(elementID)) != null ? typeof _ref.scrollIntoView === "function" ? _ref.scrollIntoView() : void 0 : void 0;
},
- querySelectorAll: (typeof window !== "undefined" && window !== null ? window.jQuery : void 0) != null ? function(node, selector) {
- return jQuery(selector, node);
- } : (typeof document !== "undefined" && document !== null ? document.querySelectorAll : void 0) != null ? function(node, selector) {
- return node.querySelectorAll(selector);
- } : function() {
- return Batman.developer.error("Please include either jQuery or a querySelectorAll polyfill, or set Batman.DOM.querySelectorAll to return an empty array.");
- },
- querySelector: (typeof window !== "undefined" && window !== null ? window.jQuery : void 0) != null ? function(node, selector) {
- return jQuery(selector, node)[0];
- } : (typeof document !== "undefined" && document !== null ? document.querySelector : void 0) != null ? function(node, selector) {
- return node.querySelector(selector);
- } : function() {
- return Batman.developer.error("Please include either jQuery or a querySelector polyfill, or set Batman.DOM.querySelector to an empty function.");
- },
partial: function(container, path, context, renderer) {
var view;
renderer.prevent('rendered');
@@ -2284,12 +2279,12 @@
context: context
});
return view.on('ready', function() {
- Batman.setInnerHTML(container, '');
- Batman.appendChild(container, view.get('node'));
+ Batman.DOM.setInnerHTML(container, '');
+ Batman.DOM.appendChild(container, view.get('node'));
return renderer.allowAndFire('rendered');
});
},
- propagateBindingEvent: Batman.propagateBindingEvent = function(binding, node) {
+ propagateBindingEvent: function(binding, node) {
var current, parentBinding, parentBindings, _i, _len;
while ((current = (current || node).parentNode)) {
parentBindings = Batman._data(current, 'bindings');
@@ -2303,21 +2298,21 @@
}
}
},
- propagateBindingEvents: Batman.propagateBindingEvents = function(newNode) {
+ propagateBindingEvents: function(newNode) {
var binding, bindings, child, _i, _j, _len, _len1, _ref;
_ref = newNode.childNodes;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
child = _ref[_i];
- Batman.propagateBindingEvents(child);
+ Batman.DOM.propagateBindingEvents(child);
}
if (bindings = Batman._data(newNode, 'bindings')) {
for (_j = 0, _len1 = bindings.length; _j < _len1; _j++) {
binding = bindings[_j];
- Batman.propagateBindingEvent(binding, newNode);
+ Batman.DOM.propagateBindingEvent(binding, newNode);
}
}
},
- trackBinding: Batman.trackBinding = function(binding, node) {
+ trackBinding: function(binding, node) {
var bindings;
if (bindings = Batman._data(node, 'bindings')) {
bindings.push(binding);
@@ -2325,10 +2320,10 @@
Batman._data(node, 'bindings', [binding]);
}
Batman.DOM.fire('bindingAdded', binding);
- Batman.propagateBindingEvent(binding, node);
+ Batman.DOM.propagateBindingEvent(binding, node);
return true;
},
- onParseExit: Batman.onParseExit = function(node, callback) {
+ onParseExit: function(node, callback) {
var set;
set = Batman._data(node, 'onParseExit') || Batman._data(node, 'onParseExit', new Batman.SimpleSet);
if (callback != null) {
@@ -2336,7 +2331,7 @@
}
return set;
},
- forgetParseExit: Batman.forgetParseExit = function(node, callback) {
+ forgetParseExit: function(node, callback) {
return Batman.removeData(node, 'onParseExit', true);
},
defineView: function(name, node) {
@@ -2345,55 +2340,14 @@
Batman.View.store.set(Batman.Navigator.normalizePath(name), contents);
return contents;
},
- setInnerHTML: Batman.setInnerHTML = function(node, html) {
- var child, childNodes, result, _i, _j, _len, _len1;
- childNodes = (function() {
- var _i, _len, _ref, _results;
- _ref = node.childNodes;
- _results = [];
- for (_i = 0, _len = _ref.length; _i < _len; _i++) {
- child = _ref[_i];
- _results.push(child);
- }
- return _results;
- })();
- for (_i = 0, _len = childNodes.length; _i < _len; _i++) {
- child = childNodes[_i];
- Batman.DOM.willRemoveNode(child);
- }
- result = node.innerHTML = html;
- for (_j = 0, _len1 = childNodes.length; _j < _len1; _j++) {
- child = childNodes[_j];
- Batman.DOM.didRemoveNode(child);
- }
- return result;
- },
- setStyleProperty: Batman.setStyleProperty = function(node, property, value, importance) {
- if (node.style.setAttribute) {
- return node.style.setAttribute(property, value, importance);
- } else {
+ setStyleProperty: function(node, property, value, importance) {
+ if (node.style.setProperty) {
return node.style.setProperty(property, value, importance);
+ } else {
+ return node.style.setAttribute(property, value, importance);
}
},
- removeNode: Batman.removeNode = function(node) {
- var _ref;
- Batman.DOM.willRemoveNode(node);
- if ((_ref = node.parentNode) != null) {
- _ref.removeChild(node);
- }
- return Batman.DOM.didRemoveNode(node);
- },
- destroyNode: Batman.destroyNode = function(node) {
- Batman.DOM.willDestroyNode(node);
- Batman.removeNode(node);
- return Batman.DOM.didDestroyNode(node);
- },
- appendChild: Batman.appendChild = function(parent, child) {
- Batman.DOM.willInsertNode(child);
- parent.appendChild(child);
- return Batman.DOM.didInsertNode(child);
- },
- removeOrDestroyNode: Batman.removeOrDestroyNode = function(node) {
+ removeOrDestroyNode: function(node) {
var view;
view = Batman._data(node, 'view');
view || (view = Batman._data(node, 'yielder'));
@@ -2403,12 +2357,12 @@
return Batman.DOM.destroyNode(node);
}
},
- insertBefore: Batman.insertBefore = function(parentNode, newNode, referenceNode) {
+ insertBefore: function(parentNode, newNode, referenceNode) {
if (referenceNode == null) {
referenceNode = null;
}
if (!referenceNode || parentNode.childNodes.length <= 0) {
- return Batman.appendChild(parentNode, newNode);
+ return Batman.DOM.appendChild(parentNode, newNode);
} else {
Batman.DOM.willInsertNode(newNode);
parentNode.insertBefore(newNode, referenceNode);
@@ -2440,7 +2394,7 @@
break;
default:
if (isSetting) {
- return Batman.setInnerHTML(node, escapeValue ? Batman.escapeHTML(value) : value);
+ return Batman.DOM.setInnerHTML(node, escapeValue ? Batman.escapeHTML(value) : value);
} else {
return node.innerHTML;
}
@@ -2450,7 +2404,7 @@
var _ref;
return (_ref = node.nodeName.toUpperCase()) === 'INPUT' || _ref === 'TEXTAREA' || _ref === 'SELECT';
},
- addEventListener: Batman.addEventListener = function(node, eventName, callback) {
+ addEventListener: function(node, eventName, callback) {
var listeners;
if (!(listeners = Batman._data(node, 'listeners'))) {
listeners = Batman._data(node, 'listeners', {});
@@ -2459,13 +2413,13 @@
listeners[eventName] = [];
}
listeners[eventName].push(callback);
- if (Batman.hasAddEventListener) {
+ if (Batman.DOM.hasAddEventListener) {
return node.addEventListener(eventName, callback, false);
} else {
return node.attachEvent("on" + eventName, callback);
}
},
- removeEventListener: Batman.removeEventListener = function(node, eventName, callback) {
+ removeEventListener: function(node, eventName, callback) {
var eventListeners, index, listeners;
if (listeners = Batman._data(node, 'listeners')) {
if (eventListeners = listeners[eventName]) {
@@ -2475,21 +2429,21 @@
}
}
}
- if (Batman.hasAddEventListener) {
+ if (Batman.DOM.hasAddEventListener) {
return node.removeEventListener(eventName, callback, false);
} else {
return node.detachEvent('on' + eventName, callback);
}
},
- hasAddEventListener: Batman.hasAddEventListener = !!(typeof window !== "undefined" && window !== null ? window.addEventListener : void 0),
- preventDefault: Batman.preventDefault = function(e) {
+ hasAddEventListener: !!(typeof window !== "undefined" && window !== null ? window.addEventListener : void 0),
+ preventDefault: function(e) {
if (typeof e.preventDefault === "function") {
return e.preventDefault();
} else {
return e.returnValue = false;
}
},
- stopPropagation: Batman.stopPropagation = function(e) {
+ stopPropagation: function(e) {
if (e.stopPropagation) {
return e.stopPropagation();
} else {
@@ -2602,7 +2556,7 @@
for (eventName in listeners) {
eventListeners = listeners[eventName];
eventListeners.forEach(function(listener) {
- return Batman.removeEventListener(node, eventName, listener);
+ return Batman.DOM.removeEventListener(node, eventName, listener);
});
}
}
@@ -2706,7 +2660,7 @@
return true;
},
defineview: function(node, name, context, renderer) {
- Batman.onParseExit(node, function() {
+ Batman.DOM.onParseExit(node, function() {
var _ref;
return (_ref = node.parentNode) != null ? _ref.removeChild(node) : void 0;
});
@@ -2718,7 +2672,7 @@
return false;
},
"yield": function(node, key) {
- Batman.onParseExit(node, function() {
+ Batman.DOM.onParseExit(node, function() {
return Batman.DOM.Yield.withName(key).set('containerNode', node);
});
return true;
@@ -2727,7 +2681,7 @@
if (action == null) {
action = 'append';
}
- Batman.onParseExit(node, function() {
+ Batman.DOM.onParseExit(node, function() {
var _ref;
if ((_ref = node.parentNode) != null) {
_ref.removeChild(node);
@@ -2753,11 +2707,17 @@
if (eventName == null) {
eventName = 'click';
}
- Batman.addEventListener(node, eventName, function() {
- var args;
- args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
- callback.apply(null, [node].concat(__slice.call(args), [context]));
- return Batman.preventDefault(args[0]);
+ Batman.DOM.addEventListener(node, eventName, function() {
+ var args, event;
+ event = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
+ if (event.metaKey || event.ctrlKey) {
+ return;
+ }
+ Batman.DOM.preventDefault(event);
+ if (!Batman.DOM.eventIsAllowed(eventName, event)) {
+ return;
+ }
+ return callback.apply(null, [node, event].concat(__slice.call(args), [context]));
});
if (node.nodeName.toUpperCase() === 'A' && !node.href) {
node.href = '#';
@@ -2795,7 +2755,7 @@
_results = [];
for (_i = 0, _len = eventNames.length; _i < _len; _i++) {
eventName = eventNames[_i];
- _results.push(Batman.addEventListener(node, eventName, function() {
+ _results.push(Batman.DOM.addEventListener(node, eventName, function() {
var args;
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
return callback.apply(null, [node].concat(__slice.call(args), [context]));
@@ -2809,36 +2769,36 @@
},
submit: function(node, callback, context) {
if (Batman.DOM.nodeIsEditable(node)) {
- Batman.addEventListener(node, 'keydown', function() {
+ Batman.DOM.addEventListener(node, 'keydown', function() {
var args;
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
if (Batman.DOM.events.isEnter(args[0])) {
return Batman.DOM._keyCapturingNode = node;
}
});
- Batman.addEventListener(node, 'keyup', function() {
+ Batman.DOM.addEventListener(node, 'keyup', function() {
var args;
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
if (Batman.DOM.events.isEnter(args[0])) {
if (Batman.DOM._keyCapturingNode === node) {
- Batman.preventDefault(args[0]);
+ Batman.DOM.preventDefault(args[0]);
callback.apply(null, [node].concat(__slice.call(args), [context]));
}
return Batman.DOM._keyCapturingNode = null;
}
});
} else {
- Batman.addEventListener(node, 'submit', function() {
+ Batman.DOM.addEventListener(node, 'submit', function() {
var args;
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
- Batman.preventDefault(args[0]);
+ Batman.DOM.preventDefault(args[0]);
return callback.apply(null, [node].concat(__slice.call(args), [context]));
});
}
return node;
},
other: function(node, eventName, callback, context) {
- return Batman.addEventListener(node, eventName, function() {
+ return Batman.DOM.addEventListener(node, eventName, function() {
var args;
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
return callback.apply(null, [node].concat(__slice.call(args), [context]));
@@ -2846,6 +2806,16 @@
}
};
+ Batman.DOM.eventIsAllowed = function(eventName, event) {
+ var delegate, _ref, _ref1;
+ if (delegate = (_ref = Batman.currentApp) != null ? (_ref1 = _ref.shouldAllowEvent) != null ? _ref1[eventName] : void 0 : void 0) {
+ if (delegate(event) === false) {
+ return false;
+ }
+ }
+ return true;
+ };
+
}).call(this);
(function() {
@@ -2930,123 +2900,83 @@
}).call(this);
(function() {
- var BatmanObject,
+ var BatmanObject, ObjectFunctions, getAccessorObject, promiseWrapper, wrapSingleAccessor,
+ __slice = [].slice,
__hasProp = {}.hasOwnProperty,
- __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
- __slice = [].slice;
-
- BatmanObject = (function(_super) {
- var counter, getAccessorObject, promiseWrapper, wrapSingleAccessor;
-
- __extends(BatmanObject, _super);
-
- Batman.initializeObject(BatmanObject);
-
- Batman.initializeObject(BatmanObject.prototype);
-
- BatmanObject.classMixin = function() {
- return Batman.mixin.apply(Batman, [this].concat(__slice.call(arguments)));
- };
-
- BatmanObject.mixin = function() {
- return this.classMixin.apply(this.prototype, arguments);
- };
-
- BatmanObject.prototype.mixin = BatmanObject.classMixin;
-
- counter = 0;
+ __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
- BatmanObject.prototype._batmanID = function() {
- var c;
- this._batmanID = function() {
- return c;
+ getAccessorObject = function(base, accessor) {
+ var deprecated, _i, _len, _ref;
+ if (typeof accessor === 'function') {
+ accessor = {
+ get: accessor
};
- return c = counter++;
- };
-
- BatmanObject.prototype.hashKey = function() {
- var key;
- if (typeof this.isEqual === 'function') {
- return;
- }
- this.hashKey = function() {
- return key;
- };
- return key = "<Batman.Object " + (this._batmanID()) + ">";
- };
-
- BatmanObject.prototype.toJSON = function() {
- var key, obj, value;
- obj = {};
- for (key in this) {
- if (!__hasProp.call(this, key)) continue;
- value = this[key];
- if (key !== "_batman" && key !== "hashKey" && key !== "_batmanID") {
- obj[key] = (value != null ? value.toJSON : void 0) ? value.toJSON() : value;
+ }
+ _ref = ['cachable', 'cacheable'];
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ deprecated = _ref[_i];
+ if (deprecated in accessor) {
+ Batman.developer.warn("Property accessor option \"" + deprecated + "\" is deprecated. Use \"cache\" instead.");
+ if (!('cache' in accessor)) {
+ accessor.cache = accessor[deprecated];
}
}
- return obj;
- };
+ }
+ return accessor;
+ };
- getAccessorObject = function(base, accessor) {
- var deprecated, _i, _len, _ref;
- if (typeof accessor === 'function') {
- accessor = {
- get: accessor
- };
- }
- _ref = ['cachable', 'cacheable'];
- for (_i = 0, _len = _ref.length; _i < _len; _i++) {
- deprecated = _ref[_i];
- if (deprecated in accessor) {
- Batman.developer.warn("Property accessor option \"" + deprecated + "\" is deprecated. Use \"cache\" instead.");
- if (!('cache' in accessor)) {
- accessor.cache = accessor[deprecated];
+ promiseWrapper = function(fetcher) {
+ return function(defaultAccessor) {
+ return {
+ get: function(key) {
+ var asyncDeliver, existingValue, newValue, _base, _base1, _ref, _ref1,
+ _this = this;
+ if ((existingValue = defaultAccessor.get.apply(this, arguments)) != null) {
+ return existingValue;
}
- }
- }
- return accessor;
- };
-
- promiseWrapper = function(fetcher) {
- return function(core) {
- return {
- get: function(key) {
- var deliver, returned, val,
- _this = this;
- val = core.get.apply(this, arguments);
- if (typeof val !== 'undefined') {
- return val;
- }
- returned = false;
- deliver = function(err, result) {
- if (returned) {
- _this.set(key, result);
+ asyncDeliver = false;
+ newValue = void 0;
+ if ((_ref = (_base = this._batman).promises) == null) {
+ _base.promises = {};
+ }
+ if ((_ref1 = (_base1 = this._batman.promises)[key]) == null) {
+ _base1[key] = (function() {
+ var deliver, returnValue;
+ deliver = function(err, result) {
+ if (asyncDeliver) {
+ _this.set(key, result);
+ }
+ return newValue = result;
+ };
+ returnValue = fetcher.call(_this, deliver, key);
+ if (newValue == null) {
+ newValue = returnValue;
}
- return val = result;
- };
- fetcher.call(this, deliver, key);
- returned = true;
- return val;
- },
- cache: true
- };
+ return true;
+ })();
+ }
+ asyncDeliver = true;
+ return newValue;
+ },
+ cache: true
};
};
+ };
- wrapSingleAccessor = function(core, wrapper) {
- var k, v;
- wrapper = (typeof wrapper === "function" ? wrapper(core) : void 0) || wrapper;
- for (k in core) {
- v = core[k];
- if (!(k in wrapper)) {
- wrapper[k] = v;
- }
+ wrapSingleAccessor = function(core, wrapper) {
+ var k, v;
+ wrapper = (typeof wrapper === "function" ? wrapper(core) : void 0) || wrapper;
+ for (k in core) {
+ v = core[k];
+ if (!(k in wrapper)) {
+ wrapper[k] = v;
}
- return wrapper;
- };
+ }
+ return wrapper;
+ };
- BatmanObject._defineAccessor = function() {
+ ObjectFunctions = {
+ _defineAccessor: function() {
var accessor, key, keys, _base, _i, _j, _len, _ref, _results;
keys = 2 <= arguments.length ? __slice.call(arguments, 0, _i = arguments.length - 1) : (_i = 0, []), accessor = arguments[_i++];
if (!(accessor != null)) {
@@ -3068,11 +2998,8 @@
}
return _results;
}
- };
-
- BatmanObject.prototype._defineAccessor = BatmanObject._defineAccessor;
-
- BatmanObject._defineWrapAccessor = function() {
+ },
+ _defineWrapAccessor: function() {
var key, keys, wrapper, _i, _j, _len, _results;
keys = 2 <= arguments.length ? __slice.call(arguments, 0, _i = arguments.length - 1) : (_i = 0, []), wrapper = arguments[_i++];
Batman.initializeObject(this);
@@ -3086,9 +3013,45 @@
}
return _results;
}
+ },
+ _resetPromises: function() {
+ var key;
+ if (this._batman.promises == null) {
+ return;
+ }
+ for (key in this._batman.promises) {
+ this._resetPromise(key);
+ }
+ },
+ _resetPromise: function(key) {
+ this.unset(key);
+ this.property(key).cached = false;
+ delete this._batman.promises[key];
+ }
+ };
+
+ BatmanObject = (function(_super) {
+ var counter;
+
+ __extends(BatmanObject, _super);
+
+ Batman.initializeObject(BatmanObject);
+
+ Batman.initializeObject(BatmanObject.prototype);
+
+ Batman.mixin(BatmanObject.prototype, ObjectFunctions, Batman.EventEmitter, Batman.Observable);
+
+ Batman.mixin(BatmanObject, ObjectFunctions, Batman.EventEmitter, Batman.Observable);
+
+ BatmanObject.classMixin = function() {
+ return Batman.mixin.apply(Batman, [this].concat(__slice.call(arguments)));
+ };
+
+ BatmanObject.mixin = function() {
+ return this.classMixin.apply(this.prototype, arguments);
};
- BatmanObject.prototype._defineWrapAccessor = BatmanObject._defineWrapAccessor;
+ BatmanObject.prototype.mixin = BatmanObject.classMixin;
BatmanObject.classAccessor = BatmanObject._defineAccessor;
@@ -3108,17 +3071,6 @@
BatmanObject.prototype.wrapAccessor = BatmanObject._defineWrapAccessor;
- function BatmanObject() {
- var mixins;
- mixins = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
- this._batman = new Batman._Batman(this);
- this.mixin.apply(this, mixins);
- }
-
- BatmanObject.classMixin(Batman.EventEmitter, Batman.Observable);
-
- BatmanObject.mixin(Batman.EventEmitter, Batman.Observable);
-
BatmanObject.observeAll = function() {
return this.prototype.observe.apply(this.prototype, arguments);
};
@@ -3139,6 +3091,48 @@
return this._batmanID();
});
+ function BatmanObject() {
+ var mixins;
+ mixins = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
+ this._batman = new Batman._Batman(this);
+ this.mixin.apply(this, mixins);
+ }
+
+ counter = 0;
+
+ BatmanObject.prototype._batmanID = function() {
+ var _base, _ref;
+ this._batman.check(this);
+ if ((_ref = (_base = this._batman).id) == null) {
+ _base.id = counter++;
+ }
+ return this._batman.id;
+ };
+
+ BatmanObject.prototype.hashKey = function() {
+ var key;
+ if (typeof this.isEqual === 'function') {
+ return;
+ }
+ this.hashKey = function() {
+ return key;
+ };
+ return key = "<Batman.Object " + (this._batmanID()) + ">";
+ };
+
+ BatmanObject.prototype.toJSON = function() {
+ var key, obj, value;
+ obj = {};
+ for (key in this) {
+ if (!__hasProp.call(this, key)) continue;
+ value = this[key];
+ if (key !== "_batman" && key !== "hashKey" && key !== "_batmanID") {
+ obj[key] = (value != null ? value.toJSON : void 0) ? value.toJSON() : value;
+ }
+ }
+ return obj;
+ };
+
return BatmanObject;
})(Object);
@@ -3176,6 +3170,8 @@
Renderer.prototype.start = function() {
this.startTime = new Date;
+ this.prevent('parsed');
+ this.prevent('rendered');
return this.parseNode(this.node);
};
@@ -3187,8 +3183,8 @@
Renderer.prototype.finish = function() {
this.startTime = null;
this.prevent('stopped');
- this.fire('parsed');
- return this.fire('rendered');
+ this.allowAndFire('parsed');
+ return this.allowAndFire('rendered');
};
Renderer.prototype.stop = function() {
@@ -3265,7 +3261,7 @@
} else if (result instanceof Batman.RenderContext) {
oldContext = this.context;
this.context = result;
- Batman.onParseExit(node, function() {
+ Batman.DOM.onParseExit(node, function() {
return _this.context = oldContext;
});
}
@@ -3287,12 +3283,12 @@
}
}
sibling = node.nextSibling;
- if ((_ref1 = Batman.onParseExit(node)) != null) {
+ if ((_ref1 = Batman.DOM.onParseExit(node)) != null) {
_ref1.forEach(function(callback) {
return callback();
});
}
- Batman.forgetParseExit(node);
+ Batman.DOM.forgetParseExit(node);
if (this.node === node) {
return;
}
@@ -3302,12 +3298,12 @@
nextParent = node;
while (nextParent = nextParent.parentNode) {
parentSibling = nextParent.nextSibling;
- if ((_ref2 = Batman.onParseExit(nextParent)) != null) {
+ if ((_ref2 = Batman.DOM.onParseExit(nextParent)) != null) {
_ref2.forEach(function(callback) {
return callback();
});
}
- Batman.forgetParseExit(nextParent);
+ Batman.DOM.forgetParseExit(nextParent);
if (this.node === nextParent) {
return;
}
@@ -3636,7 +3632,7 @@
if (typeof (hide = Batman.data(this.node, 'hide')) === 'function') {
hide.call(this.node);
} else {
- Batman.setStyleProperty(this.node, 'display', 'none', 'important');
+ Batman.DOM.setStyleProperty(this.node, 'display', 'none', 'important');
}
return view != null ? view.fire('disappear', this.node) : void 0;
}
@@ -3659,7 +3655,7 @@
SelectBinding.prototype.isInputBinding = true;
- SelectBinding.prototype.firstBind = true;
+ SelectBinding.prototype.canSetImplicitly = true;
function SelectBinding() {
this.updateOptionBindings = __bind(this.updateOptionBindings, this);
@@ -3700,9 +3696,16 @@
return this._fireDataChange(this.get('filteredValue'));
};
+ SelectBinding.prototype.lastKeyContext = null;
+
SelectBinding.prototype.dataChange = function(newValue) {
var child, matches, valueToChild, _i, _len, _name, _ref,
_this = this;
+ this.lastKeyContext || (this.lastKeyContext = this.get('keyContext'));
+ if (this.lastKeyContext !== this.get('keyContext')) {
+ this.canSetImplicitly = true;
+ this.lastKeyContext = this.get('keyContext');
+ }
if (newValue != null ? newValue.forEach : void 0) {
valueToChild = {};
_ref = this.node.children;
@@ -3724,12 +3727,15 @@
}
});
} else {
- if (typeof newValue === 'undefined' && this.firstBind) {
- this.set('unfilteredValue', this.node.value);
+ if (!(newValue != null) && this.canSetImplicitly) {
+ if (this.node.value) {
+ this.canSetImplicitly = false;
+ this.set('unfilteredValue', this.node.value);
+ }
} else {
+ this.canSetImplicitly = false;
Batman.DOM.valueForNode(this.node, newValue, this.escapeValue);
}
- this.firstBind = false;
}
this.updateOptionBindings();
};
@@ -4047,7 +4053,7 @@
this.contextName = contextName;
delete this.attributeName;
Batman.DOM.events.submit(this.get('node'), function(node, e) {
- return Batman.preventDefault(e);
+ return Batman.DOM.preventDefault(e);
});
this.setupErrorsList();
}
@@ -4065,7 +4071,7 @@
FormBinding.prototype.setupErrorsList = function() {
if (this.errorsListNode = Batman.DOM.querySelector(this.get('node'), this.get('errorsListSelector'))) {
- Batman.setInnerHTML(this.errorsListNode, this.errorsListHTML());
+ Batman.DOM.setInnerHTML(this.errorsListNode, this.errorsListHTML());
if (!this.errorsListNode.getAttribute('data-showif')) {
return this.errorsListNode.setAttribute('data-showif', "" + this.contextName + ".errors.length");
}
@@ -4093,15 +4099,11 @@
EventBinding.prototype.bindImmediately = false;
function EventBinding(node, eventName, key, context) {
- var attacher, callback, confirmText,
+ var attacher, callback,
_this = this;
EventBinding.__super__.constructor.apply(this, arguments);
- confirmText = this.node.getAttribute('data-confirm');
callback = function() {
var _ref;
- if (confirmText && !confirm(confirmText)) {
- return;
- }
return (_ref = _this.get('filteredValue')) != null ? _ref.apply(_this.get('callbackContext'), arguments) : void 0;
};
if (attacher = Batman.DOM.events[this.attributeName]) {
@@ -4132,8 +4134,8 @@
if (keys.length > 1) {
functionKey = keys.pop();
keyContext = Batman.getPath(this, ['keyContext'].concat(keys));
+ keyContext = Batman.RenderContext.deProxy(keyContext);
if (keyContext != null) {
- keyContext = Batman.RenderContext.deProxy(keyContext);
return keyContext[functionKey];
}
}
@@ -4506,11 +4508,11 @@
if (Batman.canDeleteExpando) {
delete sourceNode[Batman.expando];
}
- Batman.insertBefore(sourceNode.parentNode, this.startNode, previousSiblingNode);
- Batman.insertBefore(sourceNode.parentNode, this.endNode, previousSiblingNode);
+ Batman.DOM.insertBefore(sourceNode.parentNode, this.startNode, previousSiblingNode);
+ Batman.DOM.insertBefore(sourceNode.parentNode, this.endNode, previousSiblingNode);
this.parentRenderer.prevent('rendered');
Batman.DOM.onParseExit(sourceNode.parentNode, function() {
- Batman.destroyNode(sourceNode);
+ Batman.DOM.destroyNode(sourceNode);
_this.bind();
return _this.parentRenderer.allowAndFire('rendered');
});
@@ -4546,15 +4548,17 @@
parentNode = this.parentNode();
startIndex = this._getStartNodeIndex() + 1;
unseenNodeMap = this.nodeMap.merge();
- for (index = _i = 0, _len = newItems.length; _i < _len; index = ++_i) {
- newItem = newItems[index];
- nodeAtIndex = parentNode.childNodes[startIndex + index];
- if ((nodeAtIndex != null) && this._itemForNode(nodeAtIndex) === newItem) {
- unseenNodeMap.unset(newItem);
- continue;
- } else {
- node = (existingNode = this.nodeMap.get(newItem)) ? (unseenNodeMap.unset(newItem), existingNode) : this._newNodeForItem(newItem);
- Batman.insertBefore(this.parentNode(), node, nodeAtIndex);
+ if (newItems != null) {
+ for (index = _i = 0, _len = newItems.length; _i < _len; index = ++_i) {
+ newItem = newItems[index];
+ nodeAtIndex = parentNode.childNodes[startIndex + index];
+ if ((nodeAtIndex != null) && this._itemForNode(nodeAtIndex) === newItem) {
+ unseenNodeMap.unset(newItem);
+ continue;
+ } else {
+ node = (existingNode = this.nodeMap.get(newItem)) ? (unseenNodeMap.unset(newItem), existingNode) : this._newNodeForItem(newItem);
+ Batman.DOM.insertBefore(this.parentNode(), node, nodeAtIndex);
+ }
}
}
unseenNodeMap.forEach(function(item, node) {
@@ -4575,7 +4579,7 @@
this.parentRenderer.prevent('rendered');
renderer = new Batman.Renderer(newNode, this.renderContext.descend(newItem, this.iteratorName), this.parentRenderer.view);
renderer.on('rendered', function() {
- Batman.propagateBindingEvents(newNode);
+ Batman.DOM.propagateBindingEvents(newNode);
_this.fire('nodeAdded', newNode, newItem);
return _this.parentRenderer.allowAndFire('rendered');
});
@@ -4597,7 +4601,7 @@
IteratorBinding.prototype._removeItem = function(item) {
var node;
node = this.nodeMap.unset(item);
- Batman.destroyNode(node);
+ Batman.DOM.destroyNode(node);
return this.fire('nodeRemoved', node, item);
};
@@ -4746,6 +4750,76 @@
})(StorageAdapter.StorageError);
+ StorageAdapter.NotAllowedError = (function(_super1) {
+
+ __extends(NotAllowedError, _super1);
+
+ NotAllowedError.prototype.name = "NotAllowedError";
+
+ function NotAllowedError(message) {
+ NotAllowedError.__super__.constructor.call(this, message || "Storage operation denied access to the operation!");
+ }
+
+ return NotAllowedError;
+
+ })(StorageAdapter.StorageError);
+
+ StorageAdapter.NotAcceptableError = (function(_super1) {
+
+ __extends(NotAcceptableError, _super1);
+
+ NotAcceptableError.prototype.name = "NotAcceptableError";
+
+ function NotAcceptableError(message) {
+ NotAcceptableError.__super__.constructor.call(this, message || "Storage operation permitted but the request was malformed!");
+ }
+
+ return NotAcceptableError;
+
+ })(StorageAdapter.StorageError);
+
+ StorageAdapter.UnprocessableRecordError = (function(_super1) {
+
+ __extends(UnprocessableRecordError, _super1);
+
+ UnprocessableRecordError.prototype.name = "UnprocessableRecordError";
+
+ function UnprocessableRecordError(message) {
+ UnprocessableRecordError.__super__.constructor.call(this, message || "Storage adapter could not process the record!");
+ }
+
+ return UnprocessableRecordError;
+
+ })(StorageAdapter.StorageError);
+
+ StorageAdapter.InternalStorageError = (function(_super1) {
+
+ __extends(InternalStorageError, _super1);
+
+ InternalStorageError.prototype.name = "InternalStorageError";
+
+ function InternalStorageError(message) {
+ InternalStorageError.__super__.constructor.call(this, message || "An error occured during the storage operation!");
+ }
+
+ return InternalStorageError;
+
+ })(StorageAdapter.StorageError);
+
+ StorageAdapter.NotImplementedError = (function(_super1) {
+
+ __extends(NotImplementedError, _super1);
+
+ NotImplementedError.prototype.name = "NotImplementedError";
+
+ function NotImplementedError(message) {
+ NotImplementedError.__super__.constructor.call(this, message || "This operation is not implemented by the storage adpater!");
+ }
+
+ return NotImplementedError;
+
+ })(StorageAdapter.StorageError);
+
function StorageAdapter(model) {
var constructor;
StorageAdapter.__super__.constructor.call(this, {
@@ -4891,9 +4965,10 @@
}
return _this.runAfterFilter(key, env, callback);
};
- return this.runBeforeFilter(key, env, function(env) {
+ this.runBeforeFilter(key, env, function(env) {
return this[key](env, next);
});
+ return void 0;
};
return StorageAdapter;
@@ -4914,6 +4989,20 @@
__extends(RestStorage, _super);
+ RestStorage.CommunicationError = (function(_super1) {
+
+ __extends(CommunicationError, _super1);
+
+ CommunicationError.prototype.name = 'CommunicationError';
+
+ function CommunicationError(message) {
+ CommunicationError.__super__.constructor.call(this, message || "A communication error has occurred!");
+ }
+
+ return CommunicationError;
+
+ })(RestStorage.StorageError);
+
RestStorage.JSONContentType = 'application/json';
RestStorage.PostBodyContentType = 'application/x-www-form-urlencoded';
@@ -4998,16 +5087,19 @@
return Batman.helpers.pluralize(this.storageKey(constructor.prototype));
};
- RestStorage.prototype._execWithOptions = function(object, key, options) {
+ RestStorage.prototype._execWithOptions = function(object, key, options, context) {
+ if (context == null) {
+ context = object;
+ }
if (typeof object[key] === 'function') {
- return object[key](options);
+ return object[key].call(context, options);
} else {
return object[key];
}
};
RestStorage.prototype._defaultCollectionUrl = function(model) {
- return "/" + (this.storageKey(model.prototype));
+ return "" + (this.storageKey(model.prototype));
};
RestStorage.prototype._addParams = function(url, options) {
@@ -5018,9 +5110,32 @@
return url;
};
+ RestStorage.prototype._addUrlAffixes = function(url, subject, env) {
+ var prefix, segments;
+ segments = [url, this.urlSuffix(subject, env)];
+ if (url.charAt(0) !== '/') {
+ prefix = this.urlPrefix(subject, env);
+ if (prefix.charAt(prefix.length - 1) !== '/') {
+ segments.unshift('/');
+ }
+ segments.unshift(prefix);
+ }
+ return segments.join('');
+ };
+
+ RestStorage.prototype.urlPrefix = function(object, env) {
+ return this._execWithOptions(object, 'urlPrefix', env.options) || '';
+ };
+
+ RestStorage.prototype.urlSuffix = function(object, env) {
+ return this._execWithOptions(object, 'urlSuffix', env.options) || '';
+ };
+
RestStorage.prototype.urlForRecord = function(record, env) {
- var id, url;
- if (record.url) {
+ var id, url, _ref;
+ if ((_ref = env.options) != null ? _ref.recordUrl : void 0) {
+ url = this._execWithOptions(env.options, 'recordUrl', env.options, record);
+ } else if (record.url) {
url = this._execWithOptions(record, 'url', env.options);
} else {
url = record.constructor.url ? this._execWithOptions(record.constructor, 'url', env.options) : this._defaultCollectionUrl(record.constructor);
@@ -5032,23 +5147,13 @@
}
}
}
- url = this._addParams(url, env.options);
- return this.urlPrefix(record, env) + url + this.urlSuffix(record, env);
+ return this._addUrlAffixes(this._addParams(url, env.options), record, env);
};
RestStorage.prototype.urlForCollection = function(model, env) {
- var url;
- url = model.url ? this._execWithOptions(model, 'url', env.options) : this._defaultCollectionUrl(model, env.options);
- url = this._addParams(url, env.options);
- return this.urlPrefix(model, env) + url + this.urlSuffix(model, env);
- };
-
- RestStorage.prototype.urlPrefix = function(object, env) {
- return this._execWithOptions(object, 'urlPrefix', env.options) || '';
- };
-
- RestStorage.prototype.urlSuffix = function(object, env) {
- return this._execWithOptions(object, 'urlSuffix', env.options) || '';
+ var url, _ref;
+ url = ((_ref = env.options) != null ? _ref.collectionUrl : void 0) ? this._execWithOptions(env.options, 'collectionUrl', env.options, env.options.urlContext) : model.url ? this._execWithOptions(model, 'url', env.options) : this._defaultCollectionUrl(model, env.options);
+ return this._addUrlAffixes(this._addParams(url, env.options), model, env);
};
RestStorage.prototype.request = function(env, next) {
@@ -5212,6 +5317,37 @@
_fn(key);
}
+ RestStorage.prototype.after('all', function(env, next) {
+ if (env.error) {
+ env.error = this._errorFor(env.error, env);
+ }
+ return next();
+ });
+
+ RestStorage._statusCodeErrors = {
+ '0': RestStorage.CommunicationError,
+ '403': RestStorage.NotAllowedError,
+ '404': RestStorage.NotFoundError,
+ '406': RestStorage.NotAcceptableError,
+ '422': RestStorage.UnprocessableRecordError,
+ '500': RestStorage.InternalStorageError,
+ '501': RestStorage.NotImplementedError
+ };
+
+ RestStorage.prototype._errorFor = function(error, env) {
+ var errorClass, request;
+ if (error instanceof Error || !(error.request != null)) {
+ return error;
+ }
+ if (errorClass = this.constructor._statusCodeErrors[error.request.status]) {
+ request = error.request;
+ error = new errorClass;
+ error.request = request;
+ error.env = env;
+ }
+ return error;
+ };
+
return RestStorage;
}).call(this, Batman.StorageAdapter);
@@ -5427,1126 +5563,6 @@
var __hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
- Batman.AssociationProxy = (function(_super) {
-
- __extends(AssociationProxy, _super);
-
- AssociationProxy.prototype.isProxy = true;
-
- function AssociationProxy(association, model) {
- this.association = association;
- this.model = model;
- }
-
- AssociationProxy.prototype.loaded = false;
-
- AssociationProxy.prototype.toJSON = function() {
- var target;
- target = this.get('target');
- if (target != null) {
- return this.get('target').toJSON();
- }
- };
-
- AssociationProxy.prototype.load = function(callback) {
- var _this = this;
- this.fetch(function(err, proxiedRecord) {
- if (!err) {
- _this.set('loaded', true);
- _this.set('target', proxiedRecord);
- }
- return typeof callback === "function" ? callback(err, proxiedRecord) : void 0;
- });
- return this.get('target');
- };
-
- AssociationProxy.prototype.fetch = function(callback) {
- var record;
- if ((this.get('foreignValue') || this.get('primaryValue')) == null) {
- return callback(void 0, void 0);
- }
- record = this.fetchFromLocal();
- if (record) {
- return callback(void 0, record);
- } else {
- return this.fetchFromRemote(callback);
- }
- };
-
- AssociationProxy.accessor('loaded', Batman.Property.defaultAccessor);
-
- AssociationProxy.accessor('target', {
- get: function() {
- return this.fetchFromLocal();
- },
- set: function(_, v) {
- return v;
- }
- });
-
- AssociationProxy.accessor({
- get: function(k) {
- var _ref;
- return (_ref = this.get('target')) != null ? _ref.get(k) : void 0;
- },
- set: function(k, v) {
- var _ref;
- return (_ref = this.get('target')) != null ? _ref.set(k, v) : void 0;
- }
- });
-
- return AssociationProxy;
-
- })(Batman.Object);
-
-}).call(this);
-
-(function() {
- var __hasProp = {}.hasOwnProperty,
- __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
-
- Batman.HasOneProxy = (function(_super) {
-
- __extends(HasOneProxy, _super);
-
- function HasOneProxy() {
- return HasOneProxy.__super__.constructor.apply(this, arguments);
- }
-
- HasOneProxy.accessor('primaryValue', function() {
- return this.model.get(this.association.primaryKey);
- });
-
- HasOneProxy.prototype.fetchFromLocal = function() {
- return this.association.setIndex().get(this.get('primaryValue'));
- };
-
- HasOneProxy.prototype.fetchFromRemote = function(callback) {
- var loadOptions,
- _this = this;
- loadOptions = {};
- loadOptions[this.association.foreignKey] = this.get('primaryValue');
- return this.association.getRelatedModel().load(loadOptions, function(error, loadedRecords) {
- if (error) {
- throw error;
- }
- if (!loadedRecords || loadedRecords.length <= 0) {
- return callback(new Error("Couldn't find related record!"), void 0);
- } else {
- return callback(void 0, loadedRecords[0]);
- }
- });
- };
-
- return HasOneProxy;
-
- })(Batman.AssociationProxy);
-
-}).call(this);
-
-(function() {
- var __hasProp = {}.hasOwnProperty,
- __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
-
- Batman.BelongsToProxy = (function(_super) {
-
- __extends(BelongsToProxy, _super);
-
- function BelongsToProxy() {
- return BelongsToProxy.__super__.constructor.apply(this, arguments);
- }
-
- BelongsToProxy.accessor('foreignValue', function() {
- return this.model.get(this.association.foreignKey);
- });
-
- BelongsToProxy.prototype.fetchFromLocal = function() {
- return this.association.setIndex().get(this.get('foreignValue'));
- };
-
- BelongsToProxy.prototype.fetchFromRemote = function(callback) {
- var _this = this;
- return this.association.getRelatedModel().find(this.get('foreignValue'), function(error, loadedRecord) {
- if (error) {
- throw error;
- }
- return callback(void 0, loadedRecord);
- });
- };
-
- return BelongsToProxy;
-
- })(Batman.AssociationProxy);
-
-}).call(this);
-
-(function() {
- var __hasProp = {}.hasOwnProperty,
- __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
-
- Batman.PolymorphicBelongsToProxy = (function(_super) {
-
- __extends(PolymorphicBelongsToProxy, _super);
-
- function PolymorphicBelongsToProxy() {
- return PolymorphicBelongsToProxy.__super__.constructor.apply(this, arguments);
- }
-
- PolymorphicBelongsToProxy.accessor('foreignTypeValue', function() {
- return this.model.get(this.association.foreignTypeKey);
- });
-
- PolymorphicBelongsToProxy.prototype.fetchFromLocal = function() {
- return this.association.setIndexForType(this.get('foreignTypeValue')).get(this.get('foreignValue'));
- };
-
- PolymorphicBelongsToProxy.prototype.fetchFromRemote = function(callback) {
- var _this = this;
- return this.association.getRelatedModelForType(this.get('foreignTypeValue')).find(this.get('foreignValue'), function(error, loadedRecord) {
- if (error) {
- throw error;
- }
- return callback(void 0, loadedRecord);
- });
- };
-
- return PolymorphicBelongsToProxy;
-
- })(Batman.BelongsToProxy);
-
-}).call(this);
-
-(function() {
- var __hasProp = {}.hasOwnProperty,
- __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
- __slice = [].slice;
-
- Batman.StateMachine = (function(_super) {
-
- __extends(StateMachine, _super);
-
- StateMachine.InvalidTransitionError = function(message) {
- this.message = message != null ? message : "";
- };
-
- StateMachine.InvalidTransitionError.prototype = new Error;
-
- StateMachine.transitions = function(table) {
- var definePredicate, fromState, k, object, predicateKeys, toState, transitions, v, _fn, _ref,
- _this = this;
- for (k in table) {
- v = table[k];
- if (!(v.from && v.to)) {
- continue;
- }
- object = {};
- if (v.from.forEach) {
- v.from.forEach(function(fromKey) {
- return object[fromKey] = v.to;
- });
- } else {
- object[v.from] = v.to;
- }
- table[k] = object;
- }
- this.prototype.transitionTable = Batman.extend({}, this.prototype.transitionTable, table);
- predicateKeys = [];
- definePredicate = function(state) {
- var key;
- key = "is" + (Batman.helpers.capitalize(state));
- if (_this.prototype[key] != null) {
- return;
- }
- predicateKeys.push(key);
- return _this.prototype[key] = function() {
- return this.get('state') === state;
- };
- };
- _ref = this.prototype.transitionTable;
- _fn = function(k) {
- return _this.prototype[k] = function() {
- return this.startTransition(k);
- };
- };
- for (k in _ref) {
- transitions = _ref[k];
- if (!(!this.prototype[k])) {
- continue;
- }
- _fn(k);
- for (fromState in transitions) {
- toState = transitions[fromState];
- definePredicate(fromState);
- definePredicate(toState);
- }
- }
- if (predicateKeys.length) {
- this.accessor.apply(this, __slice.call(predicateKeys).concat([function(key) {
- return this[key]();
- }]));
- }
- return this;
- };
-
- function StateMachine(startState) {
- this.nextEvents = [];
- this.set('_state', startState);
- }
-
- StateMachine.accessor('state', function() {
- return this.get('_state');
- });
-
- StateMachine.prototype.isTransitioning = false;
-
- StateMachine.prototype.transitionTable = {};
-
- StateMachine.prototype.onTransition = function(from, into, callback) {
- return this.on("" + from + "->" + into, callback);
- };
-
- StateMachine.prototype.onEnter = function(into, callback) {
- return this.on("enter " + into, callback);
- };
-
- StateMachine.prototype.onExit = function(from, callback) {
- return this.on("exit " + from, callback);
- };
-
- StateMachine.prototype.startTransition = Batman.Property.wrapTrackingPrevention(function(event) {
- var nextState, previousState;
- if (this.isTransitioning) {
- this.nextEvents.push(event);
- return;
- }
- previousState = this.get('state');
- nextState = this.nextStateForEvent(event);
- if (!nextState) {
- return false;
- }
- this.isTransitioning = true;
- this.fire("exit " + previousState);
- this.set('_state', nextState);
- this.fire("" + previousState + "->" + nextState);
- this.fire("enter " + nextState);
- this.fire(event);
- this.isTransitioning = false;
- if (this.nextEvents.length > 0) {
- this.startTransition(this.nextEvents.shift());
- }
- return true;
- });
-
- StateMachine.prototype.canStartTransition = function(event, fromState) {
- if (fromState == null) {
- fromState = this.get('state');
- }
- return !!this.nextStateForEvent(event, fromState);
- };
-
- StateMachine.prototype.nextStateForEvent = function(event, fromState) {
- var _ref;
- if (fromState == null) {
- fromState = this.get('state');
- }
- return (_ref = this.transitionTable[event]) != null ? _ref[fromState] : void 0;
- };
-
- return StateMachine;
-
- })(Batman.Object);
-
- Batman.DelegatingStateMachine = (function(_super) {
-
- __extends(DelegatingStateMachine, _super);
-
- function DelegatingStateMachine(startState, base) {
- this.base = base;
- DelegatingStateMachine.__super__.constructor.call(this, startState);
- }
-
- DelegatingStateMachine.prototype.fire = function() {
- var result, _ref;
- result = DelegatingStateMachine.__super__.fire.apply(this, arguments);
- (_ref = this.base).fire.apply(_ref, arguments);
- return result;
- };
-
- return DelegatingStateMachine;
-
- })(Batman.StateMachine);
-
-}).call(this);
-
-(function() {
- var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
- __hasProp = {}.hasOwnProperty,
- __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
- __slice = [].slice;
-
- Batman.Model = (function(_super) {
- var functionName, _i, _j, _len, _len1, _ref, _ref1;
-
- __extends(Model, _super);
-
- Model.primaryKey = 'id';
-
- Model.storageKey = null;
-
- Model.persist = function(mechanism, options) {
- Batman.initializeObject(this.prototype);
- mechanism = mechanism.isStorageAdapter ? mechanism : new mechanism(this);
- if (options) {
- Batman.mixin(mechanism, options);
- }
- this.prototype._batman.storage = mechanism;
- return mechanism;
- };
-
- Model.storageAdapter = function() {
- Batman.initializeObject(this.prototype);
- return this.prototype._batman.storage;
- };
-
- Model.encode = function() {
- var encoder, encoderForKey, encoderOrLastKey, key, keys, _base, _i, _j, _len;
- keys = 2 <= arguments.length ? __slice.call(arguments, 0, _i = arguments.length - 1) : (_i = 0, []), encoderOrLastKey = arguments[_i++];
- Batman.initializeObject(this.prototype);
- (_base = this.prototype._batman).encoders || (_base.encoders = new Batman.SimpleHash);
- encoder = {};
- switch (Batman.typeOf(encoderOrLastKey)) {
- case 'String':
- keys.push(encoderOrLastKey);
- break;
- case 'Function':
- encoder.encode = encoderOrLastKey;
- break;
- default:
- encoder = encoderOrLastKey;
- }
- for (_j = 0, _len = keys.length; _j < _len; _j++) {
- key = keys[_j];
- encoderForKey = Batman.extend({
- as: key
- }, this.defaultEncoder, encoder);
- this.prototype._batman.encoders.set(key, encoderForKey);
- }
- };
-
- Model.defaultEncoder = {
- encode: function(x) {
- return x;
- },
- decode: function(x) {
- return x;
- }
- };
-
- Model.observeAndFire('primaryKey', function(newPrimaryKey, oldPrimaryKey) {
- this.encode(oldPrimaryKey, {
- encode: false,
- decode: false
- });
- return this.encode(newPrimaryKey, {
- encode: false,
- decode: this.defaultEncoder.decode
- });
- });
-
- Model.validate = function() {
- var keys, match, matches, options, optionsOrFunction, validator, validators, _base, _i, _j, _k, _len, _len1, _ref, _results;
- keys = 2 <= arguments.length ? __slice.call(arguments, 0, _i = arguments.length - 1) : (_i = 0, []), optionsOrFunction = arguments[_i++];
- Batman.initializeObject(this.prototype);
- validators = (_base = this.prototype._batman).validators || (_base.validators = []);
- if (typeof optionsOrFunction === 'function') {
- return validators.push({
- keys: keys,
- callback: optionsOrFunction
- });
- } else {
- options = optionsOrFunction;
- _ref = Batman.Validators;
- _results = [];
- for (_j = 0, _len = _ref.length; _j < _len; _j++) {
- validator = _ref[_j];
- if ((matches = validator.matches(options))) {
- for (_k = 0, _len1 = matches.length; _k < _len1; _k++) {
- match = matches[_k];
- delete options[match];
- }
- _results.push(validators.push({
- keys: keys,
- validator: new validator(matches)
- }));
- } else {
- _results.push(void 0);
- }
- }
- return _results;
- }
- };
-
- Model.LifecycleStateMachine = (function(_super1) {
-
- __extends(LifecycleStateMachine, _super1);
-
- function LifecycleStateMachine() {
- return LifecycleStateMachine.__super__.constructor.apply(this, arguments);
- }
-
- LifecycleStateMachine.transitions({
- load: {
- empty: 'loading',
- loaded: 'loading',
- loading: 'loading'
- },
- loaded: {
- loading: 'loaded'
- },
- error: {
- loading: 'error'
- }
- });
-
- return LifecycleStateMachine;
-
- })(Batman.DelegatingStateMachine);
-
- Model.classAccessor('lifecycle', function() {
- var _base;
- this._batman.check(this);
- return (_base = this._batman).lifecycle || (_base.lifecycle = new this.LifecycleStateMachine('empty', this));
- });
-
- Model.classAccessor('resourceName', {
- get: function() {
- if (this.resourceName != null) {
- return this.resourceName;
- } else {
- if (Batman.config.minificationErrors) {
- Batman.developer.error("Please define " + (Batman.functionName(this)) + ".resourceName in order for your model to be minification safe.");
- }
- return Batman.helpers.underscore(Batman.functionName(this));
- }
- }
- });
-
- Model.classAccessor('all', {
- get: function() {
- this._batman.check(this);
- if (this.prototype.hasStorage() && !this._batman.allLoadTriggered) {
- this.load();
- this._batman.allLoadTriggered = true;
- }
- return this.get('loaded');
- },
- set: function(k, v) {
- return this.set('loaded', v);
- }
- });
-
- Model.classAccessor('loaded', {
- get: function() {
- return this._loaded || (this._loaded = new Batman.Set);
- },
- set: function(k, v) {
- return this._loaded = v;
- }
- });
-
- Model.classAccessor('first', function() {
- return this.get('all').toArray()[0];
- });
-
- Model.classAccessor('last', function() {
- var x;
- x = this.get('all').toArray();
- return x[x.length - 1];
- });
-
- Model.clear = function() {
- var result, _ref;
- Batman.initializeObject(this);
- result = this.get('loaded').clear();
- if ((_ref = this._batman.get('associations')) != null) {
- _ref.reset();
- }
- return result;
- };
-
- Model.find = function(id, callback) {
- var record;
- Batman.developer.assert(callback, "Must call find with a callback!");
- record = new this();
- record._withoutDirtyTracking(function() {
- return this.set('id', id);
- });
- record.load(callback);
- return record;
- };
-
- Model.load = function(options, callback) {
- var lifecycle, _ref,
- _this = this;
- if ((_ref = typeof options) === 'function' || _ref === 'undefined') {
- callback = options;
- options = {};
- }
- lifecycle = this.get('lifecycle');
- if (lifecycle.load()) {
- return this._doStorageOperation('readAll', {
- data: options
- }, function(err, records, env) {
- var mappedRecords, record;
- if (err != null) {
- lifecycle.error();
- return typeof callback === "function" ? callback(err, []) : void 0;
- } else {
- mappedRecords = (function() {
- var _i, _len, _results;
- _results = [];
- for (_i = 0, _len = records.length; _i < _len; _i++) {
- record = records[_i];
- _results.push(this._mapIdentity(record));
- }
- return _results;
- }).call(_this);
- lifecycle.loaded();
- return typeof callback === "function" ? callback(err, mappedRecords, env) : void 0;
- }
- });
- } else {
- return callback(new Batman.StateMachine.InvalidTransitionError("Can't load while in state " + (lifecycle.get('state'))));
- }
- };
-
- Model.create = function(attrs, callback) {
- var obj, _ref;
- if (!callback) {
- _ref = [{}, attrs], attrs = _ref[0], callback = _ref[1];
- }
- obj = new this(attrs);
- obj.save(callback);
- return obj;
- };
-
- Model.findOrCreate = function(attrs, callback) {
- var foundRecord, record;
- record = new this(attrs);
- if (record.isNew()) {
- record.save(callback);
- } else {
- foundRecord = this._mapIdentity(record);
- callback(void 0, foundRecord);
- }
- return record;
- };
-
- Model._mapIdentity = function(record) {
- var existing, id, _ref;
- if (typeof (id = record.get('id')) === 'undefined' || id === '') {
- return record;
- } else {
- existing = (_ref = this.get("loaded.indexedBy.id").get(id)) != null ? _ref.toArray()[0] : void 0;
- if (existing) {
- existing._withoutDirtyTracking(function() {
- var _ref1;
- return this.updateAttributes(((_ref1 = record.get('attributes')) != null ? _ref1.toObject() : void 0) || {});
- });
- return existing;
- } else {
- this.get('loaded').add(record);
- return record;
- }
- }
- };
-
- Model._doStorageOperation = function(operation, options, callback) {
- var adapter;
- Batman.developer.assert(this.prototype.hasStorage(), "Can't " + operation + " model " + (Batman.functionName(this.constructor)) + " without any storage adapters!");
- adapter = this.prototype._batman.get('storage');
- return adapter.perform(operation, this, options, callback);
- };
-
- _ref = ['find', 'load', 'create'];
- for (_i = 0, _len = _ref.length; _i < _len; _i++) {
- functionName = _ref[_i];
- Model[functionName] = Batman.Property.wrapTrackingPrevention(Model[functionName]);
- }
-
- Model.InstanceLifecycleStateMachine = (function(_super1) {
-
- __extends(InstanceLifecycleStateMachine, _super1);
-
- function InstanceLifecycleStateMachine() {
- return InstanceLifecycleStateMachine.__super__.constructor.apply(this, arguments);
- }
-
- InstanceLifecycleStateMachine.transitions({
- load: {
- from: ['dirty', 'clean'],
- to: 'loading'
- },
- create: {
- from: ['dirty', 'clean'],
- to: 'creating'
- },
- save: {
- from: ['dirty', 'clean'],
- to: 'saving'
- },
- destroy: {
- from: ['dirty', 'clean'],
- to: 'destroying'
- },
- failedValidation: {
- from: ['saving', 'creating'],
- to: 'dirty'
- },
- loaded: {
- loading: 'clean'
- },
- created: {
- creating: 'clean'
- },
- saved: {
- saving: 'clean'
- },
- destroyed: {
- destroying: 'destroyed'
- },
- set: {
- from: ['dirty', 'clean'],
- to: 'dirty'
- },
- error: {
- from: ['saving', 'creating', 'loading', 'destroying'],
- to: 'error'
- }
- });
-
- return InstanceLifecycleStateMachine;
-
- })(Batman.DelegatingStateMachine);
-
- function Model(idOrAttributes) {
- if (idOrAttributes == null) {
- idOrAttributes = {};
- }
- this.destroy = __bind(this.destroy, this);
-
- this.save = __bind(this.save, this);
-
- this.load = __bind(this.load, this);
-
- Batman.developer.assert(this instanceof Batman.Object, "constructors must be called with new");
- if (Batman.typeOf(idOrAttributes) === 'Object') {
- Model.__super__.constructor.call(this, idOrAttributes);
- } else {
- Model.__super__.constructor.call(this);
- this.set('id', idOrAttributes);
- }
- }
-
- Model.accessor('lifecycle', function() {
- return this.lifecycle || (this.lifecycle = new Batman.Model.InstanceLifecycleStateMachine('clean', this));
- });
-
- Model.accessor('attributes', function() {
- return this.attributes || (this.attributes = new Batman.Hash);
- });
-
- Model.accessor('dirtyKeys', function() {
- return this.dirtyKeys || (this.dirtyKeys = new Batman.Hash);
- });
-
- Model.accessor('_dirtiedKeys', function() {
- return this._dirtiedKeys || (this._dirtiedKeys = new Batman.SimpleSet);
- });
-
- Model.accessor('errors', function() {
- return this.errors || (this.errors = new Batman.ErrorsSet);
- });
-
- Model.accessor('isNew', function() {
- return this.isNew();
- });
-
- Model.accessor(Model.defaultAccessor = {
- get: function(k) {
- return Batman.getPath(this, ['attributes', k]);
- },
- set: function(k, v) {
- if (this._willSet(k)) {
- return this.get('attributes').set(k, v);
- } else {
- return this.get(k);
- }
- },
- unset: function(k) {
- return this.get('attributes').unset(k);
- }
- });
-
- Model.wrapAccessor('id', function(core) {
- return {
- get: function() {
- var primaryKey;
- primaryKey = this.constructor.primaryKey;
- if (primaryKey === 'id') {
- return core.get.apply(this, arguments);
- } else {
- return this.get(primaryKey);
- }
- },
- set: function(key, value) {
- var parsedValue, primaryKey;
- if ((typeof value === "string") && (value.match(/[^0-9]/) === null) && (("" + (parsedValue = parseInt(value, 10))) === value)) {
- value = parsedValue;
- }
- primaryKey = this.constructor.primaryKey;
- if (primaryKey === 'id') {
- this._willSet(key);
- return core.set.apply(this, arguments);
- } else {
- return this.set(primaryKey, value);
- }
- }
- };
- });
-
- Model.prototype.isNew = function() {
- return typeof this.get('id') === 'undefined';
- };
-
- Model.prototype.updateAttributes = function(attrs) {
- this.mixin(attrs);
- return this;
- };
-
- Model.prototype.toString = function() {
- return "" + (this.constructor.get('resourceName')) + ": " + (this.get('id'));
- };
-
- Model.prototype.toParam = function() {
- return this.get('id');
- };
-
- Model.prototype.toJSON = function() {
- var encoders, obj,
- _this = this;
- obj = {};
- encoders = this._batman.get('encoders');
- if (!(!encoders || encoders.isEmpty())) {
- encoders.forEach(function(key, encoder) {
- var encodedVal, val;
- if (encoder.encode) {
- val = _this.get(key);
- if (typeof val !== 'undefined') {
- encodedVal = encoder.encode(val, key, obj, _this);
- if (typeof encodedVal !== 'undefined') {
- return obj[encoder.as] = encodedVal;
- }
- }
- }
- });
- }
- return obj;
- };
-
- Model.prototype.fromJSON = function(data) {
- var encoders, key, obj, value,
- _this = this;
- obj = {};
- encoders = this._batman.get('encoders');
- if (!encoders || encoders.isEmpty() || !encoders.some(function(key, encoder) {
- return encoder.decode != null;
- })) {
- for (key in data) {
- value = data[key];
- obj[key] = value;
- }
- } else {
- encoders.forEach(function(key, encoder) {
- if (encoder.decode && typeof data[encoder.as] !== 'undefined') {
- return obj[key] = encoder.decode(data[encoder.as], encoder.as, data, obj, _this);
- }
- });
- }
- if (this.constructor.primaryKey !== 'id') {
- obj.id = data[this.constructor.primaryKey];
- }
- Batman.developer["do"](function() {
- if ((!encoders) || encoders.length <= 1) {
- return Batman.developer.warn("Warning: Model " + (Batman.functionName(_this.constructor)) + " has suspiciously few decoders!");
- }
- });
- return this.mixin(obj);
- };
-
- Model.prototype.hasStorage = function() {
- return this._batman.get('storage') != null;
- };
-
- Model.prototype.load = function(options, callback) {
- var callbackQueue, hasOptions, _ref1, _ref2,
- _this = this;
- if (!callback) {
- _ref1 = [{}, options], options = _ref1[0], callback = _ref1[1];
- }
- hasOptions = Object.keys(options).length !== 0;
- if ((_ref2 = this.get('lifecycle.state')) === 'destroying' || _ref2 === 'destroyed') {
- if (typeof callback === "function") {
- callback(new Error("Can't load a destroyed record!"));
- }
- return;
- }
- if (this.get('lifecycle').load()) {
- callbackQueue = [];
- if (callback != null) {
- callbackQueue.push(callback);
- }
- if (!hasOptions) {
- this._currentLoad = callbackQueue;
- }
- return this._doStorageOperation('read', {
- data: options
- }, function(err, record, env) {
- var _j, _len1;
- if (!err) {
- _this.get('lifecycle').loaded();
- record = _this.constructor._mapIdentity(record);
- } else {
- _this.get('lifecycle').error();
- }
- if (!hasOptions) {
- _this._currentLoad = null;
- }
- for (_j = 0, _len1 = callbackQueue.length; _j < _len1; _j++) {
- callback = callbackQueue[_j];
- callback(err, record, env);
- }
- });
- } else {
- if (this.get('lifecycle.state') === 'loading' && !hasOptions) {
- if (callback != null) {
- return this._currentLoad.push(callback);
- }
- } else {
- return typeof callback === "function" ? callback(new Batman.StateMachine.InvalidTransitionError("Can't load while in state " + (this.get('lifecycle.state')))) : void 0;
- }
- }
- };
-
- Model.prototype.save = function(options, callback) {
- var endState, isNew, startState, storageOperation, _ref1, _ref2, _ref3,
- _this = this;
- if (!callback) {
- _ref1 = [{}, options], options = _ref1[0], callback = _ref1[1];
- }
- if ((_ref2 = this.get('lifecycle').get('state')) === 'destroying' || _ref2 === 'destroyed') {
- if (typeof callback === "function") {
- callback(new Error("Can't save a destroyed record!"));
- }
- return;
- }
- isNew = this.isNew();
- _ref3 = isNew ? ['create', 'create', 'created'] : ['save', 'update', 'saved'], startState = _ref3[0], storageOperation = _ref3[1], endState = _ref3[2];
- return this.validate(function(error, errors) {
- var associations, creating;
- if (error || errors.length) {
- _this.get('lifecycle').failedValidation();
- if (typeof callback === "function") {
- callback(error || errors, _this);
- }
- return;
- }
- creating = _this.isNew();
- if (_this.get('lifecycle').startTransition(startState)) {
- associations = _this.constructor._batman.get('associations');
- _this._withoutDirtyTracking(function() {
- var _ref4,
- _this = this;
- return associations != null ? (_ref4 = associations.getByType('belongsTo')) != null ? _ref4.forEach(function(association, label) {
- return association.apply(_this);
- }) : void 0 : void 0;
- });
- return _this._doStorageOperation(storageOperation, {
- data: options
- }, function(err, record, env) {
- if (!err) {
- _this.get('dirtyKeys').clear();
- _this.get('_dirtiedKeys').clear();
- if (associations) {
- record._withoutDirtyTracking(function() {
- var _ref4, _ref5;
- if ((_ref4 = associations.getByType('hasOne')) != null) {
- _ref4.forEach(function(association, label) {
- return association.apply(err, record);
- });
- }
- return (_ref5 = associations.getByType('hasMany')) != null ? _ref5.forEach(function(association, label) {
- return association.apply(err, record);
- }) : void 0;
- });
- }
- record = _this.constructor._mapIdentity(record);
- _this.get('lifecycle').startTransition(endState);
- } else {
- if (err instanceof Batman.ErrorsSet) {
- _this.get('lifecycle').failedValidation();
- } else {
- _this.get('lifecycle').error();
- }
- }
- return typeof callback === "function" ? callback(err, record || _this, env) : void 0;
- });
- } else {
- return typeof callback === "function" ? callback(new Batman.StateMachine.InvalidTransitionError("Can't save while in state " + (_this.get('lifecycle.state')))) : void 0;
- }
- });
- };
-
- Model.prototype.destroy = function(options, callback) {
- var _ref1,
- _this = this;
- if (!callback) {
- _ref1 = [{}, options], options = _ref1[0], callback = _ref1[1];
- }
- if (this.get('lifecycle').destroy()) {
- return this._doStorageOperation('destroy', {
- data: options
- }, function(err, record, env) {
- if (!err) {
- _this.constructor.get('loaded').remove(_this);
- _this.get('lifecycle').destroyed();
- } else {
- _this.get('lifecycle').error();
- }
- return typeof callback === "function" ? callback(err, record, env) : void 0;
- });
- } else {
- return typeof callback === "function" ? callback(new Batman.StateMachine.InvalidTransitionError("Can't destroy while in state " + (this.get('lifecycle.state')))) : void 0;
- }
- };
-
- Model.prototype.validate = function(callback) {
- var args, count, errors, finishedValidation, key, validator, validators, _j, _k, _len1, _len2, _ref1;
- errors = this.get('errors');
- errors.clear();
- validators = this._batman.get('validators') || [];
- if (!validators || validators.length === 0) {
- if (typeof callback === "function") {
- callback(void 0, errors);
- }
- return true;
- }
- count = validators.reduce((function(acc, validator) {
- return acc + validator.keys.length;
- }), 0);
- finishedValidation = function() {
- if (--count === 0) {
- return typeof callback === "function" ? callback(void 0, errors) : void 0;
- }
- };
- for (_j = 0, _len1 = validators.length; _j < _len1; _j++) {
- validator = validators[_j];
- _ref1 = validator.keys;
- for (_k = 0, _len2 = _ref1.length; _k < _len2; _k++) {
- key = _ref1[_k];
- args = [errors, this, key, finishedValidation];
- try {
- if (validator.validator) {
- validator.validator.validateEach.apply(validator.validator, args);
- } else {
- validator.callback.apply(validator, args);
- }
- } catch (e) {
- if (typeof callback === "function") {
- callback(e, errors);
- }
- }
- }
- }
- };
-
- Model.prototype.associationProxy = function(association) {
- var proxies, _base, _name;
- Batman.initializeObject(this);
- proxies = (_base = this._batman).associationProxies || (_base.associationProxies = {});
- proxies[_name = association.label] || (proxies[_name] = new association.proxyClass(association, this));
- return proxies[association.label];
- };
-
- Model.prototype._willSet = function(key) {
- if (this._pauseDirtyTracking) {
- return true;
- }
- if (this.get('lifecycle').startTransition('set')) {
- if (!this.get('_dirtiedKeys').has(key)) {
- this.set("dirtyKeys." + key, this.get(key));
- this.get('_dirtiedKeys').add(key);
- }
- return true;
- } else {
- return false;
- }
- };
-
- Model.prototype._doStorageOperation = function(operation, options, callback) {
- var adapter,
- _this = this;
- Batman.developer.assert(this.hasStorage(), "Can't " + operation + " model " + (Batman.functionName(this.constructor)) + " without any storage adapters!");
- adapter = this._batman.get('storage');
- return adapter.perform(operation, this, options, function() {
- return callback.apply(null, arguments);
- });
- };
-
- Model.prototype._withoutDirtyTracking = function(block) {
- var result;
- this._pauseDirtyTracking = true;
- result = block.call(this);
- this._pauseDirtyTracking = false;
- return result;
- };
-
- _ref1 = ['load', 'save', 'validate', 'destroy'];
- for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
- functionName = _ref1[_j];
- Model.prototype[functionName] = Batman.Property.wrapTrackingPrevention(Model.prototype[functionName]);
- }
-
- return Model;
-
- }).call(this, Batman.Object);
-
-}).call(this);
-
-(function() {
- var k, _fn, _i, _len, _ref,
- _this = this;
-
- _ref = Batman.AssociationCurator.availableAssociations;
- _fn = function(k) {
- return Batman.Model[k] = function(label, scope) {
- var collection, _base;
- Batman.initializeObject(this);
- collection = (_base = this._batman).associations || (_base.associations = new Batman.AssociationCurator(this));
- return collection.add(new Batman["" + (Batman.helpers.capitalize(k)) + "Association"](this, label, scope));
- };
- };
- for (_i = 0, _len = _ref.length; _i < _len; _i++) {
- k = _ref[_i];
- _fn(k);
- }
-
-}).call(this);
-
-(function() {
- var __hasProp = {}.hasOwnProperty,
- __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
-
Batman.ParamsReplacer = (function(_super) {
__extends(ParamsReplacer, _super);
@@ -6863,7 +5879,7 @@
};
Dispatcher.prototype.dispatch = function(params) {
- var inferredParams, path, route, _ref;
+ var error, inferredParams, path, route, _ref, _ref1;
inferredParams = this.constructor.paramsFromArgument(params);
route = this.routeForParams(inferredParams);
if (route) {
@@ -6878,6 +5894,19 @@
} else {
this.get('app.currentParams').clear();
}
+ error = {
+ type: '404',
+ isPrevented: false,
+ preventDefault: function() {
+ return this.isPrevented = true;
+ }
+ };
+ if ((_ref1 = Batman.currentApp) != null) {
+ _ref1.fire('error', error);
+ }
+ if (error.isPrevented) {
+ return params;
+ }
if (params !== '/404') {
return Batman.redirect('/404');
}
@@ -6924,6 +5953,7 @@
}
pattern = templatePath.replace(regexps.escapeRegExp, '\\$&');
regexp = RegExp("^" + (pattern.replace(regexps.openOptParam, '(?:').replace(regexps.closeOptParam, ')?').replace(regexps.namedParam, '([^\/]+)').replace(regexps.splatParam, '(.*?)')) + regexps.queryParam + "$");
+ regexps.namedOrSplat.lastIndex = 0;
namedArguments = ((function() {
var _results;
_results = [];
@@ -7401,6 +6431,7 @@
var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
__hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
+ __slice = [].slice,
__indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
Batman.Controller = (function(_super) {
@@ -7455,16 +6486,16 @@
var filters, options, _base;
Batman.initializeObject(this);
options = _optionsFromFilterArguments.apply(null, arguments);
- filters = (_base = this._batman).beforeFilters || (_base.beforeFilters = new Batman.SimpleHash);
- return filters.set(options.block, options);
+ filters = (_base = this._batman).beforeFilters || (_base.beforeFilters = []);
+ return filters.push(options);
};
Controller.afterFilter = function() {
var filters, options, _base;
Batman.initializeObject(this);
options = _optionsFromFilterArguments.apply(null, arguments);
- filters = (_base = this._batman).afterFilters || (_base.afterFilters = new Batman.SimpleHash);
- return filters.set(options.block, options);
+ filters = (_base = this._batman).afterFilters || (_base.afterFilters = []);
+ return filters.push(options);
};
Controller.afterFilter(function(params) {
@@ -7473,8 +6504,71 @@
}
});
+ Controller.catchError = function() {
+ var currentHandlers, error, errors, handlers, options, _base, _i, _j, _len, _results;
+ errors = 2 <= arguments.length ? __slice.call(arguments, 0, _i = arguments.length - 1) : (_i = 0, []), options = arguments[_i++];
+ Batman.initializeObject(this);
+ (_base = this._batman).errorHandlers || (_base.errorHandlers = new Batman.SimpleHash);
+ handlers = Batman.typeOf(options["with"]) === 'Array' ? options["with"] : [options["with"]];
+ _results = [];
+ for (_j = 0, _len = errors.length; _j < _len; _j++) {
+ error = errors[_j];
+ currentHandlers = this._batman.errorHandlers.get(error) || [];
+ _results.push(this._batman.errorHandlers.set(error, currentHandlers.concat(handlers)));
+ }
+ return _results;
+ };
+
+ Controller.prototype.errorHandler = function(callback) {
+ var errorFrame, _ref,
+ _this = this;
+ errorFrame = (_ref = this._actionFrames) != null ? _ref[this._actionFrames.length - 1] : void 0;
+ return function(err, result, env) {
+ if (err) {
+ if (errorFrame != null ? errorFrame.error : void 0) {
+ return;
+ }
+ if (errorFrame != null) {
+ errorFrame.error = err;
+ }
+ if (!_this.handleError(err)) {
+ throw err;
+ }
+ } else {
+ return typeof callback === "function" ? callback(result, env) : void 0;
+ }
+ };
+ };
+
+ Controller.prototype.handleError = function(error) {
+ var handled, _ref,
+ _this = this;
+ handled = false;
+ if ((_ref = this.constructor._batman.getAll('errorHandlers')) != null) {
+ _ref.forEach(function(hash) {
+ return hash.forEach(function(key, value) {
+ var handler, _i, _len, _results;
+ if (error instanceof key) {
+ handled = true;
+ _results = [];
+ for (_i = 0, _len = value.length; _i < _len; _i++) {
+ handler = value[_i];
+ _results.push(handler.call(_this, error));
+ }
+ return _results;
+ }
+ });
+ });
+ }
+ return handled;
+ };
+
function Controller() {
this.redirect = __bind(this.redirect, this);
+
+ this.handleError = __bind(this.handleError, this);
+
+ this.errorHandler = __bind(this.errorHandler, this);
Controller.__super__.constructor.apply(this, arguments);
this._resetActionFrames();
}
@@ -7519,7 +6613,9 @@
action: action
}, function() {
var _ref;
- _this._runFilters(action, params, 'afterFilters');
+ if (!_this._afterFilterRedirect) {
+ _this._runFilters(action, params, 'afterFilters');
+ }
_this._resetActionFrames();
return (_ref = Batman.navigator) != null ? _ref.redirect = oldRedirect : void 0;
});
@@ -7532,7 +6628,9 @@
_ref1.redirect = this.redirect;
}
this._runFilters(action, params, 'beforeFilters');
- result = this[action](params);
+ if (!this._afterFilterRedirect) {
+ result = this[action](params);
+ }
if (!frame.operationOccurred) {
this.render();
}
@@ -7623,24 +6721,28 @@
};
Controller.prototype._runFilters = function(action, params, filters) {
- var _ref,
- _this = this;
+ var block, options, _i, _len, _ref;
if (filters = (_ref = this.constructor._batman) != null ? _ref.get(filters) : void 0) {
- return filters.forEach(function(_, options) {
- var block;
+ for (_i = 0, _len = filters.length; _i < _len; _i++) {
+ options = filters[_i];
if (options.only && __indexOf.call(options.only, action) < 0) {
- return;
+ continue;
}
if (options.except && __indexOf.call(options.except, action) >= 0) {
+ continue;
+ }
+ if (this._afterFilterRedirect) {
return;
}
block = options.block;
if (typeof block === 'function') {
- return block.call(_this, params);
+ block.call(this, params);
} else {
- return typeof _this[block] === "function" ? _this[block](params) : void 0;
+ if (typeof this[block] === "function") {
+ this[block](params);
+ }
}
- });
+ }
}
};
@@ -7824,6 +6926,8 @@
return result;
};
+ Batman.Set._applySetAccessors(SetProxy);
+
_ref = ['add', 'remove', 'find', 'clear', 'has', 'merge', 'toArray', 'isEmpty', 'indexedBy', 'indexedByUnique', 'sortedBy'];
_fn = function(k) {
return SetProxy.prototype[k] = function() {
@@ -7836,8 +6940,6 @@
_fn(k);
}
- Batman.Set._applySetAccessors(SetProxy);
-
SetProxy.accessor('length', {
get: function() {
this.registerAsMutableSource();
@@ -8083,8 +7185,1177 @@
}).call(this);
(function() {
+ var __hasProp = {}.hasOwnProperty,
+ __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
+ __slice = [].slice;
- Batman.mixins = new Batman.Object;
+ Batman.StateMachine = (function(_super) {
+
+ __extends(StateMachine, _super);
+
+ StateMachine.InvalidTransitionError = function(message) {
+ this.message = message != null ? message : "";
+ };
+
+ StateMachine.InvalidTransitionError.prototype = new Error;
+
+ StateMachine.transitions = function(table) {
+ var definePredicate, fromState, k, object, predicateKeys, toState, transitions, v, _fn, _ref,
+ _this = this;
+ for (k in table) {
+ v = table[k];
+ if (!(v.from && v.to)) {
+ continue;
+ }
+ object = {};
+ if (v.from.forEach) {
+ v.from.forEach(function(fromKey) {
+ return object[fromKey] = v.to;
+ });
+ } else {
+ object[v.from] = v.to;
+ }
+ table[k] = object;
+ }
+ this.prototype.transitionTable = Batman.extend({}, this.prototype.transitionTable, table);
+ predicateKeys = [];
+ definePredicate = function(state) {
+ var key;
+ key = "is" + (Batman.helpers.capitalize(state));
+ if (_this.prototype[key] != null) {
+ return;
+ }
+ predicateKeys.push(key);
+ return _this.prototype[key] = function() {
+ return this.get('state') === state;
+ };
+ };
+ _ref = this.prototype.transitionTable;
+ _fn = function(k) {
+ return _this.prototype[k] = function() {
+ return this.startTransition(k);
+ };
+ };
+ for (k in _ref) {
+ transitions = _ref[k];
+ if (!(!this.prototype[k])) {
+ continue;
+ }
+ _fn(k);
+ for (fromState in transitions) {
+ toState = transitions[fromState];
+ definePredicate(fromState);
+ definePredicate(toState);
+ }
+ }
+ if (predicateKeys.length) {
+ this.accessor.apply(this, __slice.call(predicateKeys).concat([function(key) {
+ return this[key]();
+ }]));
+ }
+ return this;
+ };
+
+ function StateMachine(startState) {
+ this.nextEvents = [];
+ this.set('_state', startState);
+ }
+
+ StateMachine.accessor('state', function() {
+ return this.get('_state');
+ });
+
+ StateMachine.prototype.isTransitioning = false;
+
+ StateMachine.prototype.transitionTable = {};
+
+ StateMachine.prototype.onTransition = function(from, into, callback) {
+ return this.on("" + from + "->" + into, callback);
+ };
+
+ StateMachine.prototype.onEnter = function(into, callback) {
+ return this.on("enter " + into, callback);
+ };
+
+ StateMachine.prototype.onExit = function(from, callback) {
+ return this.on("exit " + from, callback);
+ };
+
+ StateMachine.prototype.startTransition = Batman.Property.wrapTrackingPrevention(function(event) {
+ var nextState, previousState;
+ if (this.isTransitioning) {
+ this.nextEvents.push(event);
+ return;
+ }
+ previousState = this.get('state');
+ nextState = this.nextStateForEvent(event);
+ if (!nextState) {
+ return false;
+ }
+ this.isTransitioning = true;
+ this.fire("exit " + previousState);
+ this.set('_state', nextState);
+ this.fire("" + previousState + "->" + nextState);
+ this.fire("enter " + nextState);
+ this.fire(event);
+ this.isTransitioning = false;
+ if (this.nextEvents.length > 0) {
+ this.startTransition(this.nextEvents.shift());
+ }
+ return true;
+ });
+
+ StateMachine.prototype.canStartTransition = function(event, fromState) {
+ if (fromState == null) {
+ fromState = this.get('state');
+ }
+ return !!this.nextStateForEvent(event, fromState);
+ };
+
+ StateMachine.prototype.nextStateForEvent = function(event, fromState) {
+ var _ref;
+ if (fromState == null) {
+ fromState = this.get('state');
+ }
+ return (_ref = this.transitionTable[event]) != null ? _ref[fromState] : void 0;
+ };
+
+ return StateMachine;
+
+ })(Batman.Object);
+
+ Batman.DelegatingStateMachine = (function(_super) {
+
+ __extends(DelegatingStateMachine, _super);
+
+ function DelegatingStateMachine(startState, base) {
+ this.base = base;
+ DelegatingStateMachine.__super__.constructor.call(this, startState);
+ }
+
+ DelegatingStateMachine.prototype.fire = function() {
+ var result, _ref;
+ result = DelegatingStateMachine.__super__.fire.apply(this, arguments);
+ (_ref = this.base).fire.apply(_ref, arguments);
+ return result;
+ };
+
+ return DelegatingStateMachine;
+
+ })(Batman.StateMachine);
+
+}).call(this);
+
+(function() {
+ var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
+ __hasProp = {}.hasOwnProperty,
+ __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
+ __slice = [].slice;
+
+ Batman.Model = (function(_super) {
+ var functionName, _i, _j, _len, _len1, _ref, _ref1;
+
+ __extends(Model, _super);
+
+ Model.storageKey = null;
+
+ Model.primaryKey = 'id';
+
+ Model.persist = function() {
+ var mechanism, options;
+ mechanism = arguments[0], options = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
+ Batman.initializeObject(this.prototype);
+ mechanism = mechanism.isStorageAdapter ? mechanism : new mechanism(this);
+ if (options.length > 0) {
+ Batman.mixin.apply(Batman, [mechanism].concat(__slice.call(options)));
+ }
+ this.prototype._batman.storage = mechanism;
+ return mechanism;
+ };
+
+ Model.storageAdapter = function() {
+ Batman.initializeObject(this.prototype);
+ return this.prototype._batman.storage;
+ };
+
+ Model.encode = function() {
+ var encoder, encoderForKey, encoderOrLastKey, key, keys, _base, _i, _j, _len;
+ keys = 2 <= arguments.length ? __slice.call(arguments, 0, _i = arguments.length - 1) : (_i = 0, []), encoderOrLastKey = arguments[_i++];
+ Batman.initializeObject(this.prototype);
+ (_base = this.prototype._batman).encoders || (_base.encoders = new Batman.SimpleHash);
+ encoder = {};
+ switch (Batman.typeOf(encoderOrLastKey)) {
+ case 'String':
+ keys.push(encoderOrLastKey);
+ break;
+ case 'Function':
+ encoder.encode = encoderOrLastKey;
+ break;
+ default:
+ encoder = encoderOrLastKey;
+ }
+ for (_j = 0, _len = keys.length; _j < _len; _j++) {
+ key = keys[_j];
+ encoderForKey = Batman.extend({
+ as: key
+ }, this.defaultEncoder, encoder);
+ this.prototype._batman.encoders.set(key, encoderForKey);
+ }
+ };
+
+ Model.defaultEncoder = {
+ encode: function(x) {
+ return x;
+ },
+ decode: function(x) {
+ return x;
+ }
+ };
+
+ Model.observeAndFire('primaryKey', function(newPrimaryKey, oldPrimaryKey) {
+ this.encode(oldPrimaryKey, {
+ encode: false,
+ decode: false
+ });
+ return this.encode(newPrimaryKey, {
+ encode: false,
+ decode: this.defaultEncoder.decode
+ });
+ });
+
+ Model.validate = function() {
+ var keys, matches, optionsOrFunction, validatorClass, validators, _base, _i, _j, _len, _ref, _results;
+ keys = 2 <= arguments.length ? __slice.call(arguments, 0, _i = arguments.length - 1) : (_i = 0, []), optionsOrFunction = arguments[_i++];
+ Batman.initializeObject(this.prototype);
+ validators = (_base = this.prototype._batman).validators || (_base.validators = []);
+ if (typeof optionsOrFunction === 'function') {
+ return validators.push({
+ keys: keys,
+ callback: optionsOrFunction
+ });
+ } else {
+ _ref = Batman.Validators;
+ _results = [];
+ for (_j = 0, _len = _ref.length; _j < _len; _j++) {
+ validatorClass = _ref[_j];
+ if ((matches = validatorClass.matches(optionsOrFunction))) {
+ _results.push(validators.push({
+ keys: keys,
+ validator: new validatorClass(matches)
+ }));
+ } else {
+ _results.push(void 0);
+ }
+ }
+ return _results;
+ }
+ };
+
+ Model.classAccessor('resourceName', {
+ get: function() {
+ if (this.resourceName != null) {
+ return this.resourceName;
+ } else {
+ if (Batman.config.minificationErrors) {
+ Batman.developer.error("Please define " + (Batman.functionName(this)) + ".resourceName in order for your model to be minification safe.");
+ }
+ return Batman.helpers.underscore(Batman.functionName(this));
+ }
+ }
+ });
+
+ Model.classAccessor('all', {
+ get: function() {
+ this._batman.check(this);
+ if (this.prototype.hasStorage() && !this._batman.allLoadTriggered) {
+ this.load();
+ this._batman.allLoadTriggered = true;
+ }
+ return this.get('loaded');
+ },
+ set: function(k, v) {
+ return this.set('loaded', v);
+ }
+ });
+
+ Model.classAccessor('loaded', {
+ get: function() {
+ return this._loaded || (this._loaded = new Batman.Set);
+ },
+ set: function(k, v) {
+ return this._loaded = v;
+ }
+ });
+
+ Model.classAccessor('first', function() {
+ return this.get('all').toArray()[0];
+ });
+
+ Model.classAccessor('last', function() {
+ var x;
+ x = this.get('all').toArray();
+ return x[x.length - 1];
+ });
+
+ Model.clear = function() {
+ var result, _ref;
+ Batman.initializeObject(this);
+ result = this.get('loaded').clear();
+ if ((_ref = this._batman.get('associations')) != null) {
+ _ref.reset();
+ }
+ this._resetPromises();
+ return result;
+ };
+
+ Model.find = function(id, callback) {
+ return this.findWithOptions(id, void 0, callback);
+ };
+
+ Model.findWithOptions = function(id, options, callback) {
+ var record;
+ if (options == null) {
+ options = {};
+ }
+ Batman.developer.assert(callback, "Must call find with a callback!");
+ record = new this();
+ record._withoutDirtyTracking(function() {
+ return this.set('id', id);
+ });
+ record.loadWithOptions(options, callback);
+ return record;
+ };
+
+ Model.load = function(options, callback) {
+ var _ref;
+ if ((_ref = typeof options) === 'function' || _ref === 'undefined') {
+ callback = options;
+ options = {};
+ } else {
+ options = {
+ data: options
+ };
+ }
+ return this.loadWithOptions(options, callback);
+ };
+
+ Model.loadWithOptions = function(options, callback) {
+ var _this = this;
+ this.fire('loading', options);
+ return this._doStorageOperation('readAll', options, function(err, records, env) {
+ var mappedRecords, record;
+ if (err != null) {
+ _this.fire('error', err);
+ return typeof callback === "function" ? callback(err, []) : void 0;
+ } else {
+ mappedRecords = (function() {
+ var _i, _len, _results;
+ _results = [];
+ for (_i = 0, _len = records.length; _i < _len; _i++) {
+ record = records[_i];
+ _results.push(this._mapIdentity(record));
+ }
+ return _results;
+ }).call(_this);
+ _this.fire('loaded', mappedRecords, env);
+ return typeof callback === "function" ? callback(err, mappedRecords, env) : void 0;
+ }
+ });
+ };
+
+ Model.create = function(attrs, callback) {
+ var obj, _ref;
+ if (!callback) {
+ _ref = [{}, attrs], attrs = _ref[0], callback = _ref[1];
+ }
+ obj = new this(attrs);
+ obj.save(callback);
+ return obj;
+ };
+
+ Model.findOrCreate = function(attrs, callback) {
+ var foundRecord, record;
+ record = new this(attrs);
+ if (record.isNew()) {
+ record.save(callback);
+ } else {
+ foundRecord = this._mapIdentity(record);
+ callback(void 0, foundRecord);
+ }
+ return record;
+ };
+
+ Model.createFromJSON = function(json) {
+ var record;
+ record = new this;
+ record._withoutDirtyTracking(function() {
+ return this.fromJSON(json);
+ });
+ return this._mapIdentity(record);
+ };
+
+ Model._mapIdentity = function(record) {
+ var existing, id, _ref;
+ if (typeof (id = record.get('id')) === 'undefined' || id === '') {
+ return record;
+ } else {
+ existing = (_ref = this.get("loaded.indexedBy.id").get(id)) != null ? _ref.toArray()[0] : void 0;
+ if (existing) {
+ existing._withoutDirtyTracking(function() {
+ var _ref1;
+ return this.updateAttributes(((_ref1 = record.get('attributes')) != null ? _ref1.toObject() : void 0) || {});
+ });
+ return existing;
+ } else {
+ this.get('loaded').add(record);
+ return record;
+ }
+ }
+ };
+
+ Model._doStorageOperation = function(operation, options, callback) {
+ var adapter;
+ Batman.developer.assert(this.prototype.hasStorage(), "Can't " + operation + " model " + (Batman.functionName(this.constructor)) + " without any storage adapters!");
+ adapter = this.prototype._batman.get('storage');
+ return adapter.perform(operation, this, options, callback);
+ };
+
+ _ref = ['find', 'load', 'create'];
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ functionName = _ref[_i];
+ Model[functionName] = Batman.Property.wrapTrackingPrevention(Model[functionName]);
+ }
+
+ Model.InstanceLifecycleStateMachine = (function(_super1) {
+
+ __extends(InstanceLifecycleStateMachine, _super1);
+
+ function InstanceLifecycleStateMachine() {
+ return InstanceLifecycleStateMachine.__super__.constructor.apply(this, arguments);
+ }
+
+ InstanceLifecycleStateMachine.transitions({
+ load: {
+ from: ['dirty', 'clean'],
+ to: 'loading'
+ },
+ create: {
+ from: ['dirty', 'clean'],
+ to: 'creating'
+ },
+ save: {
+ from: ['dirty', 'clean'],
+ to: 'saving'
+ },
+ destroy: {
+ from: ['dirty', 'clean'],
+ to: 'destroying'
+ },
+ failedValidation: {
+ from: ['saving', 'creating'],
+ to: 'dirty'
+ },
+ loaded: {
+ loading: 'clean'
+ },
+ created: {
+ creating: 'clean'
+ },
+ saved: {
+ saving: 'clean'
+ },
+ destroyed: {
+ destroying: 'destroyed'
+ },
+ set: {
+ from: ['dirty', 'clean'],
+ to: 'dirty'
+ },
+ error: {
+ from: ['saving', 'creating', 'loading', 'destroying'],
+ to: 'error'
+ }
+ });
+
+ return InstanceLifecycleStateMachine;
+
+ })(Batman.DelegatingStateMachine);
+
+ function Model(idOrAttributes) {
+ if (idOrAttributes == null) {
+ idOrAttributes = {};
+ }
+ this.destroy = __bind(this.destroy, this);
+
+ this.save = __bind(this.save, this);
+
+ this.loadWithOptions = __bind(this.loadWithOptions, this);
+
+ this.load = __bind(this.load, this);
+
+ Batman.developer.assert(this instanceof Batman.Object, "constructors must be called with new");
+ if (Batman.typeOf(idOrAttributes) === 'Object') {
+ Model.__super__.constructor.call(this, idOrAttributes);
+ } else {
+ Model.__super__.constructor.call(this);
+ this.set('id', idOrAttributes);
+ }
+ }
+
+ Model.accessor('lifecycle', function() {
+ return this.lifecycle || (this.lifecycle = new Batman.Model.InstanceLifecycleStateMachine('clean', this));
+ });
+
+ Model.accessor('attributes', function() {
+ return this.attributes || (this.attributes = new Batman.Hash);
+ });
+
+ Model.accessor('dirtyKeys', function() {
+ return this.dirtyKeys || (this.dirtyKeys = new Batman.Hash);
+ });
+
+ Model.accessor('_dirtiedKeys', function() {
+ return this._dirtiedKeys || (this._dirtiedKeys = new Batman.SimpleSet);
+ });
+
+ Model.accessor('errors', function() {
+ return this.errors || (this.errors = new Batman.ErrorsSet);
+ });
+
+ Model.accessor('isNew', function() {
+ return this.isNew();
+ });
+
+ Model.accessor('isDirty', function() {
+ return this.isDirty();
+ });
+
+ Model.accessor(Model.defaultAccessor = {
+ get: function(k) {
+ return Batman.getPath(this, ['attributes', k]);
+ },
+ set: function(k, v) {
+ if (this._willSet(k)) {
+ return this.get('attributes').set(k, v);
+ } else {
+ return this.get(k);
+ }
+ },
+ unset: function(k) {
+ return this.get('attributes').unset(k);
+ }
+ });
+
+ Model.wrapAccessor('id', function(core) {
+ return {
+ get: function() {
+ var primaryKey;
+ primaryKey = this.constructor.primaryKey;
+ if (primaryKey === 'id') {
+ return core.get.apply(this, arguments);
+ } else {
+ return this.get(primaryKey);
+ }
+ },
+ set: function(key, value) {
+ var parsedValue, primaryKey;
+ if ((typeof value === "string") && (value.match(/[^0-9]/) === null) && (("" + (parsedValue = parseInt(value, 10))) === value)) {
+ value = parsedValue;
+ }
+ primaryKey = this.constructor.primaryKey;
+ if (primaryKey === 'id') {
+ this._willSet(key);
+ return core.set.apply(this, arguments);
+ } else {
+ return this.set(primaryKey, value);
+ }
+ }
+ };
+ });
+
+ Model.prototype.isNew = function() {
+ return typeof this.get('id') === 'undefined';
+ };
+
+ Model.prototype.isDirty = function() {
+ return this.get('lifecycle.state') === 'dirty';
+ };
+
+ Model.prototype.updateAttributes = function(attrs) {
+ this.mixin(attrs);
+ return this;
+ };
+
+ Model.prototype.toString = function() {
+ return "" + (this.constructor.get('resourceName')) + ": " + (this.get('id'));
+ };
+
+ Model.prototype.toParam = function() {
+ return this.get('id');
+ };
+
+ Model.prototype.toJSON = function() {
+ var encoders, obj,
+ _this = this;
+ obj = {};
+ encoders = this._batman.get('encoders');
+ if (!(!encoders || encoders.isEmpty())) {
+ encoders.forEach(function(key, encoder) {
+ var encodedVal, val;
+ if (encoder.encode) {
+ val = _this.get(key);
+ if (typeof val !== 'undefined') {
+ encodedVal = encoder.encode(val, key, obj, _this);
+ if (typeof encodedVal !== 'undefined') {
+ return obj[encoder.as] = encodedVal;
+ }
+ }
+ }
+ });
+ }
+ return obj;
+ };
+
+ Model.prototype.fromJSON = function(data) {
+ var encoders, key, obj, value,
+ _this = this;
+ obj = {};
+ encoders = this._batman.get('encoders');
+ if (!encoders || encoders.isEmpty() || !encoders.some(function(key, encoder) {
+ return encoder.decode != null;
+ })) {
+ for (key in data) {
+ value = data[key];
+ obj[key] = value;
+ }
+ } else {
+ encoders.forEach(function(key, encoder) {
+ if (encoder.decode && typeof data[encoder.as] !== 'undefined') {
+ return obj[key] = encoder.decode(data[encoder.as], encoder.as, data, obj, _this);
+ }
+ });
+ }
+ if (this.constructor.primaryKey !== 'id') {
+ obj.id = data[this.constructor.primaryKey];
+ }
+ Batman.developer["do"](function() {
+ if ((!encoders) || encoders.length <= 1) {
+ return Batman.developer.warn("Warning: Model " + (Batman.functionName(_this.constructor)) + " has suspiciously few decoders!");
+ }
+ });
+ return this.mixin(obj);
+ };
+
+ Model.prototype.hasStorage = function() {
+ return this._batman.get('storage') != null;
+ };
+
+ Model.prototype.load = function(options, callback) {
+ var _ref1;
+ if (!callback) {
+ _ref1 = [{}, options], options = _ref1[0], callback = _ref1[1];
+ } else {
+ options = {
+ data: options
+ };
+ }
+ return this.loadWithOptions(options, callback);
+ };
+
+ Model.prototype.loadWithOptions = function(options, callback) {
+ var callbackQueue, hasOptions, _ref1,
+ _this = this;
+ hasOptions = Object.keys(options).length !== 0;
+ if ((_ref1 = this.get('lifecycle.state')) === 'destroying' || _ref1 === 'destroyed') {
+ if (typeof callback === "function") {
+ callback(new Error("Can't load a destroyed record!"));
+ }
+ return;
+ }
+ if (this.get('lifecycle').load()) {
+ callbackQueue = [];
+ if (callback != null) {
+ callbackQueue.push(callback);
+ }
+ if (!hasOptions) {
+ this._currentLoad = callbackQueue;
+ }
+ return this._doStorageOperation('read', options, function(err, record, env) {
+ var _j, _len1;
+ if (!err) {
+ _this.get('lifecycle').loaded();
+ record = _this.constructor._mapIdentity(record);
+ } else {
+ _this.get('lifecycle').error();
+ }
+ if (!hasOptions) {
+ _this._currentLoad = null;
+ }
+ for (_j = 0, _len1 = callbackQueue.length; _j < _len1; _j++) {
+ callback = callbackQueue[_j];
+ callback(err, record, env);
+ }
+ });
+ } else {
+ if (this.get('lifecycle.state') === 'loading' && !hasOptions) {
+ if (callback != null) {
+ return this._currentLoad.push(callback);
+ }
+ } else {
+ return typeof callback === "function" ? callback(new Batman.StateMachine.InvalidTransitionError("Can't load while in state " + (this.get('lifecycle.state')))) : void 0;
+ }
+ }
+ };
+
+ Model.prototype.save = function(options, callback) {
+ var endState, isNew, startState, storageOperation, _ref1, _ref2,
+ _this = this;
+ if (!callback) {
+ _ref1 = [{}, options], options = _ref1[0], callback = _ref1[1];
+ }
+ isNew = this.isNew();
+ _ref2 = isNew ? ['create', 'create', 'created'] : ['save', 'update', 'saved'], startState = _ref2[0], storageOperation = _ref2[1], endState = _ref2[2];
+ if (this.get('lifecycle').startTransition(startState)) {
+ return this.validate(function(error, errors) {
+ var associations;
+ if (error || errors.length) {
+ _this.get('lifecycle').failedValidation();
+ return typeof callback === "function" ? callback(error || errors, _this) : void 0;
+ }
+ associations = _this.constructor._batman.get('associations');
+ _this._withoutDirtyTracking(function() {
+ var _ref3,
+ _this = this;
+ return associations != null ? (_ref3 = associations.getByType('belongsTo')) != null ? _ref3.forEach(function(association, label) {
+ return association.apply(_this);
+ }) : void 0 : void 0;
+ });
+ return _this._doStorageOperation(storageOperation, {
+ data: options
+ }, function(err, record, env) {
+ if (!err) {
+ _this.get('dirtyKeys').clear();
+ _this.get('_dirtiedKeys').clear();
+ if (associations) {
+ record._withoutDirtyTracking(function() {
+ var _ref3, _ref4;
+ if ((_ref3 = associations.getByType('hasOne')) != null) {
+ _ref3.forEach(function(association, label) {
+ return association.apply(err, record);
+ });
+ }
+ return (_ref4 = associations.getByType('hasMany')) != null ? _ref4.forEach(function(association, label) {
+ return association.apply(err, record);
+ }) : void 0;
+ });
+ }
+ record = _this.constructor._mapIdentity(record);
+ _this.get('lifecycle').startTransition(endState);
+ } else {
+ if (err instanceof Batman.ErrorsSet) {
+ _this.get('lifecycle').failedValidation();
+ } else {
+ _this.get('lifecycle').error();
+ }
+ }
+ return typeof callback === "function" ? callback(err, record || _this, env) : void 0;
+ });
+ });
+ } else {
+ return typeof callback === "function" ? callback(new Batman.StateMachine.InvalidTransitionError("Can't save while in state " + (this.get('lifecycle.state')))) : void 0;
+ }
+ };
+
+ Model.prototype.destroy = function(options, callback) {
+ var _ref1,
+ _this = this;
+ if (!callback) {
+ _ref1 = [{}, options], options = _ref1[0], callback = _ref1[1];
+ }
+ if (this.get('lifecycle').destroy()) {
+ return this._doStorageOperation('destroy', {
+ data: options
+ }, function(err, record, env) {
+ if (!err) {
+ _this.constructor.get('loaded').remove(_this);
+ _this.get('lifecycle').destroyed();
+ } else {
+ _this.get('lifecycle').error();
+ }
+ return typeof callback === "function" ? callback(err, record, env) : void 0;
+ });
+ } else {
+ return typeof callback === "function" ? callback(new Batman.StateMachine.InvalidTransitionError("Can't destroy while in state " + (this.get('lifecycle.state')))) : void 0;
+ }
+ };
+
+ Model.prototype.validate = function(callback) {
+ var args, count, errors, finishedValidation, key, validator, validators, _j, _k, _len1, _len2, _ref1;
+ errors = this.get('errors');
+ errors.clear();
+ validators = this._batman.get('validators') || [];
+ if (!validators || validators.length === 0) {
+ if (typeof callback === "function") {
+ callback(void 0, errors);
+ }
+ return true;
+ }
+ count = validators.reduce((function(acc, validator) {
+ return acc + validator.keys.length;
+ }), 0);
+ finishedValidation = function() {
+ if (--count === 0) {
+ return typeof callback === "function" ? callback(void 0, errors) : void 0;
+ }
+ };
+ for (_j = 0, _len1 = validators.length; _j < _len1; _j++) {
+ validator = validators[_j];
+ _ref1 = validator.keys;
+ for (_k = 0, _len2 = _ref1.length; _k < _len2; _k++) {
+ key = _ref1[_k];
+ args = [errors, this, key, finishedValidation];
+ try {
+ if (validator.validator) {
+ validator.validator.validateEach.apply(validator.validator, args);
+ } else {
+ validator.callback.apply(validator, args);
+ }
+ } catch (e) {
+ if (typeof callback === "function") {
+ callback(e, errors);
+ }
+ }
+ }
+ }
+ };
+
+ Model.prototype.associationProxy = function(association) {
+ var proxies, _base, _name;
+ Batman.initializeObject(this);
+ proxies = (_base = this._batman).associationProxies || (_base.associationProxies = {});
+ proxies[_name = association.label] || (proxies[_name] = new association.proxyClass(association, this));
+ return proxies[association.label];
+ };
+
+ Model.prototype._willSet = function(key) {
+ if (this._pauseDirtyTracking) {
+ return true;
+ }
+ if (this.get('lifecycle').startTransition('set')) {
+ if (!this.get('_dirtiedKeys').has(key)) {
+ this.set("dirtyKeys." + key, this.get(key));
+ this.get('_dirtiedKeys').add(key);
+ }
+ return true;
+ } else {
+ return false;
+ }
+ };
+
+ Model.prototype._doStorageOperation = function(operation, options, callback) {
+ var adapter,
+ _this = this;
+ Batman.developer.assert(this.hasStorage(), "Can't " + operation + " model " + (Batman.functionName(this.constructor)) + " without any storage adapters!");
+ adapter = this._batman.get('storage');
+ return adapter.perform(operation, this, options, function() {
+ return callback.apply(null, arguments);
+ });
+ };
+
+ Model.prototype._withoutDirtyTracking = function(block) {
+ var result;
+ this._pauseDirtyTracking = true;
+ result = block.call(this);
+ this._pauseDirtyTracking = false;
+ return result;
+ };
+
+ _ref1 = ['load', 'save', 'validate', 'destroy'];
+ for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
+ functionName = _ref1[_j];
+ Model.prototype[functionName] = Batman.Property.wrapTrackingPrevention(Model.prototype[functionName]);
+ }
+
+ return Model;
+
+ }).call(this, Batman.Object);
+
+}).call(this);
+
+(function() {
+ var k, _fn, _i, _len, _ref,
+ _this = this;
+
+ _ref = Batman.AssociationCurator.availableAssociations;
+ _fn = function(k) {
+ return Batman.Model[k] = function(label, scope) {
+ var collection, _base;
+ Batman.initializeObject(this);
+ collection = (_base = this._batman).associations || (_base.associations = new Batman.AssociationCurator(this));
+ return collection.add(new Batman["" + (Batman.helpers.capitalize(k)) + "Association"](this, label, scope));
+ };
+ };
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ k = _ref[_i];
+ _fn(k);
+ }
+
+}).call(this);
+
+(function() {
+ var __hasProp = {}.hasOwnProperty,
+ __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
+
+ Batman.Proxy = (function(_super) {
+
+ __extends(Proxy, _super);
+
+ Proxy.prototype.isProxy = true;
+
+ function Proxy(target) {
+ Proxy.__super__.constructor.call(this);
+ if (target != null) {
+ this.set('target', target);
+ }
+ }
+
+ Proxy.accessor('target', Batman.Property.defaultAccessor);
+
+ Proxy.accessor({
+ get: function(key) {
+ var _ref;
+ return (_ref = this.get('target')) != null ? _ref.get(key) : void 0;
+ },
+ set: function(key, value) {
+ var _ref;
+ return (_ref = this.get('target')) != null ? _ref.set(key, value) : void 0;
+ },
+ unset: function(key) {
+ var _ref;
+ return (_ref = this.get('target')) != null ? _ref.unset(key) : void 0;
+ }
+ });
+
+ return Proxy;
+
+ })(Batman.Object);
+
+}).call(this);
+
+(function() {
+ var __hasProp = {}.hasOwnProperty,
+ __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
+
+ Batman.AssociationProxy = (function(_super) {
+
+ __extends(AssociationProxy, _super);
+
+ AssociationProxy.prototype.loaded = false;
+
+ function AssociationProxy(association, model) {
+ this.association = association;
+ this.model = model;
+ AssociationProxy.__super__.constructor.call(this);
+ }
+
+ AssociationProxy.prototype.toJSON = function() {
+ var target;
+ target = this.get('target');
+ if (target != null) {
+ return this.get('target').toJSON();
+ }
+ };
+
+ AssociationProxy.prototype.load = function(callback) {
+ var _this = this;
+ this.fetch(function(err, proxiedRecord) {
+ if (!err) {
+ _this._setTarget(proxiedRecord);
+ }
+ return typeof callback === "function" ? callback(err, proxiedRecord) : void 0;
+ });
+ return this.get('target');
+ };
+
+ AssociationProxy.prototype.loadFromLocal = function() {
+ var target;
+ if (!this._canLoad()) {
+ return;
+ }
+ if (target = this.fetchFromLocal()) {
+ this._setTarget(target);
+ }
+ return target;
+ };
+
+ AssociationProxy.prototype.fetch = function(callback) {
+ var record;
+ if (!this._canLoad()) {
+ return callback(void 0, void 0);
+ }
+ record = this.fetchFromLocal();
+ if (record) {
+ return callback(void 0, record);
+ } else {
+ return this.fetchFromRemote(callback);
+ }
+ };
+
+ AssociationProxy.accessor('loaded', Batman.Property.defaultAccessor);
+
+ AssociationProxy.accessor('target', {
+ get: function() {
+ return this.fetchFromLocal();
+ },
+ set: function(_, v) {
+ return v;
+ }
+ });
+
+ AssociationProxy.prototype._canLoad = function() {
+ return (this.get('foreignValue') || this.get('primaryValue')) != null;
+ };
+
+ AssociationProxy.prototype._setTarget = function(target) {
+ this.set('target', target);
+ this.set('loaded', true);
+ return this.fire('loaded', target);
+ };
+
+ return AssociationProxy;
+
+ })(Batman.Proxy);
+
+}).call(this);
+
+(function() {
+ var __hasProp = {}.hasOwnProperty,
+ __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
+
+ Batman.HasOneProxy = (function(_super) {
+
+ __extends(HasOneProxy, _super);
+
+ function HasOneProxy() {
+ return HasOneProxy.__super__.constructor.apply(this, arguments);
+ }
+
+ HasOneProxy.accessor('primaryValue', function() {
+ return this.model.get(this.association.primaryKey);
+ });
+
+ HasOneProxy.prototype.fetchFromLocal = function() {
+ return this.association.setIndex().get(this.get('primaryValue'));
+ };
+
+ HasOneProxy.prototype.fetchFromRemote = function(callback) {
+ var loadOptions,
+ _this = this;
+ loadOptions = {
+ data: {}
+ };
+ loadOptions.data[this.association.foreignKey] = this.get('primaryValue');
+ if (this.association.options.url) {
+ loadOptions.collectionUrl = this.association.options.url;
+ loadOptions.urlContext = this.model;
+ }
+ return this.association.getRelatedModel().loadWithOptions(loadOptions, function(error, loadedRecords) {
+ if (error) {
+ throw error;
+ }
+ if (!loadedRecords || loadedRecords.length <= 0) {
+ return callback(new Error("Couldn't find related record!"), void 0);
+ } else {
+ return callback(void 0, loadedRecords[0]);
+ }
+ });
+ };
+
+ return HasOneProxy;
+
+ })(Batman.AssociationProxy);
+
+}).call(this);
+
+(function() {
+ var __hasProp = {}.hasOwnProperty,
+ __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
+
+ Batman.BelongsToProxy = (function(_super) {
+
+ __extends(BelongsToProxy, _super);
+
+ function BelongsToProxy() {
+ return BelongsToProxy.__super__.constructor.apply(this, arguments);
+ }
+
+ BelongsToProxy.accessor('foreignValue', function() {
+ return this.model.get(this.association.foreignKey);
+ });
+
+ BelongsToProxy.prototype.fetchFromLocal = function() {
+ return this.association.setIndex().get(this.get('foreignValue'));
+ };
+
+ BelongsToProxy.prototype.fetchFromRemote = function(callback) {
+ var loadOptions,
+ _this = this;
+ loadOptions = {};
+ if (this.association.options.url) {
+ loadOptions.recordUrl = this.association.options.url;
+ }
+ return this.association.getRelatedModel().findWithOptions(this.get('foreignValue'), loadOptions, function(error, loadedRecord) {
+ if (error) {
+ throw error;
+ }
+ return callback(void 0, loadedRecord);
+ });
+ };
+
+ return BelongsToProxy;
+
+ })(Batman.AssociationProxy);
+
+}).call(this);
+
+(function() {
+ var __hasProp = {}.hasOwnProperty,
+ __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
+
+ Batman.PolymorphicBelongsToProxy = (function(_super) {
+
+ __extends(PolymorphicBelongsToProxy, _super);
+
+ function PolymorphicBelongsToProxy() {
+ return PolymorphicBelongsToProxy.__super__.constructor.apply(this, arguments);
+ }
+
+ PolymorphicBelongsToProxy.accessor('foreignTypeValue', function() {
+ return this.model.get(this.association.foreignTypeKey);
+ });
+
+ PolymorphicBelongsToProxy.prototype.fetchFromLocal = function() {
+ return this.association.setIndexForType(this.get('foreignTypeValue')).get(this.get('foreignValue'));
+ };
+
+ PolymorphicBelongsToProxy.prototype.fetchFromRemote = function(callback) {
+ var loadOptions,
+ _this = this;
+ loadOptions = {};
+ if (this.association.options.url) {
+ loadOptions.recordUrl = this.association.options.url;
+ }
+ return this.association.getRelatedModelForType(this.get('foreignTypeValue')).findWithOptions(this.get('foreignValue'), loadOptions, function(error, loadedRecord) {
+ if (error) {
+ throw error;
+ }
+ return callback(void 0, loadedRecord);
+ });
+ };
+
+ return PolymorphicBelongsToProxy;
+
+ })(Batman.BelongsToProxy);
}).call(this);
@@ -8121,6 +8392,358 @@
}).call(this);
(function() {
+
+ Batman.mixins = new Batman.Object;
+
+}).call(this);
+
+(function() {
+
+ Batman.URI = (function() {
+ /*
+ # URI parsing
+ */
+
+ var attributes, childKeyMatchers, decodeQueryComponent, encodeComponent, encodeQueryComponent, keyVal, nameParser, normalizeParams, plus, queryFromParams, r20, strictParser;
+
+ strictParser = /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/;
+
+ attributes = ["source", "protocol", "authority", "userInfo", "user", "password", "hostname", "port", "relative", "path", "directory", "file", "query", "hash"];
+
+ function URI(str) {
+ var i, matches;
+ matches = strictParser.exec(str);
+ i = 14;
+ while (i--) {
+ this[attributes[i]] = matches[i] || '';
+ }
+ this.queryParams = this.constructor.paramsFromQuery(this.query);
+ delete this.authority;
+ delete this.userInfo;
+ delete this.relative;
+ delete this.directory;
+ delete this.file;
+ delete this.query;
+ }
+
+ URI.prototype.queryString = function() {
+ return this.constructor.queryFromParams(this.queryParams);
+ };
+
+ URI.prototype.toString = function() {
+ return [this.protocol ? "" + this.protocol + ":" : void 0, this.authority() ? "//" : void 0, this.authority(), this.relative()].join("");
+ };
+
+ URI.prototype.userInfo = function() {
+ return [this.user, this.password ? ":" + this.password : void 0].join("");
+ };
+
+ URI.prototype.authority = function() {
+ return [this.userInfo(), this.user || this.password ? "@" : void 0, this.hostname, this.port ? ":" + this.port : void 0].join("");
+ };
+
+ URI.prototype.relative = function() {
+ var query;
+ query = this.queryString();
+ return [this.path, query ? "?" + query : void 0, this.hash ? "#" + this.hash : void 0].join("");
+ };
+
+ URI.prototype.directory = function() {
+ var splitPath;
+ splitPath = this.path.split('/');
+ if (splitPath.length > 1) {
+ return splitPath.slice(0, splitPath.length - 1).join('/') + "/";
+ } else {
+ return "";
+ }
+ };
+
+ URI.prototype.file = function() {
+ var splitPath;
+ splitPath = this.path.split("/");
+ return splitPath[splitPath.length - 1];
+ };
+
+ /*
+ # query parsing
+ */
+
+
+ URI.paramsFromQuery = function(query) {
+ var matches, params, segment, _i, _len, _ref;
+ params = {};
+ _ref = query.split('&');
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ segment = _ref[_i];
+ if (matches = segment.match(keyVal)) {
+ normalizeParams(params, decodeQueryComponent(matches[1]), decodeQueryComponent(matches[2]));
+ } else {
+ normalizeParams(params, decodeQueryComponent(segment), null);
+ }
+ }
+ return params;
+ };
+
+ URI.decodeQueryComponent = decodeQueryComponent = function(str) {
+ return decodeURIComponent(str.replace(plus, '%20'));
+ };
+
+ nameParser = /^[\[\]]*([^\[\]]+)\]*(.*)/;
+
+ childKeyMatchers = [/^\[\]\[([^\[\]]+)\]$/, /^\[\](.+)$/];
+
+ plus = /\+/g;
+
+ r20 = /%20/g;
+
+ keyVal = /^([^=]*)=(.*)/;
+
+ normalizeParams = function(params, name, v) {
+ var after, childKey, k, last, matches, _ref, _ref1, _ref2;
+ if (matches = name.match(nameParser)) {
+ k = matches[1];
+ after = matches[2];
+ } else {
+ return;
+ }
+ if (after === '') {
+ params[k] = v;
+ } else if (after === '[]') {
+ if ((_ref = params[k]) == null) {
+ params[k] = [];
+ }
+ if (Batman.typeOf(params[k]) !== 'Array') {
+ throw new Error("expected Array (got " + (Batman.typeOf(params[k])) + ") for param \"" + k + "\"");
+ }
+ params[k].push(v);
+ } else if (matches = after.match(childKeyMatchers[0]) || after.match(childKeyMatchers[1])) {
+ childKey = matches[1];
+ if ((_ref1 = params[k]) == null) {
+ params[k] = [];
+ }
+ if (Batman.typeOf(params[k]) !== 'Array') {
+ throw new Error("expected Array (got " + (Batman.typeOf(params[k])) + ") for param \"" + k + "\"");
+ }
+ last = params[k][params[k].length - 1];
+ if (Batman.typeOf(last) === 'Object' && !(childKey in last)) {
+ normalizeParams(last, childKey, v);
+ } else {
+ params[k].push(normalizeParams({}, childKey, v));
+ }
+ } else {
+ if ((_ref2 = params[k]) == null) {
+ params[k] = {};
+ }
+ if (Batman.typeOf(params[k]) !== 'Object') {
+ throw new Error("expected Object (got " + (Batman.typeOf(params[k])) + ") for param \"" + k + "\"");
+ }
+ params[k] = normalizeParams(params[k], after, v);
+ }
+ return params;
+ };
+
+ /*
+ # query building
+ */
+
+
+ URI.queryFromParams = queryFromParams = function(value, prefix) {
+ var arrayResults, k, v, valueType;
+ if (value == null) {
+ return prefix;
+ }
+ valueType = Batman.typeOf(value);
+ if (!((prefix != null) || valueType === 'Object')) {
+ throw new Error("value must be an Object");
+ }
+ switch (valueType) {
+ case 'Array':
+ return ((function() {
+ var _i, _len;
+ arrayResults = [];
+ if (value.length === 0) {
+ arrayResults.push(queryFromParams(null, "" + prefix + "[]"));
+ } else {
+ for (_i = 0, _len = value.length; _i < _len; _i++) {
+ v = value[_i];
+ arrayResults.push(queryFromParams(v, "" + prefix + "[]"));
+ }
+ }
+ return arrayResults;
+ })()).join("&");
+ case 'Object':
+ return ((function() {
+ var _results;
+ _results = [];
+ for (k in value) {
+ v = value[k];
+ _results.push(queryFromParams(v, prefix ? "" + prefix + "[" + (encodeQueryComponent(k)) + "]" : encodeQueryComponent(k)));
+ }
+ return _results;
+ })()).join("&");
+ default:
+ if (prefix != null) {
+ return "" + prefix + "=" + (encodeQueryComponent(value));
+ } else {
+ return encodeQueryComponent(value);
+ }
+ }
+ };
+
+ URI.encodeComponent = encodeComponent = function(str) {
+ if (str != null) {
+ return encodeURIComponent(str);
+ } else {
+ return '';
+ }
+ };
+
+ URI.encodeQueryComponent = encodeQueryComponent = function(str) {
+ return encodeComponent(str).replace(r20, '+');
+ };
+
+ return URI;
+
+ })();
+
+}).call(this);
+
+(function() {
+ var __hasProp = {}.hasOwnProperty,
+ __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
+
+ Batman.Request = (function(_super) {
+ var dataHasFileUploads;
+
+ __extends(Request, _super);
+
+ Request.objectToFormData = function(data) {
+ var formData, key, pairForList, val, _i, _len, _ref, _ref1;
+ pairForList = function(key, object, first) {
+ var k, list, v;
+ if (first == null) {
+ first = false;
+ }
+ if (object instanceof Batman.container.File) {
+ return [[key, object]];
+ }
+ return list = (function() {
+ switch (Batman.typeOf(object)) {
+ case 'Object':
+ list = (function() {
+ var _results;
+ _results = [];
+ for (k in object) {
+ v = object[k];
+ _results.push(pairForList((first ? k : "" + key + "[" + k + "]"), v));
+ }
+ return _results;
+ })();
+ return list.reduce(function(acc, list) {
+ return acc.concat(list);
+ }, []);
+ case 'Array':
+ return object.reduce(function(acc, element) {
+ return acc.concat(pairForList("" + key + "[]", element));
+ }, []);
+ default:
+ return [[key, object != null ? object : ""]];
+ }
+ })();
+ };
+ formData = new Batman.container.FormData();
+ _ref = pairForList("", data, true);
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ _ref1 = _ref[_i], key = _ref1[0], val = _ref1[1];
+ formData.append(key, val);
+ }
+ return formData;
+ };
+
+ Request.dataHasFileUploads = dataHasFileUploads = function(data) {
+ var k, type, v, _i, _len;
+ if ((typeof File !== "undefined" && File !== null) && data instanceof File) {
+ return true;
+ }
+ type = Batman.typeOf(data);
+ switch (type) {
+ case 'Object':
+ for (k in data) {
+ v = data[k];
+ if (dataHasFileUploads(v)) {
+ return true;
+ }
+ }
+ break;
+ case 'Array':
+ for (_i = 0, _len = data.length; _i < _len; _i++) {
+ v = data[_i];
+ if (dataHasFileUploads(v)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ };
+
+ Request.wrapAccessor('method', function(core) {
+ return {
+ set: function(k, val) {
+ return core.set.call(this, k, val != null ? typeof val.toUpperCase === "function" ? val.toUpperCase() : void 0 : void 0);
+ }
+ };
+ });
+
+ Request.prototype.method = 'GET';
+
+ Request.prototype.hasFileUploads = function() {
+ return dataHasFileUploads(this.data);
+ };
+
+ Request.prototype.contentType = 'application/x-www-form-urlencoded';
+
+ Request.prototype.autosend = true;
+
+ function Request(options) {
+ var handler, handlers, k, _ref;
+ handlers = {};
+ for (k in options) {
+ handler = options[k];
+ if (!(k === 'success' || k === 'error' || k === 'loading' || k === 'loaded')) {
+ continue;
+ }
+ handlers[k] = handler;
+ delete options[k];
+ }
+ Request.__super__.constructor.call(this, options);
+ for (k in handlers) {
+ handler = handlers[k];
+ this.on(k, handler);
+ }
+ if (((_ref = this.get('url')) != null ? _ref.length : void 0) > 0) {
+ if (this.autosend) {
+ this.send();
+ }
+ } else {
+ this.observe('url', function(url) {
+ if (url != null) {
+ return this.send();
+ }
+ });
+ }
+ }
+
+ Request.prototype.send = function() {
+ return Batman.developer.error("Please source a dependency file for a request implementation");
+ };
+
+ return Request;
+
+ })(Batman.Object);
+
+}).call(this);
+
+(function() {
var __hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
__slice = [].slice;
@@ -8284,6 +8907,27 @@
return _results;
};
+ SetSort.prototype.find = function(block) {
+ var item, _i, _len, _ref;
+ this.base.registerAsMutableSource();
+ _ref = this.get('_storage');
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ item = _ref[_i];
+ if (block(item)) {
+ return item;
+ }
+ }
+ };
+
+ SetSort.prototype.merge = function(other) {
+ this.base.registerAsMutableSource();
+ return (function(func, args, ctor) {
+ ctor.prototype = func.prototype;
+ var child = new ctor, result = func.apply(child, args), t = typeof result;
+ return t == "object" || t == "function" ? result || child : child;
+ })(Batman.Set, this._storage, function(){}).merge(other).sortedBy(this.key, this.order);
+ };
+
SetSort.prototype.compare = function(a, b) {
if (a === b) {
return 0;
@@ -8388,7 +9032,7 @@
if (this.foreignKeyValue == null) {
return callback(void 0, this);
}
- return this.association.getRelatedModel().load(this._getLoadOptions(), function(err, records) {
+ return this.association.getRelatedModel().loadWithOptions(this._getLoadOptions(), function(err, records) {
if (!err) {
_this.markAsLoaded();
}
@@ -8398,8 +9042,14 @@
AssociationSet.prototype._getLoadOptions = function() {
var loadOptions;
- loadOptions = {};
- loadOptions[this.association.foreignKey] = this.foreignKeyValue;
+ loadOptions = {
+ data: {}
+ };
+ loadOptions.data[this.association.foreignKey] = this.foreignKeyValue;
+ if (this.association.options.url) {
+ loadOptions.collectionUrl = this.association.options.url;
+ loadOptions.urlContext = this.association.parentSetIndex().get(this.foreignKeyValue);
+ }
return loadOptions;
};
@@ -8433,9 +9083,15 @@
PolymorphicAssociationSet.prototype._getLoadOptions = function() {
var loadOptions;
- loadOptions = {};
- loadOptions[this.association.foreignKey] = this.foreignKeyValue;
- loadOptions[this.association.foreignTypeKey] = this.foreignTypeKeyValue;
+ loadOptions = {
+ data: {}
+ };
+ loadOptions.data[this.association.foreignKey] = this.foreignKeyValue;
+ loadOptions.data[this.association.foreignTypeKey] = this.foreignTypeKeyValue;
+ if (this.association.options.url) {
+ loadOptions.collectionUrl = this.association.options.url;
+ loadOptions.urlContext = this.association.parentSetIndex().get(this.foreignKeyValue);
+ }
return loadOptions;
};
@@ -8612,14 +9268,27 @@
}
AssociationSetIndex.prototype._resultSetForKey = function(key) {
+ return this.association.setForKey(key);
+ };
+
+ AssociationSetIndex.prototype.forEach = function(iterator, ctx) {
var _this = this;
- return this._storage.getOrSet(key, function() {
- return new _this.association.proxyClass(key, _this.association);
+ return this.association.proxies.forEach(function(record, set) {
+ var key;
+ key = _this.association.indexValueForRecord(record);
+ if (set.get('length') > 0) {
+ return iterator.call(ctx, key, set, _this);
+ }
});
};
- AssociationSetIndex.prototype._setResultSet = function(key, set) {
- return this._storage.set(key, set);
+ AssociationSetIndex.prototype.toArray = function() {
+ var results;
+ results = [];
+ this.forEach(function(key) {
+ return results.push(key);
+ });
+ return results;
};
return AssociationSetIndex;
@@ -8709,349 +9378,6 @@
}).call(this);
(function() {
-
- Batman.URI = (function() {
- /*
- # URI parsing
- */
-
- var attributes, childKeyMatchers, decodeQueryComponent, encodeComponent, encodeQueryComponent, keyVal, nameParser, normalizeParams, plus, queryFromParams, r20, strictParser;
-
- strictParser = /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/;
-
- attributes = ["source", "protocol", "authority", "userInfo", "user", "password", "hostname", "port", "relative", "path", "directory", "file", "query", "hash"];
-
- function URI(str) {
- var i, matches;
- matches = strictParser.exec(str);
- i = 14;
- while (i--) {
- this[attributes[i]] = matches[i] || '';
- }
- this.queryParams = this.constructor.paramsFromQuery(this.query);
- delete this.authority;
- delete this.userInfo;
- delete this.relative;
- delete this.directory;
- delete this.file;
- delete this.query;
- }
-
- URI.prototype.queryString = function() {
- return this.constructor.queryFromParams(this.queryParams);
- };
-
- URI.prototype.toString = function() {
- return [this.protocol ? "" + this.protocol + ":" : void 0, this.authority() ? "//" : void 0, this.authority(), this.relative()].join("");
- };
-
- URI.prototype.userInfo = function() {
- return [this.user, this.password ? ":" + this.password : void 0].join("");
- };
-
- URI.prototype.authority = function() {
- return [this.userInfo(), this.user || this.password ? "@" : void 0, this.hostname, this.port ? ":" + this.port : void 0].join("");
- };
-
- URI.prototype.relative = function() {
- var query;
- query = this.queryString();
- return [this.path, query ? "?" + query : void 0, this.hash ? "#" + this.hash : void 0].join("");
- };
-
- URI.prototype.directory = function() {
- var splitPath;
- splitPath = this.path.split('/');
- if (splitPath.length > 1) {
- return splitPath.slice(0, splitPath.length - 1).join('/') + "/";
- } else {
- return "";
- }
- };
-
- URI.prototype.file = function() {
- var splitPath;
- splitPath = this.path.split("/");
- return splitPath[splitPath.length - 1];
- };
-
- /*
- # query parsing
- */
-
-
- URI.paramsFromQuery = function(query) {
- var matches, params, segment, _i, _len, _ref;
- params = {};
- _ref = query.split('&');
- for (_i = 0, _len = _ref.length; _i < _len; _i++) {
- segment = _ref[_i];
- if (matches = segment.match(keyVal)) {
- normalizeParams(params, decodeQueryComponent(matches[1]), decodeQueryComponent(matches[2]));
- } else {
- normalizeParams(params, decodeQueryComponent(segment), null);
- }
- }
- return params;
- };
-
- URI.decodeQueryComponent = decodeQueryComponent = function(str) {
- return decodeURIComponent(str.replace(plus, '%20'));
- };
-
- nameParser = /^[\[\]]*([^\[\]]+)\]*(.*)/;
-
- childKeyMatchers = [/^\[\]\[([^\[\]]+)\]$/, /^\[\](.+)$/];
-
- plus = /\+/g;
-
- r20 = /%20/g;
-
- keyVal = /^([^=]*)=(.*)/;
-
- normalizeParams = function(params, name, v) {
- var after, childKey, k, last, matches, _ref, _ref1, _ref2;
- if (matches = name.match(nameParser)) {
- k = matches[1];
- after = matches[2];
- } else {
- return;
- }
- if (after === '') {
- params[k] = v;
- } else if (after === '[]') {
- if ((_ref = params[k]) == null) {
- params[k] = [];
- }
- if (Batman.typeOf(params[k]) !== 'Array') {
- throw new Error("expected Array (got " + (Batman.typeOf(params[k])) + ") for param \"" + k + "\"");
- }
- params[k].push(v);
- } else if (matches = after.match(childKeyMatchers[0]) || after.match(childKeyMatchers[1])) {
- childKey = matches[1];
- if ((_ref1 = params[k]) == null) {
- params[k] = [];
- }
- if (Batman.typeOf(params[k]) !== 'Array') {
- throw new Error("expected Array (got " + (Batman.typeOf(params[k])) + ") for param \"" + k + "\"");
- }
- last = params[k][params[k].length - 1];
- if (Batman.typeOf(last) === 'Object' && !(childKey in last)) {
- normalizeParams(last, childKey, v);
- } else {
- params[k].push(normalizeParams({}, childKey, v));
- }
- } else {
- if ((_ref2 = params[k]) == null) {
- params[k] = {};
- }
- if (Batman.typeOf(params[k]) !== 'Object') {
- throw new Error("expected Object (got " + (Batman.typeOf(params[k])) + ") for param \"" + k + "\"");
- }
- params[k] = normalizeParams(params[k], after, v);
- }
- return params;
- };
-
- /*
- # query building
- */
-
-
- URI.queryFromParams = queryFromParams = function(value, prefix) {
- var arrayResults, k, v, valueType;
- if (value == null) {
- return prefix;
- }
- valueType = Batman.typeOf(value);
- if (!((prefix != null) || valueType === 'Object')) {
- throw new Error("value must be an Object");
- }
- switch (valueType) {
- case 'Array':
- return ((function() {
- var _i, _len;
- arrayResults = [];
- if (value.length === 0) {
- arrayResults.push(queryFromParams(null, "" + prefix + "[]"));
- } else {
- for (_i = 0, _len = value.length; _i < _len; _i++) {
- v = value[_i];
- arrayResults.push(queryFromParams(v, "" + prefix + "[]"));
- }
- }
- return arrayResults;
- })()).join("&");
- case 'Object':
- return ((function() {
- var _results;
- _results = [];
- for (k in value) {
- v = value[k];
- _results.push(queryFromParams(v, prefix ? "" + prefix + "[" + (encodeQueryComponent(k)) + "]" : encodeQueryComponent(k)));
- }
- return _results;
- })()).join("&");
- default:
- if (prefix != null) {
- return "" + prefix + "=" + (encodeQueryComponent(value));
- } else {
- return encodeQueryComponent(value);
- }
- }
- };
-
- URI.encodeComponent = encodeComponent = function(str) {
- if (str != null) {
- return encodeURIComponent(str);
- } else {
- return '';
- }
- };
-
- URI.encodeQueryComponent = encodeQueryComponent = function(str) {
- return encodeComponent(str).replace(r20, '+');
- };
-
- return URI;
-
- })();
-
-}).call(this);
-
-(function() {
- var __hasProp = {}.hasOwnProperty,
- __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
-
- Batman.Request = (function(_super) {
- var dataHasFileUploads;
-
- __extends(Request, _super);
-
- Request.objectToFormData = function(data) {
- var formData, key, pairForList, val, _i, _len, _ref, _ref1;
- pairForList = function(key, object, first) {
- var k, list, v;
- if (first == null) {
- first = false;
- }
- return list = (function() {
- switch (Batman.typeOf(object)) {
- case 'Object':
- list = (function() {
- var _results;
- _results = [];
- for (k in object) {
- v = object[k];
- _results.push(pairForList((first ? k : "" + key + "[" + k + "]"), v));
- }
- return _results;
- })();
- return list.reduce(function(acc, list) {
- return acc.concat(list);
- }, []);
- case 'Array':
- return object.reduce(function(acc, element) {
- return acc.concat(pairForList("" + key + "[]", element));
- }, []);
- default:
- return [[key, object != null ? object : ""]];
- }
- })();
- };
- formData = new Batman.container.FormData();
- _ref = pairForList("", data, true);
- for (_i = 0, _len = _ref.length; _i < _len; _i++) {
- _ref1 = _ref[_i], key = _ref1[0], val = _ref1[1];
- formData.append(key, val);
- }
- return formData;
- };
-
- Request.dataHasFileUploads = dataHasFileUploads = function(data) {
- var k, type, v, _i, _len;
- if ((typeof File !== "undefined" && File !== null) && data instanceof File) {
- return true;
- }
- type = Batman.typeOf(data);
- switch (type) {
- case 'Object':
- for (k in data) {
- v = data[k];
- if (dataHasFileUploads(v)) {
- return true;
- }
- }
- break;
- case 'Array':
- for (_i = 0, _len = data.length; _i < _len; _i++) {
- v = data[_i];
- if (dataHasFileUploads(v)) {
- return true;
- }
- }
- }
- return false;
- };
-
- Request.wrapAccessor('method', function(core) {
- return {
- set: function(k, val) {
- return core.set.call(this, k, val != null ? typeof val.toUpperCase === "function" ? val.toUpperCase() : void 0 : void 0);
- }
- };
- });
-
- Request.prototype.method = 'GET';
-
- Request.prototype.hasFileUploads = function() {
- return dataHasFileUploads(this.data);
- };
-
- Request.prototype.contentType = 'application/x-www-form-urlencoded';
-
- Request.prototype.autosend = true;
-
- function Request(options) {
- var handler, handlers, k, _ref;
- handlers = {};
- for (k in options) {
- handler = options[k];
- if (!(k === 'success' || k === 'error' || k === 'loading' || k === 'loaded')) {
- continue;
- }
- handlers[k] = handler;
- delete options[k];
- }
- Request.__super__.constructor.call(this, options);
- for (k in handlers) {
- handler = handlers[k];
- this.on(k, handler);
- }
- if (((_ref = this.get('url')) != null ? _ref.length : void 0) > 0) {
- if (this.autosend) {
- this.send();
- }
- } else {
- this.observe('url', function(url) {
- if (url != null) {
- return this.send();
- }
- });
- }
- }
-
- Request.prototype.send = function() {
- return Batman.developer.error("Please source a dependency file for a request implementation");
- };
-
- return Request;
-
- })(Batman.Object);
-
-}).call(this);
-
-(function() {
var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
__slice = [].slice;
@@ -9113,20 +9439,36 @@
};
Navigator.prototype.dispatch = function(params) {
- return this.cachedPath = this.app.get('dispatcher').dispatch(params);
+ this.cachedPath = this.app.get('dispatcher').dispatch(params);
+ if (this._lastRedirect) {
+ this.cachedPath = this._lastRedirect;
+ }
+ return this.cachedPath;
};
Navigator.prototype.push = function(params) {
- var path;
+ var path, pathFromParams, _base;
+ pathFromParams = typeof (_base = this.app.get('dispatcher')).pathFromParams === "function" ? _base.pathFromParams(params) : void 0;
+ if (pathFromParams) {
+ this._lastRedirect = pathFromParams;
+ }
path = this.dispatch(params);
- this.pushState(null, '', path);
+ if (!this._lastRedirect || this._lastRedirect === path) {
+ this.pushState(null, '', path);
+ }
return path;
};
Navigator.prototype.replace = function(params) {
- var path;
+ var path, pathFromParams, _base;
+ pathFromParams = typeof (_base = this.app.get('dispatcher')).pathFromParams === "function" ? _base.pathFromParams(params) : void 0;
+ if (pathFromParams) {
+ this._lastRedirect = pathFromParams;
+ }
path = this.dispatch(params);
- this.replaceState(null, '', path);
+ if (!this._lastRedirect || this._lastRedirect === path) {
+ this.replaceState(null, '', path);
+ }
return path;
};
@@ -9173,19 +9515,23 @@
};
PushStateNavigator.prototype.startWatching = function() {
- return Batman.addEventListener(window, 'popstate', this.handleCurrentLocation);
+ return Batman.DOM.addEventListener(window, 'popstate', this.handleCurrentLocation);
};
PushStateNavigator.prototype.stopWatching = function() {
- return Batman.removeEventListener(window, 'popstate', this.handleCurrentLocation);
+ return Batman.DOM.removeEventListener(window, 'popstate', this.handleCurrentLocation);
};
PushStateNavigator.prototype.pushState = function(stateObject, title, path) {
- return window.history.pushState(stateObject, title, this.linkTo(path));
+ if (path !== this.pathFromLocation(window.location)) {
+ return window.history.pushState(stateObject, title, this.linkTo(path));
+ }
};
PushStateNavigator.prototype.replaceState = function(stateObject, title, path) {
- return window.history.replaceState(stateObject, title, this.linkTo(path));
+ if (path !== this.pathFromLocation(window.location)) {
+ return window.history.replaceState(stateObject, title, this.linkTo(path));
+ }
};
PushStateNavigator.prototype.linkTo = function(url) {
@@ -9231,10 +9577,10 @@
if ((typeof window !== "undefined" && window !== null) && 'onhashchange' in window) {
HashbangNavigator.prototype.startWatching = function() {
- return Batman.addEventListener(window, 'hashchange', this.handleCurrentLocation);
+ return Batman.DOM.addEventListener(window, 'hashchange', this.handleCurrentLocation);
};
HashbangNavigator.prototype.stopWatching = function() {
- return Batman.removeEventListener(window, 'hashchange', this.handleCurrentLocation);
+ return Batman.DOM.removeEventListener(window, 'hashchange', this.handleCurrentLocation);
};
} else {
HashbangNavigator.prototype.startWatching = function() {
@@ -9558,7 +9904,7 @@
options = Batman.extend({}, this.baseOptions, options);
options[cardinality] = true;
routeTemplate = this.constructor.ROUTES[cardinality];
- resourceRoot = options.controller;
+ resourceRoot = Batman.helpers.underscore(options.controller);
for (_j = 0, _len = names.length; _j < _len; _j++) {
name = names[_j];
routeOptions = Batman.extend({
@@ -9744,6 +10090,8 @@
App.layout = void 0;
+ App.shouldAllowEvent = {};
+
_ref = Batman.RouteMapBuilder.BUILDER_FUNCTIONS;
_fn = function(name) {
return App[name] = function() {
@@ -9948,21 +10296,62 @@
__extends(PluralAssociation, _super);
- function PluralAssociation() {
- return PluralAssociation.__super__.constructor.apply(this, arguments);
- }
-
PluralAssociation.prototype.proxyClass = Batman.AssociationSet;
PluralAssociation.prototype.isSingular = false;
- PluralAssociation.prototype.setForRecord = Batman.Property.wrapTrackingPrevention(function(record) {
- var id;
- if (id = record.get(this.primaryKey)) {
- return this.setIndex().get(id);
+ function PluralAssociation() {
+ PluralAssociation.__super__.constructor.apply(this, arguments);
+ this._resetSetHashes();
+ }
+
+ PluralAssociation.prototype.setForRecord = function(record) {
+ var childModelSetIndex, indexValue,
+ _this = this;
+ indexValue = this.indexValueForRecord(record);
+ childModelSetIndex = this.setIndex();
+ Batman.Property.withoutTracking(function() {
+ return _this._setsByRecord.getOrSet(record, function() {
+ var existingValueSet, newSet;
+ if (indexValue != null) {
+ existingValueSet = _this._setsByValue.get(indexValue);
+ if (existingValueSet != null) {
+ return existingValueSet;
+ }
+ }
+ newSet = new _this.proxyClass(indexValue, _this);
+ if (indexValue != null) {
+ _this._setsByValue.set(indexValue, newSet);
+ }
+ return newSet;
+ });
+ });
+ if (indexValue != null) {
+ return childModelSetIndex.get(indexValue);
} else {
- return new this.proxyClass(void 0, this);
+ return this._setsByRecord.get(record);
+ }
+ };
+
+ PluralAssociation.prototype.setForKey = Batman.Property.wrapTrackingPrevention(function(indexValue) {
+ var foundSet,
+ _this = this;
+ foundSet = void 0;
+ this._setsByRecord.forEach(function(record, set) {
+ if (foundSet != null) {
+ return;
+ }
+ if (_this.indexValueForRecord(record) === indexValue) {
+ return foundSet = set;
+ }
+ });
+ if (foundSet != null) {
+ foundSet.foreignKeyValue = indexValue;
+ return foundSet;
}
+ return this._setsByValue.getOrSet(indexValue, function() {
+ return new _this.proxyClass(indexValue, _this);
+ });
});
PluralAssociation.prototype.getAccessor = function(self, model, label) {
@@ -9989,11 +10378,30 @@
}
};
+ PluralAssociation.prototype.parentSetIndex = function() {
+ this.parentIndex || (this.parentIndex = this.model.get('loaded').indexedByUnique(this.primaryKey));
+ return this.parentIndex;
+ };
+
PluralAssociation.prototype.setIndex = function() {
this.index || (this.index = new Batman.AssociationSetIndex(this, this[this.indexRelatedModelOn]));
return this.index;
};
+ PluralAssociation.prototype.indexValueForRecord = function(record) {
+ return record.get(this.primaryKey);
+ };
+
+ PluralAssociation.prototype.reset = function() {
+ PluralAssociation.__super__.reset.apply(this, arguments);
+ return this._resetSetHashes();
+ };
+
+ PluralAssociation.prototype._resetSetHashes = function() {
+ this._setsByRecord = new Batman.SimpleHash;
+ return this._setsByValue = new Batman.SimpleHash;
+ };
+
return PluralAssociation;
})(Batman.Association);
@@ -10202,18 +10610,33 @@
SingularAssociation.prototype.isSingular = true;
SingularAssociation.prototype.getAccessor = function(self, model, label) {
- var proxy, recordInAttributes;
+ var parent, proxy, record, recordInAttributes, _ref;
if (recordInAttributes = self.getFromAttributes(this)) {
return recordInAttributes;
}
if (self.getRelatedModel()) {
proxy = this.associationProxy(self);
- Batman.Property.withoutTracking(function() {
- if (!proxy.get('loaded') && self.options.autoload) {
- return proxy.load();
+ record = false;
+ parent = this;
+ if ((_ref = proxy._loadSetter) == null) {
+ proxy._loadSetter = proxy.once('loaded', function(child) {
+ return parent._withoutDirtyTracking(function() {
+ return this.set(self.label, child);
+ });
+ });
+ }
+ if (!Batman.Property.withoutTracking(function() {
+ return proxy.get('loaded');
+ })) {
+ if (self.options.autoload) {
+ Batman.Property.withoutTracking(function() {
+ return proxy.load();
+ });
+ } else {
+ record = proxy.loadFromLocal();
}
- });
- return proxy;
+ }
+ return record || proxy;
}
};
@@ -10275,15 +10698,14 @@
association = this;
return function(data, _, __, ___, parentRecord) {
var record, relatedModel;
+ if (!data) {
+ return;
+ }
relatedModel = association.getRelatedModel();
- record = new relatedModel();
- record._withoutDirtyTracking(function() {
- return this.fromJSON(data);
- });
+ record = relatedModel.createFromJSON(data);
if (association.options.inverseOf) {
record.set(association.options.inverseOf, parentRecord);
}
- record = relatedModel._mapIdentity(record);
return record;
};
};
@@ -10343,11 +10765,7 @@
return function(data, _, __, ___, childRecord) {
var inverse, record, relatedModel;
relatedModel = association.getRelatedModel();
- record = new relatedModel();
- record._withoutDirtyTracking(function() {
- return this.fromJSON(data);
- });
- record = relatedModel._mapIdentity(record);
+ record = relatedModel.createFromJSON(data);
if (association.options.inverseOf) {
if (inverse = association.inverse()) {
if (inverse instanceof Batman.HasManyAssociation) {
@@ -10496,11 +10914,7 @@
var foreignTypeValue, inverse, record, relatedModel;
foreignTypeValue = response[association.foreignTypeKey] || childRecord.get(association.foreignTypeKey);
relatedModel = association.getRelatedModelForType(foreignTypeValue);
- record = new relatedModel();
- record._withoutDirtyTracking(function() {
- return this.fromJSON(data);
- });
- record = relatedModel._mapIdentity(record);
+ record = relatedModel.createFromJSON(data);
if (association.options.inverseOf) {
if (inverse = association.inverseForType(foreignTypeValue)) {
if (inverse instanceof Batman.PolymorphicHasManyAssociation) {
@@ -10531,29 +10945,23 @@
__extends(Validator, _super);
- function Validator() {
- var mixins, options;
- options = arguments[0], mixins = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
- this.options = options;
- Validator.__super__.constructor.apply(this, mixins);
- }
-
- Validator.prototype.validate = function(record) {
- return Batman.developer.error("You must override validate in Batman.Validator subclasses.");
- };
-
- Validator.prototype.format = function(key, messageKey, interpolations) {
- return Batman.t("errors.messages." + messageKey, interpolations);
+ Validator.triggers = function() {
+ var triggers;
+ triggers = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
+ if (this._triggers != null) {
+ return this._triggers.concat(triggers);
+ } else {
+ return this._triggers = triggers;
+ }
};
Validator.options = function() {
var options;
options = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
- Batman.initializeObject(this);
- if (this._batman.options) {
- return this._batman.options.concat(options);
+ if (this._options != null) {
+ return this._options.concat(options);
} else {
- return this._batman.options = options;
+ return this._options = options;
}
};
@@ -10563,7 +10971,10 @@
shouldReturn = false;
for (key in options) {
value = options[key];
- if (~((_ref = this._batman) != null ? (_ref1 = _ref.options) != null ? _ref1.indexOf(key) : void 0 : void 0)) {
+ if (~((_ref = this._options) != null ? _ref.indexOf(key) : void 0)) {
+ results[key] = value;
+ }
+ if (~((_ref1 = this._triggers) != null ? _ref1.indexOf(key) : void 0)) {
results[key] = value;
shouldReturn = true;
}
@@ -10573,6 +10984,27 @@
}
};
+ function Validator() {
+ var mixins, options;
+ options = arguments[0], mixins = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
+ this.options = options;
+ Validator.__super__.constructor.apply(this, mixins);
+ }
+
+ Validator.prototype.validate = function(record) {
+ return Batman.developer.error("You must override validate in Batman.Validator subclasses.");
+ };
+
+ Validator.prototype.format = function(key, messageKey, interpolations) {
+ return Batman.t("errors.messages." + messageKey, interpolations);
+ };
+
+ Validator.prototype.handleBlank = function(value) {
+ if (this.options.allowBlank && !Batman.PresenceValidator.prototype.isPresent(value)) {
+ return true;
+ }
+ };
+
return Validator;
})(Batman.Object);
@@ -10592,7 +11024,13 @@
wrong_length: "must be %{count} characters",
blank: "can't be blank",
not_numeric: "must be a number",
- not_matching: "is not valid"
+ greater_than: "must be greater than %{count}",
+ greater_than_or_equal_to: "must be greater than or equal to %{count}",
+ equal_to: "must be equal to %{count}",
+ less_than: "must be less than %{count}",
+ less_than_or_equal_to: "must be less than or equal to %{count}",
+ not_matching: "is not valid",
+ invalid_association: "is not valid"
}
}
});
@@ -10607,7 +11045,9 @@
__extends(RegExpValidator, _super);
- RegExpValidator.options('regexp', 'pattern');
+ RegExpValidator.triggers('regexp', 'pattern');
+
+ RegExpValidator.options('allowBlank');
function RegExpValidator(options) {
var _ref;
@@ -10618,10 +11058,11 @@
RegExpValidator.prototype.validateEach = function(errors, record, key, callback) {
var value;
value = record.get(key);
- if ((value != null) && value !== '') {
- if (!this.regexp.test(value)) {
- errors.add(key, this.format(key, 'not_matching'));
- }
+ if (this.handleBlank(value)) {
+ return callback();
+ }
+ if (!(value != null) || value === '' || !this.regexp.test(value)) {
+ errors.add(key, this.format(key, 'not_matching'));
}
return callback();
};
@@ -10646,17 +11087,21 @@
return PresenceValidator.__super__.constructor.apply(this, arguments);
}
- PresenceValidator.options('presence');
+ PresenceValidator.triggers('presence');
PresenceValidator.prototype.validateEach = function(errors, record, key, callback) {
var value;
value = record.get(key);
- if (this.options.presence && (!(value != null) || value === '')) {
+ if (!this.isPresent(value)) {
errors.add(key, this.format(key, 'blank'));
}
return callback();
};
+ PresenceValidator.prototype.isPresent = function(value) {
+ return (value != null) && value !== '';
+ };
+
return PresenceValidator;
})(Batman.Validator);
@@ -10677,17 +11122,57 @@
return NumericValidator.__super__.constructor.apply(this, arguments);
}
- NumericValidator.options('numeric');
+ NumericValidator.triggers('numeric', 'greaterThan', 'greaterThanOrEqualTo', 'equalTo', 'lessThan', 'lessThanOrEqualTo');
+
+ NumericValidator.options('allowBlank');
NumericValidator.prototype.validateEach = function(errors, record, key, callback) {
- var value;
+ var options, value;
+ options = this.options;
value = record.get(key);
- if (this.options.numeric && isNaN(parseFloat(value))) {
+ if (this.handleBlank(value)) {
+ return callback();
+ }
+ if (!(value != null) || !(this.isNumeric(value) || this.canCoerceToNumeric(value))) {
errors.add(key, this.format(key, 'not_numeric'));
+ } else {
+ if (options.greaterThan && value <= options.greaterThan) {
+ errors.add(key, this.format(key, 'greater_than', {
+ count: options.greaterThan
+ }));
+ }
+ if (options.greaterThanOrEqualTo && value < options.greaterThanOrEqualTo) {
+ errors.add(key, this.format(key, 'greater_than_or_equal_to', {
+ count: options.greaterThanOrEqualTo
+ }));
+ }
+ if (options.equalTo && value !== options.equalTo) {
+ errors.add(key, this.format(key, 'equal_to', {
+ count: options.equalTo
+ }));
+ }
+ if (options.lessThan && value >= options.lessThan) {
+ errors.add(key, this.format(key, 'less_than', {
+ count: options.lessThan
+ }));
+ }
+ if (options.lessThanOrEqualTo && value > options.lessThanOrEqualTo) {
+ errors.add(key, this.format(key, 'less_than_or_equal_to', {
+ count: options.lessThanOrEqualTo
+ }));
+ }
}
return callback();
};
+ NumericValidator.prototype.isNumeric = function(value) {
+ return !isNaN(parseFloat(value)) && isFinite(value);
+ };
+
+ NumericValidator.prototype.canCoerceToNumeric = function(value) {
+ return (value - 0) == value && value.length > 0;
+ };
+
return NumericValidator;
})(Batman.Validator);
@@ -10704,7 +11189,9 @@
__extends(LengthValidator, _super);
- LengthValidator.options('minLength', 'maxLength', 'length', 'lengthWithin', 'lengthIn');
+ LengthValidator.triggers('minLength', 'maxLength', 'length', 'lengthWithin', 'lengthIn');
+
+ LengthValidator.options('allowBlank');
function LengthValidator(options) {
var range;
@@ -10718,9 +11205,15 @@
}
LengthValidator.prototype.validateEach = function(errors, record, key, callback) {
- var options, value, _ref;
+ var options, value;
options = this.options;
- value = (_ref = record.get(key)) != null ? _ref : [];
+ value = record.get(key);
+ if (value !== '' && this.handleBlank(value)) {
+ return callback();
+ }
+ if (value == null) {
+ value = [];
+ }
if (options.minLength && value.length < options.minLength) {
errors.add(key, this.format(key, 'too_short', {
count: options.minLength
@@ -10751,6 +11244,60 @@
var __hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
+ Batman.AssociatedValidator = (function(_super) {
+
+ __extends(AssociatedValidator, _super);
+
+ function AssociatedValidator() {
+ return AssociatedValidator.__super__.constructor.apply(this, arguments);
+ }
+
+ AssociatedValidator.triggers('associated');
+
+ AssociatedValidator.prototype.validateEach = function(errors, record, key, callback) {
+ var childFinished, count, value,
+ _this = this;
+ value = record.get(key);
+ if (value != null) {
+ if (value instanceof Batman.AssociationProxy) {
+ value = typeof value.get === "function" ? value.get('target') : void 0;
+ }
+ count = 1;
+ childFinished = function(err, childErrors) {
+ if (childErrors.length > 0) {
+ errors.add(key, _this.format(key, 'invalid_association'));
+ }
+ if (--count === 0) {
+ return callback();
+ }
+ };
+ if ((value != null ? value.forEach : void 0) != null) {
+ value.forEach(function(record) {
+ count += 1;
+ return record.validate(childFinished);
+ });
+ } else if ((value != null ? value.validate : void 0) != null) {
+ count += 1;
+ value.validate(childFinished);
+ }
+ return childFinished(null, []);
+ } else {
+ return callback();
+ }
+ };
+
+ return AssociatedValidator;
+
+ })(Batman.Validator);
+
+ Batman.Validators.push(Batman.AssociatedValidator);
+
+}).call(this);
+
+(function() {
+ var __hasProp = {}.hasOwnProperty,
+ __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
+
Batman.ControllerActionFrame = (function(_super) {
__extends(ControllerActionFrame, _super);
@@ -10842,8 +11389,10 @@
return parentNode.removeChild(this.placeholderNode);
}
} else {
- parentNode.insertBefore(this.placeholderNode, this.node);
- return Batman.DOM.removeNode(this.node);
+ if (this.node.parentNode != null) {
+ parentNode.insertBefore(this.placeholderNode, this.node);
+ return Batman.DOM.removeNode(this.node);
+ }
}
};
@@ -11011,7 +11560,7 @@
buntUndefined = function(f) {
return function(value) {
- if (typeof value === 'undefined') {
+ if (value == null) {
return void 0;
} else {
return f.apply(this, arguments);
@@ -11045,8 +11594,11 @@
return lhs || rhs;
},
not: function(value, binding) {
- return !!!value;
+ return !value;
},
+ trim: buntUndefined(function(value, binding) {
+ return value.trim();
+ }),
matches: buntUndefined(function(value, searchFor) {
return value.indexOf(searchFor) !== -1;
}),
@@ -11071,10 +11623,10 @@
}
},
prepend: function(value, string, binding) {
- return string + value;
+ return (string != null ? string : '') + (value != null ? value : '');
},
append: function(value, string, binding) {
- return value + string;
+ return (value != null ? value : '') + (string != null ? string : '');
},
replace: buntUndefined(function(value, searchFor, replaceWith, flags, binding) {
if (!binding) {
@@ -11102,7 +11654,7 @@
count = void 0;
}
}
- if (count) {
+ if (count != null) {
return Batman.helpers.pluralize(count, string, void 0, includeCount);
} else {
return Batman.helpers.pluralize(string);
@@ -11329,10 +11881,6 @@
__extends(ViewStore, _super);
- ViewStore.prefix = 'views';
-
- ViewStore.fetchFromRemote = true;
-
function ViewStore() {
ViewStore.__super__.constructor.apply(this, arguments);
this._viewContents = {};
@@ -11344,7 +11892,7 @@
ViewStore.prototype.fetchView = function(path) {
var _this = this;
return new Batman.Request({
- url: Batman.Navigator.normalizePath(this.constructor.prefix, "" + path + ".html"),
+ url: Batman.Navigator.normalizePath(Batman.config.viewPrefix, "" + path + ".html"),
type: 'html',
success: function(response) {
return _this.set(path, response);
@@ -11371,7 +11919,7 @@
if (contents = this._sourceFromDOM(path)) {
return contents;
}
- if (this.constructor.fetchFromRemote) {
+ if (Batman.config.fetchRemoteViews) {
this.fetchView(path);
} else {
throw new Error("Couldn't find view source for \'" + path + "\'!");
@@ -11446,28 +11994,21 @@
View.store = new Batman.ViewStore();
View.option = function() {
- var keys,
- _this = this;
+ var keys;
keys = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
- keys.forEach(function(key) {
- return _this.accessor(_this.prototype._argumentBindingKey(key), function(bindingKey) {
- var context, keyPath, node, _ref;
- if (!((node = this.get('node')) && (context = this.get('context')))) {
- return;
- }
- keyPath = node.getAttribute(("data-view-" + key).toLowerCase());
- if (keyPath == null) {
- return;
- }
- if ((_ref = this[bindingKey]) != null) {
- _ref.die();
- }
- return this[bindingKey] = new Batman.DOM.ViewArgumentBinding(node, keyPath, context);
- });
- });
- return this.accessor.apply(this, __slice.call(keys).concat([function(key) {
- var _ref;
- return (_ref = this.get(this._argumentBindingKey(key))) != null ? _ref.get('filteredValue') : void 0;
+ return this.accessor.apply(this, __slice.call(keys).concat([{
+ get: function(key) {
+ var _ref;
+ return (_ref = this.get("argumentBindings." + key)) != null ? _ref.get('filteredValue') : void 0;
+ },
+ set: function(key, value) {
+ var _ref;
+ return (_ref = this.get("argumentBindings." + key)) != null ? _ref.set('filteredValue', value) : void 0;
+ },
+ unset: function(key) {
+ var _ref;
+ return (_ref = this.get("argumentBindings." + key)) != null ? _ref.unset('filteredValue') : void 0;
+ }
}]));
};
@@ -11481,6 +12022,25 @@
View.prototype.event('ready').oneShot = true;
+ View.accessor('argumentBindings', function() {
+ var _this = this;
+ return new Batman.TerminalAccessible(function(key) {
+ var bindingKey, context, keyPath, node, _ref;
+ if (!((node = _this.get('node')) && (context = _this.get('context')))) {
+ return;
+ }
+ keyPath = node.getAttribute(("data-view-" + key).toLowerCase());
+ if (keyPath == null) {
+ return;
+ }
+ bindingKey = "_argumentBinding" + key;
+ if ((_ref = _this[bindingKey]) != null) {
+ _ref.die();
+ }
+ return _this[bindingKey] = new Batman.DOM.ViewArgumentBinding(node, keyPath, context);
+ });
+ });
+
View.accessor('html', {
get: function() {
var source;
@@ -11508,7 +12068,7 @@
}
this.node = document.createElement('div');
this._setNodeOwner(this.node);
- Batman.setInnerHTML(this.node, html);
+ Batman.DOM.setInnerHTML(this.node, html);
}
return this.node;
},
@@ -11519,7 +12079,7 @@
this._setNodeOwner(node);
updateHTML = function(html) {
if (html != null) {
- Batman.setInnerHTML(_this.node, html);
+ Batman.DOM.setInnerHTML(_this.node, html);
return _this.forget('html', updateHTML);
}
};
@@ -11630,10 +12190,6 @@
});
};
- View.prototype._argumentBindingKey = function(key) {
- return "_" + key + "ArgumentBinding";
- };
-
View.prototype._setNodeOwner = function(node) {
return Batman._data(node, 'view', this);
};
@@ -11761,7 +12317,7 @@
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
child = _ref[_i];
- _results.push(Batman.removeOrDestroyNode(child));
+ _results.push(Batman.DOM.removeOrDestroyNode(child));
}
return _results;
});
@@ -11782,7 +12338,7 @@
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
child = _ref[_i];
if (!~this.currentVersionNodes.indexOf(child)) {
- _results.push(Batman.removeOrDestroyNode(child));
+ _results.push(Batman.DOM.removeOrDestroyNode(child));
}
}
return _results;
@@ -11790,7 +12346,7 @@
Yield.prototype.append = Yield.queued(function(node) {
this.currentVersionNodes.push(node);
- return Batman.appendChild(this.containerNode, node, true);
+ return Batman.DOM.appendChild(this.containerNode, node, true);
});
Yield.prototype.replace = Yield.queued(function(node) {
diff --git a/javascripts/dashing.coffee b/javascripts/dashing.coffee
index 6d1b5cc..d6d7e22 100644
--- a/javascripts/dashing.coffee
+++ b/javascripts/dashing.coffee
@@ -14,7 +14,7 @@ Batman.Filters.dashize = (str) ->
return str.replace(dashes_rx1, '$1_$2').replace(dashes_rx2, '$1_$2').replace('_', '-').toLowerCase()
Batman.Filters.shortenedNumber = (num) ->
- return if isNaN(num)
+ return num if isNaN(num)
if num >= 1000000000
(num / 1000000000).toFixed(1) + 'B'
else if num >= 1000000