summaryrefslogtreecommitdiff
path: root/javascripts/batman.js
diff options
context:
space:
mode:
Diffstat (limited to 'javascripts/batman.js')
-rw-r--r--javascripts/batman.js11811
1 files changed, 11811 insertions, 0 deletions
diff --git a/javascripts/batman.js b/javascripts/batman.js
new file mode 100644
index 0000000..22c7b3a
--- /dev/null
+++ b/javascripts/batman.js
@@ -0,0 +1,11811 @@
+(function() {
+ var Batman,
+ __slice = [].slice;
+
+ Batman = function() {
+ var mixins;
+ mixins = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
+ 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.Object, mixins, function(){});
+ };
+
+ Batman.version = '0.10.0';
+
+ Batman.config = {
+ pathPrefix: '/',
+ usePushState: false,
+ minificationErrors: true
+ };
+
+ (Batman.container = (function() {
+ return this;
+ })()).Batman = Batman;
+
+ if (typeof define === 'function') {
+ define('batman', [], function() {
+ return Batman;
+ });
+ }
+
+ Batman.exportHelpers = function(onto) {
+ var k, _i, _len, _ref;
+ _ref = ['mixin', 'extend', 'unmixin', 'redirect', 'typeOf', 'redirect', 'setImmediate', 'clearImmediate'];
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ k = _ref[_i];
+ onto["$" + k] = Batman[k];
+ }
+ return onto;
+ };
+
+ Batman.exportGlobals = function() {
+ return Batman.exportHelpers(Batman.container);
+ };
+
+}).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; };
+
+ Batman.Inflector = (function() {
+
+ Inflector.prototype.plural = function(regex, replacement) {
+ return this._plural.unshift([regex, replacement]);
+ };
+
+ Inflector.prototype.singular = function(regex, replacement) {
+ return this._singular.unshift([regex, replacement]);
+ };
+
+ Inflector.prototype.human = function(regex, replacement) {
+ return this._human.unshift([regex, replacement]);
+ };
+
+ Inflector.prototype.uncountable = function() {
+ var strings;
+ strings = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
+ return this._uncountable = this._uncountable.concat(strings.map(function(x) {
+ return new RegExp("" + x + "$", 'i');
+ }));
+ };
+
+ Inflector.prototype.irregular = function(singular, plural) {
+ if (singular.charAt(0) === plural.charAt(0)) {
+ this.plural(new RegExp("(" + (singular.charAt(0)) + ")" + (singular.slice(1)) + "$", "i"), "$1" + plural.slice(1));
+ this.plural(new RegExp("(" + (singular.charAt(0)) + ")" + (plural.slice(1)) + "$", "i"), "$1" + plural.slice(1));
+ return this.singular(new RegExp("(" + (plural.charAt(0)) + ")" + (plural.slice(1)) + "$", "i"), "$1" + singular.slice(1));
+ } else {
+ this.plural(new RegExp("" + singular + "$", 'i'), plural);
+ this.plural(new RegExp("" + plural + "$", 'i'), plural);
+ return this.singular(new RegExp("" + plural + "$", 'i'), singular);
+ }
+ };
+
+ function Inflector() {
+ this._plural = [];
+ this._singular = [];
+ this._uncountable = [];
+ this._human = [];
+ }
+
+ Inflector.prototype.ordinalize = function(number) {
+ var absNumber, _ref;
+ absNumber = Math.abs(parseInt(number));
+ if (_ref = absNumber % 100, __indexOf.call([11, 12, 13], _ref) >= 0) {
+ return number + "th";
+ } else {
+ switch (absNumber % 10) {
+ case 1:
+ return number + "st";
+ case 2:
+ return number + "nd";
+ case 3:
+ return number + "rd";
+ default:
+ return number + "th";
+ }
+ }
+ };
+
+ Inflector.prototype.pluralize = function(word) {
+ var regex, replace_string, uncountableRegex, _i, _j, _len, _len1, _ref, _ref1, _ref2;
+ _ref = this._uncountable;
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ uncountableRegex = _ref[_i];
+ if (uncountableRegex.test(word)) {
+ return word;
+ }
+ }
+ _ref1 = this._plural;
+ for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
+ _ref2 = _ref1[_j], regex = _ref2[0], replace_string = _ref2[1];
+ if (regex.test(word)) {
+ return word.replace(regex, replace_string);
+ }
+ }
+ return word;
+ };
+
+ Inflector.prototype.singularize = function(word) {
+ var regex, replace_string, uncountableRegex, _i, _j, _len, _len1, _ref, _ref1, _ref2;
+ _ref = this._uncountable;
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ uncountableRegex = _ref[_i];
+ if (uncountableRegex.test(word)) {
+ return word;
+ }
+ }
+ _ref1 = this._singular;
+ for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
+ _ref2 = _ref1[_j], regex = _ref2[0], replace_string = _ref2[1];
+ if (regex.test(word)) {
+ return word.replace(regex, replace_string);
+ }
+ }
+ return word;
+ };
+
+ Inflector.prototype.humanize = function(word) {
+ var regex, replace_string, _i, _len, _ref, _ref1;
+ _ref = this._human;
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ _ref1 = _ref[_i], regex = _ref1[0], replace_string = _ref1[1];
+ if (regex.test(word)) {
+ return word.replace(regex, replace_string);
+ }
+ }
+ return word;
+ };
+
+ return Inflector;
+
+ })();
+
+}).call(this);
+
+(function() {
+ var Inflector, camelize_rx, capitalize_rx, humanize_rx1, humanize_rx2, humanize_rx3, underscore_rx1, underscore_rx2;
+
+ camelize_rx = /(?:^|_|\-)(.)/g;
+
+ capitalize_rx = /(^|\s)([a-z])/g;
+
+ underscore_rx1 = /([A-Z]+)([A-Z][a-z])/g;
+
+ underscore_rx2 = /([a-z\d])([A-Z])/g;
+
+ humanize_rx1 = /_id$/;
+
+ humanize_rx2 = /_|-/g;
+
+ humanize_rx3 = /^\w/g;
+
+ Batman.helpers = {
+ ordinalize: function() {
+ return Batman.helpers.inflector.ordinalize.apply(Batman.helpers.inflector, arguments);
+ },
+ singularize: function() {
+ return Batman.helpers.inflector.singularize.apply(Batman.helpers.inflector, arguments);
+ },
+ pluralize: function(count, singular, plural, includeCount) {
+ var result;
+ if (includeCount == null) {
+ includeCount = true;
+ }
+ if (arguments.length < 2) {
+ return Batman.helpers.inflector.pluralize(count);
+ } else {
+ result = +count === 1 ? singular : plural || Batman.helpers.inflector.pluralize(singular);
+ if (includeCount) {
+ result = ("" + (count || 0) + " ") + result;
+ }
+ return result;
+ }
+ },
+ camelize: function(string, firstLetterLower) {
+ string = string.replace(camelize_rx, function(str, p1) {
+ return p1.toUpperCase();
+ });
+ if (firstLetterLower) {
+ return string.substr(0, 1).toLowerCase() + string.substr(1);
+ } else {
+ return string;
+ }
+ },
+ underscore: function(string) {
+ return string.replace(underscore_rx1, '$1_$2').replace(underscore_rx2, '$1_$2').replace('-', '_').toLowerCase();
+ },
+ capitalize: function(string) {
+ return string.replace(capitalize_rx, function(m, p1, p2) {
+ return p1 + p2.toUpperCase();
+ });
+ },
+ trim: function(string) {
+ if (string) {
+ return string.trim();
+ } else {
+ return "";
+ }
+ },
+ interpolate: function(stringOrObject, keys) {
+ var key, string, value;
+ if (typeof stringOrObject === 'object') {
+ string = stringOrObject[keys.count];
+ if (!string) {
+ string = stringOrObject['other'];
+ }
+ } else {
+ string = stringOrObject;
+ }
+ for (key in keys) {
+ value = keys[key];
+ string = string.replace(new RegExp("%\\{" + key + "\\}", "g"), value);
+ }
+ return string;
+ },
+ humanize: function(string) {
+ string = Batman.helpers.underscore(string);
+ string = Batman.helpers.inflector.humanize(string);
+ return string.replace(humanize_rx1, '').replace(humanize_rx2, ' ').replace(humanize_rx3, function(match) {
+ return match.toUpperCase();
+ });
+ }
+ };
+
+ Inflector = new Batman.Inflector;
+
+ Batman.helpers.inflector = Inflector;
+
+ Inflector.plural(/$/, 's');
+
+ Inflector.plural(/s$/i, 's');
+
+ Inflector.plural(/(ax|test)is$/i, '$1es');
+
+ Inflector.plural(/(octop|vir)us$/i, '$1i');
+
+ Inflector.plural(/(octop|vir)i$/i, '$1i');
+
+ Inflector.plural(/(alias|status)$/i, '$1es');
+
+ Inflector.plural(/(bu)s$/i, '$1ses');
+
+ Inflector.plural(/(buffal|tomat)o$/i, '$1oes');
+
+ Inflector.plural(/([ti])um$/i, '$1a');
+
+ Inflector.plural(/([ti])a$/i, '$1a');
+
+ Inflector.plural(/sis$/i, 'ses');
+
+ Inflector.plural(/(?:([^f])fe|([lr])f)$/i, '$1$2ves');
+
+ Inflector.plural(/(hive)$/i, '$1s');
+
+ Inflector.plural(/([^aeiouy]|qu)y$/i, '$1ies');
+
+ Inflector.plural(/(x|ch|ss|sh)$/i, '$1es');
+
+ Inflector.plural(/(matr|vert|ind)(?:ix|ex)$/i, '$1ices');
+
+ Inflector.plural(/([m|l])ouse$/i, '$1ice');
+
+ Inflector.plural(/([m|l])ice$/i, '$1ice');
+
+ Inflector.plural(/^(ox)$/i, '$1en');
+
+ Inflector.plural(/^(oxen)$/i, '$1');
+
+ Inflector.plural(/(quiz)$/i, '$1zes');
+
+ Inflector.singular(/s$/i, '');
+
+ Inflector.singular(/(n)ews$/i, '$1ews');
+
+ Inflector.singular(/([ti])a$/i, '$1um');
+
+ Inflector.singular(/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i, '$1$2sis');
+
+ Inflector.singular(/(^analy)ses$/i, '$1sis');
+
+ Inflector.singular(/([^f])ves$/i, '$1fe');
+
+ Inflector.singular(/(hive)s$/i, '$1');
+
+ Inflector.singular(/(tive)s$/i, '$1');
+
+ Inflector.singular(/([lr])ves$/i, '$1f');
+
+ Inflector.singular(/([^aeiouy]|qu)ies$/i, '$1y');
+
+ Inflector.singular(/(s)eries$/i, '$1eries');
+
+ Inflector.singular(/(m)ovies$/i, '$1ovie');
+
+ Inflector.singular(/(x|ch|ss|sh)es$/i, '$1');
+
+ Inflector.singular(/([m|l])ice$/i, '$1ouse');
+
+ Inflector.singular(/(bus)es$/i, '$1');
+
+ Inflector.singular(/(o)es$/i, '$1');
+
+ Inflector.singular(/(shoe)s$/i, '$1');
+
+ Inflector.singular(/(cris|ax|test)es$/i, '$1is');
+
+ Inflector.singular(/(octop|vir)i$/i, '$1us');
+
+ Inflector.singular(/(alias|status)es$/i, '$1');
+
+ Inflector.singular(/^(ox)en/i, '$1');
+
+ Inflector.singular(/(vert|ind)ices$/i, '$1ex');
+
+ Inflector.singular(/(matr)ices$/i, '$1ix');
+
+ Inflector.singular(/(quiz)zes$/i, '$1');
+
+ Inflector.singular(/(database)s$/i, '$1');
+
+ Inflector.irregular('person', 'people');
+
+ Inflector.irregular('man', 'men');
+
+ Inflector.irregular('child', 'children');
+
+ Inflector.irregular('sex', 'sexes');
+
+ Inflector.irregular('move', 'moves');
+
+ Inflector.irregular('cow', 'kine');
+
+ Inflector.irregular('zombie', 'zombies');
+
+ Inflector.uncountable('equipment', 'information', 'rice', 'money', 'species', 'series', 'fish', 'sheep', 'jeans');
+
+}).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 = {
+ suppressed: false,
+ DevelopmentError: (function() {
+ var DevelopmentError;
+ DevelopmentError = function(message) {
+ this.message = message;
+ return this.name = "DevelopmentError";
+ };
+ DevelopmentError.prototype = Error.prototype;
+ return DevelopmentError;
+ })(),
+ _ie_console: function(f, args) {
+ var arg, _i, _len, _results;
+ if (args.length !== 1) {
+ if (typeof console !== "undefined" && console !== null) {
+ console[f]("..." + f + " of " + args.length + " items...");
+ }
+ }
+ _results = [];
+ for (_i = 0, _len = args.length; _i < _len; _i++) {
+ arg = args[_i];
+ _results.push(typeof console !== "undefined" && console !== null ? console[f](arg) : void 0);
+ }
+ return _results;
+ },
+ suppress: function(f) {
+ developer.suppressed = true;
+ if (f) {
+ f();
+ return developer.suppressed = false;
+ }
+ },
+ unsuppress: function() {
+ return developer.suppressed = false;
+ },
+ log: function() {
+ if (developer.suppressed || !((typeof console !== "undefined" && console !== null ? console.log : void 0) != null)) {
+ return;
+ }
+ if (console.log.apply) {
+ return console.log.apply(console, arguments);
+ } else {
+ return developer._ie_console("log", arguments);
+ }
+ },
+ warn: function() {
+ if (developer.suppressed || !((typeof console !== "undefined" && console !== null ? console.warn : void 0) != null)) {
+ return;
+ }
+ if (console.warn.apply) {
+ return console.warn.apply(console, arguments);
+ } else {
+ return developer._ie_console("warn", arguments);
+ }
+ },
+ error: function(message) {
+ throw new developer.DevelopmentError(message);
+ },
+ assert: function(result, message) {
+ if (!result) {
+ return developer.error(message);
+ }
+ },
+ "do": function(f) {
+ if (!developer.suppressed) {
+ return f();
+ }
+ },
+ addFilters: function() {
+ return Batman.extend(Batman.Filters, {
+ log: function(value, key) {
+ if (typeof console !== "undefined" && console !== null) {
+ if (typeof console.log === "function") {
+ console.log(arguments);
+ }
+ }
+ return value;
+ },
+ logStack: function(value) {
+ if (typeof console !== "undefined" && console !== null) {
+ if (typeof console.log === "function") {
+ console.log(developer.currentFilterStack);
+ }
+ }
+ return value;
+ }
+ });
+ }
+ };
+
+ developer = Batman.developer;
+
+ Batman.developer.assert((function() {}).bind, "Error! Batman needs Function.bind to work! Please shim it using something like es5-shim or augmentjs!");
+
+}).call(this);
+
+(function() {
+ var _Batman;
+
+ Batman._Batman = _Batman = (function() {
+
+ function _Batman(object) {
+ this.object = object;
+ }
+
+ _Batman.prototype.check = function(object) {
+ if (object !== this.object) {
+ object._batman = new Batman._Batman(object);
+ return false;
+ }
+ return true;
+ };
+
+ _Batman.prototype.get = function(key) {
+ var reduction, results;
+ results = this.getAll(key);
+ switch (results.length) {
+ case 0:
+ return void 0;
+ case 1:
+ return results[0];
+ default:
+ reduction = results[0].concat != null ? function(a, b) {
+ return a.concat(b);
+ } : results[0].merge != null ? function(a, b) {
+ return a.merge(b);
+ } : results.every(function(x) {
+ return typeof x === 'object';
+ }) ? (results.unshift({}), function(a, b) {
+ return Batman.extend(a, b);
+ }) : void 0;
+ if (reduction) {
+ return results.reduceRight(reduction);
+ } else {
+ return results;
+ }
+ }
+ };
+
+ _Batman.prototype.getFirst = function(key) {
+ var results;
+ results = this.getAll(key);
+ return results[0];
+ };
+
+ _Batman.prototype.getAll = function(keyOrGetter) {
+ var getter, results, val;
+ if (typeof keyOrGetter === 'function') {
+ getter = keyOrGetter;
+ } else {
+ getter = function(ancestor) {
+ var _ref;
+ return (_ref = ancestor._batman) != null ? _ref[keyOrGetter] : void 0;
+ };
+ }
+ results = this.ancestors(getter);
+ if (val = getter(this.object)) {
+ results.unshift(val);
+ }
+ return results;
+ };
+
+ _Batman.prototype.ancestors = function(getter) {
+ var isClass, parent, proto, results, val, _ref, _ref1;
+ if (getter == null) {
+ getter = function(x) {
+ return x;
+ };
+ }
+ results = [];
+ isClass = !!this.object.prototype;
+ parent = isClass ? (_ref = this.object.__super__) != null ? _ref.constructor : void 0 : (proto = Object.getPrototypeOf(this.object)) === this.object ? this.object.constructor.__super__ : proto;
+ if (parent != null) {
+ if ((_ref1 = parent._batman) != null) {
+ _ref1.check(parent);
+ }
+ val = getter(parent);
+ if (val != null) {
+ results.push(val);
+ }
+ if (parent._batman != null) {
+ results = results.concat(parent._batman.ancestors(getter));
+ }
+ }
+ return results;
+ };
+
+ _Batman.prototype.set = function(key, value) {
+ return this[key] = value;
+ };
+
+ return _Batman;
+
+ })();
+
+}).call(this);
+
+(function() {
+
+ Batman.Event = (function() {
+
+ Event.forBaseAndKey = function(base, key) {
+ if (base.isEventEmitter) {
+ return base.event(key);
+ } else {
+ return new Batman.Event(base, key);
+ }
+ };
+
+ function Event(base, key) {
+ this.base = base;
+ this.key = key;
+ this.handlers = [];
+ this._preventCount = 0;
+ }
+
+ Event.prototype.isEvent = true;
+
+ Event.prototype.isEqual = function(other) {
+ return this.constructor === other.constructor && this.base === other.base && this.key === other.key;
+ };
+
+ Event.prototype.hashKey = function() {
+ var key;
+ this.hashKey = function() {
+ return key;
+ };
+ return key = "<Batman.Event base: " + (Batman.Hash.prototype.hashKeyFor(this.base)) + ", key: \"" + (Batman.Hash.prototype.hashKeyFor(this.key)) + "\">";
+ };
+
+ Event.prototype.addHandler = function(handler) {
+ if (this.handlers.indexOf(handler) === -1) {
+ this.handlers.push(handler);
+ }
+ if (this.oneShot) {
+ this.autofireHandler(handler);
+ }
+ return this;
+ };
+
+ Event.prototype.removeHandler = function(handler) {
+ var index;
+ if ((index = this.handlers.indexOf(handler)) !== -1) {
+ this.handlers.splice(index, 1);
+ }
+ return this;
+ };
+
+ Event.prototype.eachHandler = function(iterator) {
+ var key, _ref, _ref1;
+ this.handlers.slice().forEach(iterator);
+ if ((_ref = this.base) != null ? _ref.isEventEmitter : void 0) {
+ key = this.key;
+ return (_ref1 = this.base._batman) != null ? _ref1.ancestors(function(ancestor) {
+ var handlers, _ref2, _ref3;
+ if (ancestor.isEventEmitter && ((_ref2 = ancestor._batman) != null ? (_ref3 = _ref2.events) != null ? _ref3.hasOwnProperty(key) : void 0 : void 0)) {
+ handlers = ancestor.event(key).handlers;
+ return handlers.slice().forEach(iterator);
+ }
+ }) : void 0;
+ }
+ };
+
+ Event.prototype.clearHandlers = function() {
+ return this.handlers = [];
+ };
+
+ Event.prototype.handlerContext = function() {
+ return this.base;
+ };
+
+ Event.prototype.prevent = function() {
+ return ++this._preventCount;
+ };
+
+ Event.prototype.allow = function() {
+ if (this._preventCount) {
+ --this._preventCount;
+ }
+ return this._preventCount;
+ };
+
+ Event.prototype.isPrevented = function() {
+ return this._preventCount > 0;
+ };
+
+ Event.prototype.autofireHandler = function(handler) {
+ if (this._oneShotFired && (this._oneShotArgs != null)) {
+ return handler.apply(this.handlerContext(), this._oneShotArgs);
+ }
+ };
+
+ Event.prototype.resetOneShot = function() {
+ this._oneShotFired = false;
+ return this._oneShotArgs = null;
+ };
+
+ Event.prototype.fire = function() {
+ var args, context;
+ if (this.isPrevented() || this._oneShotFired) {
+ return false;
+ }
+ context = this.handlerContext();
+ args = arguments;
+ if (this.oneShot) {
+ this._oneShotFired = true;
+ this._oneShotArgs = arguments;
+ }
+ return this.eachHandler(function(handler) {
+ return handler.apply(context, args);
+ });
+ };
+
+ Event.prototype.allowAndFire = function() {
+ this.allow();
+ return this.fire.apply(this, arguments);
+ };
+
+ return Event;
+
+ })();
+
+}).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.PropertyEvent = (function(_super) {
+
+ __extends(PropertyEvent, _super);
+
+ function PropertyEvent() {
+ return PropertyEvent.__super__.constructor.apply(this, arguments);
+ }
+
+ PropertyEvent.prototype.eachHandler = function(iterator) {
+ return this.base.eachObserver(iterator);
+ };
+
+ PropertyEvent.prototype.handlerContext = function() {
+ return this.base.base;
+ };
+
+ return PropertyEvent;
+
+ })(Batman.Event);
+
+}).call(this);
+
+(function() {
+ var __slice = [].slice;
+
+ Batman.EventEmitter = {
+ isEventEmitter: true,
+ hasEvent: function(key) {
+ var _ref, _ref1;
+ return (_ref = this._batman) != null ? typeof _ref.get === "function" ? (_ref1 = _ref.get('events')) != null ? _ref1.hasOwnProperty(key) : void 0 : void 0 : void 0;
+ },
+ event: function(key) {
+ var eventClass, events, existingEvent, newEvent, _base;
+ Batman.initializeObject(this);
+ eventClass = this.eventClass || Batman.Event;
+ events = (_base = this._batman).events || (_base.events = {});
+ if (events.hasOwnProperty(key)) {
+ return existingEvent = events[key];
+ } else {
+ this._batman.ancestors(function(ancestor) {
+ var _ref, _ref1;
+ return existingEvent || (existingEvent = (_ref = ancestor._batman) != null ? (_ref1 = _ref.events) != null ? _ref1[key] : void 0 : void 0);
+ });
+ newEvent = events[key] = new eventClass(this, key);
+ newEvent.oneShot = existingEvent != null ? existingEvent.oneShot : void 0;
+ return newEvent;
+ }
+ },
+ on: function(key, handler) {
+ return this.event(key).addHandler(handler);
+ },
+ once: function(key, originalHandler) {
+ var event, handler;
+ event = this.event(key);
+ handler = function() {
+ originalHandler.apply(this, arguments);
+ return event.removeHandler(handler);
+ };
+ return event.addHandler(handler);
+ },
+ registerAsMutableSource: function() {
+ return Batman.Property.registerSource(this);
+ },
+ mutation: function(wrappedFunction) {
+ return function() {
+ var result;
+ result = wrappedFunction.apply(this, arguments);
+ this.event('change').fire(this, this);
+ return result;
+ };
+ },
+ prevent: function(key) {
+ this.event(key).prevent();
+ return this;
+ },
+ allow: function(key) {
+ this.event(key).allow();
+ return this;
+ },
+ isPrevented: function(key) {
+ return this.event(key).isPrevented();
+ },
+ fire: function() {
+ var args, key, _ref;
+ key = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
+ return (_ref = this.event(key)).fire.apply(_ref, args);
+ },
+ allowAndFire: function() {
+ var args, key, _ref;
+ key = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
+ return (_ref = this.event(key)).allowAndFire.apply(_ref, args);
+ }
+ };
+
+}).call(this);
+
+(function() {
+ var __slice = [].slice;
+
+ Batman.Enumerable = {
+ isEnumerable: true,
+ map: function(f, ctx) {
+ var r;
+ if (ctx == null) {
+ ctx = Batman.container;
+ }
+ r = [];
+ this.forEach(function() {
+ return r.push(f.apply(ctx, arguments));
+ });
+ return r;
+ },
+ mapToProperty: function(key) {
+ var r;
+ r = [];
+ this.forEach(function(item) {
+ return r.push(item.get(key));
+ });
+ return r;
+ },
+ every: function(f, ctx) {
+ var r;
+ if (ctx == null) {
+ ctx = Batman.container;
+ }
+ r = true;
+ this.forEach(function() {
+ return r = r && f.apply(ctx, arguments);
+ });
+ return r;
+ },
+ some: function(f, ctx) {
+ var r;
+ if (ctx == null) {
+ ctx = Batman.container;
+ }
+ r = false;
+ this.forEach(function() {
+ return r = r || f.apply(ctx, arguments);
+ });
+ return r;
+ },
+ reduce: function(f, r) {
+ var count, self;
+ count = 0;
+ self = this;
+ this.forEach(function() {
+ if (r != null) {
+ return r = f.apply(null, [r].concat(__slice.call(arguments), [count], [self]));
+ } else {
+ return r = arguments[0];
+ }
+ });
+ return r;
+ },
+ filter: function(f) {
+ var r, wrap;
+ r = new this.constructor;
+ if (r.add) {
+ wrap = function(r, e) {
+ if (f(e)) {
+ r.add(e);
+ }
+ return r;
+ };
+ } else if (r.set) {
+ wrap = function(r, k, v) {
+ if (f(k, v)) {
+ r.set(k, v);
+ }
+ return r;
+ };
+ } else {
+ if (!r.push) {
+ r = [];
+ }
+ wrap = function(r, e) {
+ if (f(e)) {
+ r.push(e);
+ }
+ return r;
+ };
+ }
+ return this.reduce(wrap, r);
+ },
+ inGroupsOf: function(n) {
+ var current, i, r;
+ r = [];
+ current = false;
+ i = 0;
+ this.forEach(function(x) {
+ if (i++ % n === 0) {
+ current = [];
+ r.push(current);
+ }
+ return current.push(x);
+ });
+ return r;
+ }
+ };
+
+}).call(this);
+
+(function() {
+ var __slice = [].slice;
+
+ Batman.SimpleHash = (function() {
+
+ function SimpleHash(obj) {
+ this._storage = {};
+ this.length = 0;
+ if (obj != null) {
+ this.update(obj);
+ }
+ }
+
+ Batman.extend(SimpleHash.prototype, Batman.Enumerable);
+
+ SimpleHash.prototype.propertyClass = Batman.Property;
+
+ SimpleHash.prototype.hasKey = function(key) {
+ var pair, pairs, _i, _len;
+ if (this.objectKey(key)) {
+ if (!this._objectStorage) {
+ return false;
+ }
+ if (pairs = this._objectStorage[this.hashKeyFor(key)]) {
+ for (_i = 0, _len = pairs.length; _i < _len; _i++) {
+ pair = pairs[_i];
+ if (this.equality(pair[0], key)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ } else {
+ key = this.prefixedKey(key);
+ return this._storage.hasOwnProperty(key);
+ }
+ };
+
+ SimpleHash.prototype.get = function(key) {
+ var pair, pairs, _i, _len;
+ if (this.objectKey(key)) {
+ if (!this._objectStorage) {
+ return void 0;
+ }
+ if (pairs = this._objectStorage[this.hashKeyFor(key)]) {
+ for (_i = 0, _len = pairs.length; _i < _len; _i++) {
+ pair = pairs[_i];
+ if (this.equality(pair[0], key)) {
+ return pair[1];
+ }
+ }
+ }
+ } else {
+ return this._storage[this.prefixedKey(key)];
+ }
+ };
+
+ SimpleHash.prototype.set = function(key, val) {
+ var pair, pairs, _base, _i, _len, _name;
+ if (this.objectKey(key)) {
+ this._objectStorage || (this._objectStorage = {});
+ pairs = (_base = this._objectStorage)[_name = this.hashKeyFor(key)] || (_base[_name] = []);
+ for (_i = 0, _len = pairs.length; _i < _len; _i++) {
+ pair = pairs[_i];
+ if (this.equality(pair[0], key)) {
+ return pair[1] = val;
+ }
+ }
+ this.length++;
+ pairs.push([key, val]);
+ return val;
+ } else {
+ key = this.prefixedKey(key);
+ if (this._storage[key] == null) {
+ this.length++;
+ }
+ return this._storage[key] = val;
+ }
+ };
+
+ SimpleHash.prototype.unset = function(key) {
+ var hashKey, index, obj, pair, pairs, val, value, _i, _len, _ref;
+ if (this.objectKey(key)) {
+ if (!this._objectStorage) {
+ return void 0;
+ }
+ hashKey = this.hashKeyFor(key);
+ if (pairs = this._objectStorage[hashKey]) {
+ for (index = _i = 0, _len = pairs.length; _i < _len; index = ++_i) {
+ _ref = pairs[index], obj = _ref[0], value = _ref[1];
+ if (this.equality(obj, key)) {
+ pair = pairs.splice(index, 1);
+ if (!pairs.length) {
+ delete this._objectStorage[hashKey];
+ }
+ this.length--;
+ return pair[0][1];
+ }
+ }
+ }
+ } else {
+ key = this.prefixedKey(key);
+ val = this._storage[key];
+ if (this._storage[key] != null) {
+ this.length--;
+ delete this._storage[key];
+ }
+ return val;
+ }
+ };
+
+ SimpleHash.prototype.getOrSet = function(key, valueFunction) {
+ var currentValue;
+ currentValue = this.get(key);
+ if (!currentValue) {
+ currentValue = valueFunction();
+ this.set(key, currentValue);
+ }
+ return currentValue;
+ };
+
+ SimpleHash.prototype.prefixedKey = function(key) {
+ return "_" + key;
+ };
+
+ SimpleHash.prototype.unprefixedKey = function(key) {
+ return key.slice(1);
+ };
+
+ SimpleHash.prototype.hashKeyFor = function(obj) {
+ return (obj != null ? typeof obj.hashKey === "function" ? obj.hashKey() : void 0 : void 0) || obj;
+ };
+
+ SimpleHash.prototype.equality = function(lhs, rhs) {
+ if (lhs === rhs) {
+ return true;
+ }
+ if (lhs !== lhs && rhs !== rhs) {
+ return true;
+ }
+ if ((lhs != null ? typeof lhs.isEqual === "function" ? lhs.isEqual(rhs) : void 0 : void 0) && (rhs != null ? typeof rhs.isEqual === "function" ? rhs.isEqual(lhs) : void 0 : void 0)) {
+ return true;
+ }
+ return false;
+ };
+
+ SimpleHash.prototype.objectKey = function(key) {
+ return typeof key !== 'string';
+ };
+
+ SimpleHash.prototype.forEach = function(iterator, ctx) {
+ var key, obj, results, value, values, _i, _len, _ref, _ref1, _ref2, _ref3;
+ results = [];
+ if (this._objectStorage) {
+ _ref = this._objectStorage;
+ for (key in _ref) {
+ values = _ref[key];
+ _ref1 = values.slice();
+ for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
+ _ref2 = _ref1[_i], obj = _ref2[0], value = _ref2[1];
+ results.push(iterator.call(ctx, obj, value, this));
+ }
+ }
+ }
+ _ref3 = this._storage;
+ for (key in _ref3) {
+ value = _ref3[key];
+ results.push(iterator.call(ctx, this.unprefixedKey(key), value, this));
+ }
+ return results;
+ };
+
+ SimpleHash.prototype.keys = function() {
+ var result;
+ result = [];
+ Batman.SimpleHash.prototype.forEach.call(this, function(key) {
+ return result.push(key);
+ });
+ return result;
+ };
+
+ SimpleHash.prototype.toArray = SimpleHash.prototype.keys;
+
+ SimpleHash.prototype.clear = function() {
+ this._storage = {};
+ delete this._objectStorage;
+ return this.length = 0;
+ };
+
+ SimpleHash.prototype.isEmpty = function() {
+ return this.length === 0;
+ };
+
+ SimpleHash.prototype.merge = function() {
+ var hash, merged, others, _i, _len;
+ others = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
+ merged = new this.constructor;
+ others.unshift(this);
+ for (_i = 0, _len = others.length; _i < _len; _i++) {
+ hash = others[_i];
+ hash.forEach(function(obj, value) {
+ return merged.set(obj, value);
+ });
+ }
+ return merged;
+ };
+
+ SimpleHash.prototype.update = function(object) {
+ var k, v, _results;
+ _results = [];
+ for (k in object) {
+ v = object[k];
+ _results.push(this.set(k, v));
+ }
+ return _results;
+ };
+
+ SimpleHash.prototype.replace = function(object) {
+ var _this = this;
+ this.forEach(function(key, value) {
+ if (!(key in object)) {
+ return _this.unset(key);
+ }
+ });
+ return this.update(object);
+ };
+
+ SimpleHash.prototype.toObject = function() {
+ var key, obj, pair, value, _ref, _ref1;
+ obj = {};
+ _ref = this._storage;
+ for (key in _ref) {
+ value = _ref[key];
+ obj[this.unprefixedKey(key)] = value;
+ }
+ if (this._objectStorage) {
+ _ref1 = this._objectStorage;
+ for (key in _ref1) {
+ pair = _ref1[key];
+ obj[key] = pair[0][1];
+ }
+ }
+ return obj;
+ };
+
+ SimpleHash.prototype.toJSON = SimpleHash.prototype.toObject;
+
+ return SimpleHash;
+
+ })();
+
+}).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.AssociationCurator = (function(_super) {
+
+ __extends(AssociationCurator, _super);
+
+ AssociationCurator.availableAssociations = ['belongsTo', 'hasOne', 'hasMany'];
+
+ function AssociationCurator(model) {
+ this.model = model;
+ AssociationCurator.__super__.constructor.call(this);
+ this._byTypeStorage = new Batman.SimpleHash;
+ }
+
+ AssociationCurator.prototype.add = function(association) {
+ var associationTypeSet;
+ this.set(association.label, association);
+ if (!(associationTypeSet = this._byTypeStorage.get(association.associationType))) {
+ associationTypeSet = new Batman.SimpleSet;
+ this._byTypeStorage.set(association.associationType, associationTypeSet);
+ }
+ return associationTypeSet.add(association);
+ };
+
+ AssociationCurator.prototype.getByType = function(type) {
+ return this._byTypeStorage.get(type);
+ };
+
+ AssociationCurator.prototype.getByLabel = function(label) {
+ return this.get(label);
+ };
+
+ AssociationCurator.prototype.reset = function() {
+ this.forEach(function(label, association) {
+ return association.reset();
+ });
+ return true;
+ };
+
+ AssociationCurator.prototype.merge = function() {
+ var others, result;
+ others = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
+ result = AssociationCurator.__super__.merge.apply(this, arguments);
+ result._byTypeStorage = this._byTypeStorage.merge(others.map(function(other) {
+ return other._byTypeStorage;
+ }));
+ return result;
+ };
+
+ AssociationCurator.prototype._markDirtyAttribute = function(key, oldValue) {
+ var _ref;
+ if ((_ref = this.lifecycle.get('state')) !== 'loading' && _ref !== 'creating' && _ref !== 'saving' && _ref !== 'saved') {
+ if (this.lifecycle.startTransition('set')) {
+ return this.dirtyKeys.set(key, oldValue);
+ } else {
+ throw new Batman.StateMachine.InvalidTransitionError("Can't set while in state " + (this.lifecycle.get('state')));
+ }
+ }
+ };
+
+ return AssociationCurator;
+
+ })(Batman.SimpleHash);
+
+}).call(this);
+
+(function() {
+ var __slice = [].slice;
+
+ Batman.SimpleSet = (function() {
+
+ function SimpleSet() {
+ this._storage = [];
+ this.length = 0;
+ if (arguments.length > 0) {
+ this.add.apply(this, arguments);
+ }
+ }
+
+ Batman.extend(SimpleSet.prototype, Batman.Enumerable);
+
+ SimpleSet.prototype.has = function(item) {
+ return !!(~this._indexOfItem(item));
+ };
+
+ SimpleSet.prototype.add = function() {
+ var addedItems, item, items, _i, _len;
+ items = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
+ addedItems = [];
+ for (_i = 0, _len = items.length; _i < _len; _i++) {
+ item = items[_i];
+ if (!(!~this._indexOfItem(item))) {
+ continue;
+ }
+ this._storage.push(item);
+ addedItems.push(item);
+ }
+ this.length = this._storage.length;
+ if (this.fire && addedItems.length !== 0) {
+ this.fire('change', this, this);
+ this.fire.apply(this, ['itemsWereAdded'].concat(__slice.call(addedItems)));
+ }
+ return addedItems;
+ };
+
+ SimpleSet.prototype.remove = function() {
+ var index, item, items, removedItems, _i, _len;
+ items = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
+ removedItems = [];
+ for (_i = 0, _len = items.length; _i < _len; _i++) {
+ item = items[_i];
+ if (!(~(index = this._indexOfItem(item)))) {
+ continue;
+ }
+ this._storage.splice(index, 1);
+ removedItems.push(item);
+ }
+ this.length = this._storage.length;
+ if (this.fire && removedItems.length !== 0) {
+ this.fire('change', this, this);
+ this.fire.apply(this, ['itemsWereRemoved'].concat(__slice.call(removedItems)));
+ }
+ return removedItems;
+ };
+
+ SimpleSet.prototype.find = function(f) {
+ var item, _i, _len, _ref;
+ _ref = this._storage;
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ item = _ref[_i];
+ if (f(item)) {
+ return item;
+ }
+ }
+ };
+
+ SimpleSet.prototype.forEach = function(iterator, ctx) {
+ var container;
+ container = this;
+ return this._storage.slice().forEach(function(key) {
+ return iterator.call(ctx, key, null, container);
+ });
+ };
+
+ SimpleSet.prototype.isEmpty = function() {
+ return this.length === 0;
+ };
+
+ SimpleSet.prototype.clear = function() {
+ var items;
+ items = this._storage;
+ this._storage = [];
+ this.length = 0;
+ if (this.fire && items.length !== 0) {
+ this.fire('change', this, this);
+ this.fire.apply(this, ['itemsWereRemoved'].concat(__slice.call(items)));
+ }
+ return items;
+ };
+
+ SimpleSet.prototype.replace = function(other) {
+ try {
+ if (typeof this.prevent === "function") {
+ this.prevent('change');
+ }
+ this.clear();
+ return this.add.apply(this, other.toArray());
+ } finally {
+ if (typeof this.allowAndFire === "function") {
+ this.allowAndFire('change', this, this);
+ }
+ }
+ };
+
+ SimpleSet.prototype.toArray = function() {
+ return this._storage.slice();
+ };
+
+ SimpleSet.prototype.merge = function() {
+ var merged, others, set, _i, _len;
+ others = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
+ merged = new this.constructor;
+ others.unshift(this);
+ for (_i = 0, _len = others.length; _i < _len; _i++) {
+ set = others[_i];
+ set.forEach(function(v) {
+ return merged.add(v);
+ });
+ }
+ return merged;
+ };
+
+ SimpleSet.prototype.indexedBy = function(key) {
+ this._indexes || (this._indexes = new Batman.SimpleHash);
+ return this._indexes.get(key) || this._indexes.set(key, new Batman.SetIndex(this, key));
+ };
+
+ SimpleSet.prototype.indexedByUnique = function(key) {
+ this._uniqueIndexes || (this._uniqueIndexes = new Batman.SimpleHash);
+ return this._uniqueIndexes.get(key) || this._uniqueIndexes.set(key, new Batman.UniqueSetIndex(this, key));
+ };
+
+ SimpleSet.prototype.sortedBy = function(key, order) {
+ var sortsForKey;
+ if (order == null) {
+ order = "asc";
+ }
+ order = order.toLowerCase() === "desc" ? "desc" : "asc";
+ this._sorts || (this._sorts = new Batman.SimpleHash);
+ sortsForKey = this._sorts.get(key) || this._sorts.set(key, new Batman.Object);
+ return sortsForKey.get(order) || sortsForKey.set(order, new Batman.SetSort(this, key, order));
+ };
+
+ SimpleSet.prototype.equality = Batman.SimpleHash.prototype.equality;
+
+ SimpleSet.prototype._indexOfItem = function(givenItem) {
+ var index, item, _i, _len, _ref;
+ _ref = this._storage;
+ for (index = _i = 0, _len = _ref.length; _i < _len; index = ++_i) {
+ item = _ref[index];
+ if (this.equality(givenItem, item)) {
+ return index;
+ }
+ }
+ return -1;
+ };
+
+ return SimpleSet;
+
+ })();
+
+}).call(this);
+
+(function() {
+ var __slice = [].slice;
+
+ Batman.Property = (function() {
+
+ Batman.mixin(Property.prototype, Batman.EventEmitter);
+
+ Property._sourceTrackerStack = [];
+
+ Property.sourceTracker = function() {
+ var stack;
+ return (stack = this._sourceTrackerStack)[stack.length - 1];
+ };
+
+ Property.defaultAccessor = {
+ get: function(key) {
+ return this[key];
+ },
+ set: function(key, val) {
+ return this[key] = val;
+ },
+ unset: function(key) {
+ var x;
+ x = this[key];
+ delete this[key];
+ return x;
+ },
+ cache: false
+ };
+
+ Property.defaultAccessorForBase = function(base) {
+ var _ref;
+ return ((_ref = base._batman) != null ? _ref.getFirst('defaultAccessor') : void 0) || Batman.Property.defaultAccessor;
+ };
+
+ Property.accessorForBaseAndKey = function(base, key) {
+ var accessor, _bm, _ref,
+ _this = this;
+ if ((_bm = base._batman) != null) {
+ accessor = (_ref = _bm.keyAccessors) != null ? _ref.get(key) : void 0;
+ if (!accessor) {
+ _bm.ancestors(function(ancestor) {
+ var _ref1, _ref2;
+ return accessor || (accessor = (_ref1 = ancestor._batman) != null ? (_ref2 = _ref1.keyAccessors) != null ? _ref2.get(key) : void 0 : void 0);
+ });
+ }
+ }
+ return accessor || this.defaultAccessorForBase(base);
+ };
+
+ Property.forBaseAndKey = function(base, key) {
+ if (base.isObservable) {
+ return base.property(key);
+ } else {
+ return new Batman.Keypath(base, key);
+ }
+ };
+
+ Property.withoutTracking = function(block) {
+ return this.wrapTrackingPrevention(block)();
+ };
+
+ Property.wrapTrackingPrevention = function(block) {
+ return function() {
+ Batman.Property.pushDummySourceTracker();
+ try {
+ return block.apply(this, arguments);
+ } finally {
+ Batman.Property.popSourceTracker();
+ }
+ };
+ };
+
+ Property.registerSource = function(obj) {
+ var _ref;
+ if (!obj.isEventEmitter) {
+ return;
+ }
+ return (_ref = this.sourceTracker()) != null ? _ref.add(obj) : void 0;
+ };
+
+ Property.pushSourceTracker = function() {
+ return Batman.Property._sourceTrackerStack.push(new Batman.SimpleSet);
+ };
+
+ Property.pushDummySourceTracker = function() {
+ return Batman.Property._sourceTrackerStack.push(null);
+ };
+
+ Property.popSourceTracker = function() {
+ return Batman.Property._sourceTrackerStack.pop();
+ };
+
+ function Property(base, key) {
+ this.base = base;
+ this.key = key;
+ }
+
+ Property.prototype._isolationCount = 0;
+
+ Property.prototype.cached = false;
+
+ Property.prototype.value = null;
+
+ Property.prototype.sources = null;
+
+ Property.prototype.isProperty = true;
+
+ Property.prototype.isDead = false;
+
+ Property.prototype.eventClass = Batman.PropertyEvent;
+
+ Property.prototype.isEqual = function(other) {
+ return this.constructor === other.constructor && this.base === other.base && this.key === other.key;
+ };
+
+ Property.prototype.hashKey = function() {
+ var key;
+ this.hashKey = function() {
+ return key;
+ };
+ return key = "<Batman.Property base: " + (Batman.Hash.prototype.hashKeyFor(this.base)) + ", key: \"" + (Batman.Hash.prototype.hashKeyFor(this.key)) + "\">";
+ };
+
+ Property.prototype.event = function(key) {
+ var eventClass, _base;
+ eventClass = this.eventClass || Batman.Event;
+ this.events || (this.events = {});
+ (_base = this.events)[key] || (_base[key] = new eventClass(this, key));
+ return this.events[key];
+ };
+
+ Property.prototype.changeEvent = function() {
+ var event;
+ event = this.event('change');
+ this.changeEvent = function() {
+ return event;
+ };
+ return event;
+ };
+
+ Property.prototype.accessor = function() {
+ var accessor;
+ accessor = this.constructor.accessorForBaseAndKey(this.base, this.key);
+ this.accessor = function() {
+ return accessor;
+ };
+ return accessor;
+ };
+
+ Property.prototype.eachObserver = function(iterator) {
+ var key;
+ key = this.key;
+ this.changeEvent().handlers.slice().forEach(iterator);
+ if (this.base.isObservable) {
+ return this.base._batman.ancestors(function(ancestor) {
+ var handlers, property;
+ if (ancestor.isObservable && ancestor.hasProperty(key)) {
+ property = ancestor.property(key);
+ handlers = property.changeEvent().handlers;
+ return handlers.slice().forEach(iterator);
+ }
+ });
+ }
+ };
+
+ Property.prototype.observers = function() {
+ var results;
+ results = [];
+ this.eachObserver(function(observer) {
+ return results.push(observer);
+ });
+ return results;
+ };
+
+ Property.prototype.hasObservers = function() {
+ return this.observers().length > 0;
+ };
+
+ Property.prototype.updateSourcesFromTracker = function() {
+ var handler, newSources;
+ newSources = this.constructor.popSourceTracker();
+ handler = this.sourceChangeHandler();
+ this._eachSourceChangeEvent(function(e) {
+ return e.removeHandler(handler);
+ });
+ this.sources = newSources;
+ return this._eachSourceChangeEvent(function(e) {
+ return e.addHandler(handler);
+ });
+ };
+
+ Property.prototype._eachSourceChangeEvent = function(iterator) {
+ if (this.sources == null) {
+ return;
+ }
+ return this.sources.forEach(function(source) {
+ return iterator(source.event('change'));
+ });
+ };
+
+ Property.prototype.getValue = function() {
+ this.registerAsMutableSource();
+ if (!this.isCached()) {
+ this.constructor.pushSourceTracker();
+ try {
+ this.value = this.valueFromAccessor();
+ this.cached = true;
+ } finally {
+ this.updateSourcesFromTracker();
+ }
+ }
+ return this.value;
+ };
+
+ Property.prototype.isCachable = function() {
+ var cacheable;
+ if (this.isFinal()) {
+ return true;
+ }
+ cacheable = this.accessor().cache;
+ if (cacheable != null) {
+ return !!cacheable;
+ } else {
+ return true;
+ }
+ };
+
+ Property.prototype.isCached = function() {
+ return this.isCachable() && this.cached;
+ };
+
+ Property.prototype.isFinal = function() {
+ return !!this.accessor()['final'];
+ };
+
+ Property.prototype.refresh = function() {
+ var previousValue, value;
+ this.cached = false;
+ previousValue = this.value;
+ value = this.getValue();
+ if (value !== previousValue && !this.isIsolated()) {
+ this.fire(value, previousValue);
+ }
+ if (this.value !== void 0 && this.isFinal()) {
+ return this.lockValue();
+ }
+ };
+
+ Property.prototype.sourceChangeHandler = function() {
+ var handler,
+ _this = this;
+ handler = this._handleSourceChange.bind(this);
+ Batman.developer["do"](function() {
+ return handler.property = _this;
+ });
+ this.sourceChangeHandler = function() {
+ return handler;
+ };
+ return handler;
+ };
+
+ Property.prototype._handleSourceChange = function() {
+ if (this.isIsolated()) {
+ return this._needsRefresh = true;
+ } else if (!this.isFinal() && !this.hasObservers()) {
+ return this.cached = false;
+ } else {
+ return this.refresh();
+ }
+ };
+
+ Property.prototype.valueFromAccessor = function() {
+ var _ref;
+ return (_ref = this.accessor().get) != null ? _ref.call(this.base, this.key) : void 0;
+ };
+
+ Property.prototype.setValue = function(val) {
+ var set;
+ if (!(set = this.accessor().set)) {
+ return;
+ }
+ return this._changeValue(function() {
+ return set.call(this.base, this.key, val);
+ });
+ };
+
+ Property.prototype.unsetValue = function() {
+ var unset;
+ if (!(unset = this.accessor().unset)) {
+ return;
+ }
+ return this._changeValue(function() {
+ return unset.call(this.base, this.key);
+ });
+ };
+
+ Property.prototype._changeValue = function(block) {
+ var result;
+ this.cached = false;
+ this.constructor.pushDummySourceTracker();
+ try {
+ result = block.apply(this);
+ this.refresh();
+ } finally {
+ this.constructor.popSourceTracker();
+ }
+ if (!(this.isCached() || this.hasObservers())) {
+ this.die();
+ }
+ return result;
+ };
+
+ Property.prototype.forget = function(handler) {
+ if (handler != null) {
+ return this.changeEvent().removeHandler(handler);
+ } else {
+ return this.changeEvent().clearHandlers();
+ }
+ };
+
+ Property.prototype.observeAndFire = function(handler) {
+ this.observe(handler);
+ return handler.call(this.base, this.value, this.value, this.key);
+ };
+
+ Property.prototype.observe = function(handler) {
+ this.changeEvent().addHandler(handler);
+ if (this.sources == null) {
+ this.getValue();
+ }
+ return this;
+ };
+
+ Property.prototype.observeOnce = function(originalHandler) {
+ var event, handler;
+ event = this.changeEvent();
+ handler = function() {
+ originalHandler.apply(this, arguments);
+ return event.removeHandler(handler);
+ };
+ event.addHandler(handler);
+ if (this.sources == null) {
+ this.getValue();
+ }
+ return this;
+ };
+
+ Property.prototype._removeHandlers = function() {
+ var handler;
+ handler = this.sourceChangeHandler();
+ this._eachSourceChangeEvent(function(e) {
+ return e.removeHandler(handler);
+ });
+ delete this.sources;
+ return this.changeEvent().clearHandlers();
+ };
+
+ Property.prototype.lockValue = function() {
+ this._removeHandlers();
+ this.getValue = function() {
+ return this.value;
+ };
+ return this.setValue = this.unsetValue = this.refresh = this.observe = function() {};
+ };
+
+ Property.prototype.die = function() {
+ var _ref, _ref1;
+ this._removeHandlers();
+ if ((_ref = this.base._batman) != null) {
+ if ((_ref1 = _ref.properties) != null) {
+ _ref1.unset(this.key);
+ }
+ }
+ return this.isDead = true;
+ };
+
+ Property.prototype.fire = function() {
+ var _ref;
+ return (_ref = this.changeEvent()).fire.apply(_ref, __slice.call(arguments).concat([this.key]));
+ };
+
+ Property.prototype.isolate = function() {
+ if (this._isolationCount === 0) {
+ this._preIsolationValue = this.getValue();
+ }
+ return this._isolationCount++;
+ };
+
+ Property.prototype.expose = function() {
+ if (this._isolationCount === 1) {
+ this._isolationCount--;
+ if (this._needsRefresh) {
+ this.value = this._preIsolationValue;
+ this.refresh();
+ } else if (this.value !== this._preIsolationValue) {
+ this.fire(this.value, this._preIsolationValue);
+ }
+ return this._preIsolationValue = null;
+ } else if (this._isolationCount > 0) {
+ return this._isolationCount--;
+ }
+ };
+
+ Property.prototype.isIsolated = function() {
+ return this._isolationCount > 0;
+ };
+
+ return Property;
+
+ })();
+
+}).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.Keypath = (function(_super) {
+
+ __extends(Keypath, _super);
+
+ function Keypath(base, key) {
+ if (typeof key === 'string') {
+ this.segments = key.split('.');
+ this.depth = this.segments.length;
+ } else {
+ this.segments = [key];
+ this.depth = 1;
+ }
+ Keypath.__super__.constructor.apply(this, arguments);
+ }
+
+ Keypath.prototype.isCachable = function() {
+ if (this.depth === 1) {
+ return Keypath.__super__.isCachable.apply(this, arguments);
+ } else {
+ return true;
+ }
+ };
+
+ Keypath.prototype.terminalProperty = function() {
+ var base;
+ base = Batman.getPath(this.base, this.segments.slice(0, -1));
+ if (base == null) {
+ return;
+ }
+ return Batman.Keypath.forBaseAndKey(base, this.segments[this.depth - 1]);
+ };
+
+ Keypath.prototype.valueFromAccessor = function() {
+ if (this.depth === 1) {
+ return Keypath.__super__.valueFromAccessor.apply(this, arguments);
+ } else {
+ return Batman.getPath(this.base, this.segments);
+ }
+ };
+
+ Keypath.prototype.setValue = function(val) {
+ var _ref;
+ if (this.depth === 1) {
+ return Keypath.__super__.setValue.apply(this, arguments);
+ } else {
+ return (_ref = this.terminalProperty()) != null ? _ref.setValue(val) : void 0;
+ }
+ };
+
+ Keypath.prototype.unsetValue = function() {
+ var _ref;
+ if (this.depth === 1) {
+ return Keypath.__super__.unsetValue.apply(this, arguments);
+ } else {
+ return (_ref = this.terminalProperty()) != null ? _ref.unsetValue() : void 0;
+ }
+ };
+
+ return Keypath;
+
+ })(Batman.Property);
+
+}).call(this);
+
+(function() {
+ var __slice = [].slice;
+
+ Batman.Observable = {
+ isObservable: true,
+ hasProperty: function(key) {
+ var _ref, _ref1;
+ return (_ref = this._batman) != null ? (_ref1 = _ref.properties) != null ? typeof _ref1.hasKey === "function" ? _ref1.hasKey(key) : void 0 : void 0 : void 0;
+ },
+ property: function(key) {
+ var properties, propertyClass, _base;
+ Batman.initializeObject(this);
+ propertyClass = this.propertyClass || Batman.Keypath;
+ properties = (_base = this._batman).properties || (_base.properties = new Batman.SimpleHash);
+ return properties.get(key) || properties.set(key, new propertyClass(this, key));
+ },
+ get: function(key) {
+ return this.property(key).getValue();
+ },
+ set: function(key, val) {
+ return this.property(key).setValue(val);
+ },
+ unset: function(key) {
+ return this.property(key).unsetValue();
+ },
+ getOrSet: Batman.SimpleHash.prototype.getOrSet,
+ forget: function(key, observer) {
+ var _ref;
+ if (key) {
+ this.property(key).forget(observer);
+ } else {
+ if ((_ref = this._batman.properties) != null) {
+ _ref.forEach(function(key, property) {
+ return property.forget();
+ });
+ }
+ }
+ return this;
+ },
+ observe: function() {
+ var args, key, _ref;
+ key = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
+ (_ref = this.property(key)).observe.apply(_ref, args);
+ return this;
+ },
+ observeAndFire: function() {
+ var args, key, _ref;
+ key = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
+ (_ref = this.property(key)).observeAndFire.apply(_ref, args);
+ return this;
+ },
+ observeOnce: function() {
+ var args, key, _ref;
+ key = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
+ (_ref = this.property(key)).observeOnce.apply(_ref, args);
+ return this;
+ }
+ };
+
+}).call(this);
+
+(function() {
+
+ Batman.DOM = {
+ textInputTypes: ['text', 'search', 'tel', 'url', 'email', 'password'],
+ scrollIntoView: function(elementID) {
+ 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');
+ view = new Batman.View({
+ source: path,
+ context: context
+ });
+ return view.on('ready', function() {
+ Batman.setInnerHTML(container, '');
+ Batman.appendChild(container, view.get('node'));
+ return renderer.allowAndFire('rendered');
+ });
+ },
+ propagateBindingEvent: Batman.propagateBindingEvent = function(binding, node) {
+ var current, parentBinding, parentBindings, _i, _len;
+ while ((current = (current || node).parentNode)) {
+ parentBindings = Batman._data(current, 'bindings');
+ if (parentBindings != null) {
+ for (_i = 0, _len = parentBindings.length; _i < _len; _i++) {
+ parentBinding = parentBindings[_i];
+ if (typeof parentBinding.childBindingAdded === "function") {
+ parentBinding.childBindingAdded(binding);
+ }
+ }
+ }
+ }
+ },
+ propagateBindingEvents: Batman.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);
+ }
+ if (bindings = Batman._data(newNode, 'bindings')) {
+ for (_j = 0, _len1 = bindings.length; _j < _len1; _j++) {
+ binding = bindings[_j];
+ Batman.propagateBindingEvent(binding, newNode);
+ }
+ }
+ },
+ trackBinding: Batman.trackBinding = function(binding, node) {
+ var bindings;
+ if (bindings = Batman._data(node, 'bindings')) {
+ bindings.push(binding);
+ } else {
+ Batman._data(node, 'bindings', [binding]);
+ }
+ Batman.DOM.fire('bindingAdded', binding);
+ Batman.propagateBindingEvent(binding, node);
+ return true;
+ },
+ onParseExit: Batman.onParseExit = function(node, callback) {
+ var set;
+ set = Batman._data(node, 'onParseExit') || Batman._data(node, 'onParseExit', new Batman.SimpleSet);
+ if (callback != null) {
+ set.add(callback);
+ }
+ return set;
+ },
+ forgetParseExit: Batman.forgetParseExit = function(node, callback) {
+ return Batman.removeData(node, 'onParseExit', true);
+ },
+ defineView: function(name, node) {
+ var contents;
+ contents = node.innerHTML;
+ 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 {
+ return node.style.setProperty(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) {
+ var view;
+ view = Batman._data(node, 'view');
+ view || (view = Batman._data(node, 'yielder'));
+ if ((view != null) && view.get('cached')) {
+ return Batman.DOM.removeNode(node);
+ } else {
+ return Batman.DOM.destroyNode(node);
+ }
+ },
+ insertBefore: Batman.insertBefore = function(parentNode, newNode, referenceNode) {
+ if (referenceNode == null) {
+ referenceNode = null;
+ }
+ if (!referenceNode || parentNode.childNodes.length <= 0) {
+ return Batman.appendChild(parentNode, newNode);
+ } else {
+ Batman.DOM.willInsertNode(newNode);
+ parentNode.insertBefore(newNode, referenceNode);
+ return Batman.DOM.didInsertNode(newNode);
+ }
+ },
+ valueForNode: function(node, value, escapeValue) {
+ var isSetting;
+ if (value == null) {
+ value = '';
+ }
+ if (escapeValue == null) {
+ escapeValue = true;
+ }
+ isSetting = arguments.length > 1;
+ switch (node.nodeName.toUpperCase()) {
+ case 'INPUT':
+ case 'TEXTAREA':
+ if (isSetting) {
+ return node.value = value;
+ } else {
+ return node.value;
+ }
+ break;
+ case 'SELECT':
+ if (isSetting) {
+ return node.value = value;
+ }
+ break;
+ default:
+ if (isSetting) {
+ return Batman.setInnerHTML(node, escapeValue ? Batman.escapeHTML(value) : value);
+ } else {
+ return node.innerHTML;
+ }
+ }
+ },
+ nodeIsEditable: function(node) {
+ var _ref;
+ return (_ref = node.nodeName.toUpperCase()) === 'INPUT' || _ref === 'TEXTAREA' || _ref === 'SELECT';
+ },
+ addEventListener: Batman.addEventListener = function(node, eventName, callback) {
+ var listeners;
+ if (!(listeners = Batman._data(node, 'listeners'))) {
+ listeners = Batman._data(node, 'listeners', {});
+ }
+ if (!listeners[eventName]) {
+ listeners[eventName] = [];
+ }
+ listeners[eventName].push(callback);
+ if (Batman.hasAddEventListener) {
+ return node.addEventListener(eventName, callback, false);
+ } else {
+ return node.attachEvent("on" + eventName, callback);
+ }
+ },
+ removeEventListener: Batman.removeEventListener = function(node, eventName, callback) {
+ var eventListeners, index, listeners;
+ if (listeners = Batman._data(node, 'listeners')) {
+ if (eventListeners = listeners[eventName]) {
+ index = eventListeners.indexOf(callback);
+ if (index !== -1) {
+ eventListeners.splice(index, 1);
+ }
+ }
+ }
+ if (Batman.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) {
+ if (typeof e.preventDefault === "function") {
+ return e.preventDefault();
+ } else {
+ return e.returnValue = false;
+ }
+ },
+ stopPropagation: Batman.stopPropagation = function(e) {
+ if (e.stopPropagation) {
+ return e.stopPropagation();
+ } else {
+ return e.cancelBubble = true;
+ }
+ },
+ willInsertNode: function(node) {
+ var child, view, _i, _len, _ref, _ref1;
+ view = Batman._data(node, 'view');
+ if (view != null) {
+ view.fire('beforeAppear', node);
+ }
+ if ((_ref = Batman.data(node, 'show')) != null) {
+ _ref.call(node);
+ }
+ _ref1 = node.childNodes;
+ for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
+ child = _ref1[_i];
+ Batman.DOM.willInsertNode(child);
+ }
+ return true;
+ },
+ didInsertNode: function(node) {
+ var child, view, _i, _len, _ref;
+ view = Batman._data(node, 'view');
+ if (view) {
+ view.fire('appear', node);
+ view.applyYields();
+ }
+ _ref = node.childNodes;
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ child = _ref[_i];
+ Batman.DOM.didInsertNode(child);
+ }
+ return true;
+ },
+ willRemoveNode: function(node) {
+ var child, view, _i, _len, _ref, _ref1;
+ view = Batman._data(node, 'view');
+ if (view) {
+ view.fire('beforeDisappear', node);
+ }
+ if ((_ref = Batman.data(node, 'hide')) != null) {
+ _ref.call(node);
+ }
+ _ref1 = node.childNodes;
+ for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
+ child = _ref1[_i];
+ Batman.DOM.willRemoveNode(child);
+ }
+ return true;
+ },
+ didRemoveNode: function(node) {
+ var child, view, _i, _len, _ref;
+ view = Batman._data(node, 'view');
+ if (view) {
+ view.retractYields();
+ view.fire('disappear', node);
+ }
+ _ref = node.childNodes;
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ child = _ref[_i];
+ Batman.DOM.didRemoveNode(child);
+ }
+ return true;
+ },
+ willDestroyNode: function(node) {
+ var child, view, _i, _len, _ref;
+ view = Batman._data(node, 'view');
+ if (view) {
+ view.fire('beforeDestroy', node);
+ view.get('yields').forEach(function(name, actions) {
+ var _i, _len, _results;
+ _results = [];
+ for (_i = 0, _len = actions.length; _i < _len; _i++) {
+ node = actions[_i].node;
+ _results.push(Batman.DOM.willDestroyNode(node));
+ }
+ return _results;
+ });
+ }
+ _ref = node.childNodes;
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ child = _ref[_i];
+ Batman.DOM.willDestroyNode(child);
+ }
+ return true;
+ },
+ didDestroyNode: function(node) {
+ var bindings, child, eventListeners, eventName, listeners, view, _i, _len, _ref;
+ view = Batman._data(node, 'view');
+ if (view) {
+ view.fire('destroy', node);
+ view.get('yields').forEach(function(name, actions) {
+ var _i, _len, _results;
+ _results = [];
+ for (_i = 0, _len = actions.length; _i < _len; _i++) {
+ node = actions[_i].node;
+ _results.push(Batman.DOM.didDestroyNode(node));
+ }
+ return _results;
+ });
+ }
+ if (bindings = Batman._data(node, 'bindings')) {
+ bindings.forEach(function(binding) {
+ return binding.die();
+ });
+ }
+ if (listeners = Batman._data(node, 'listeners')) {
+ for (eventName in listeners) {
+ eventListeners = listeners[eventName];
+ eventListeners.forEach(function(listener) {
+ return Batman.removeEventListener(node, eventName, listener);
+ });
+ }
+ }
+ Batman.removeData(node);
+ Batman.removeData(node, void 0, true);
+ _ref = node.childNodes;
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ child = _ref[_i];
+ Batman.DOM.didDestroyNode(child);
+ }
+ return true;
+ }
+ };
+
+ Batman.mixin(Batman.DOM, Batman.EventEmitter, Batman.Observable);
+
+ Batman.DOM.event('bindingAdded');
+
+}).call(this);
+
+(function() {
+ var __slice = [].slice;
+
+ Batman.DOM.readers = {
+ target: function(node, key, context, renderer) {
+ Batman.DOM.readers.bind(node, key, context, renderer, 'nodeChange');
+ return true;
+ },
+ source: function(node, key, context, renderer) {
+ Batman.DOM.readers.bind(node, key, context, renderer, 'dataChange');
+ return true;
+ },
+ bind: function(node, key, context, renderer, only) {
+ var bindingClass;
+ bindingClass = false;
+ switch (node.nodeName.toLowerCase()) {
+ case 'input':
+ switch (node.getAttribute('type')) {
+ case 'checkbox':
+ Batman.DOM.attrReaders.bind(node, 'checked', key, context, renderer, only);
+ return true;
+ case 'radio':
+ bindingClass = Batman.DOM.RadioBinding;
+ break;
+ case 'file':
+ bindingClass = Batman.DOM.FileBinding;
+ }
+ break;
+ case 'select':
+ bindingClass = Batman.DOM.SelectBinding;
+ }
+ bindingClass || (bindingClass = Batman.DOM.Binding);
+ (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;
+ })(bindingClass, arguments, function(){});
+ return true;
+ },
+ context: function(node, key, context, renderer) {
+ return context.descendWithKey(key);
+ },
+ mixin: function(node, key, context, renderer) {
+ new Batman.DOM.MixinBinding(node, key, context.descend(Batman.mixins), renderer);
+ return true;
+ },
+ showif: function(node, key, context, parentRenderer, invert) {
+ new Batman.DOM.ShowHideBinding(node, key, context, parentRenderer, false, invert);
+ return true;
+ },
+ hideif: function() {
+ var _ref;
+ return (_ref = Batman.DOM.readers).showif.apply(_ref, __slice.call(arguments).concat([true]));
+ },
+ insertif: function(node, key, context, parentRenderer, invert) {
+ new Batman.DOM.InsertionBinding(node, key, context, parentRenderer, false, invert);
+ return true;
+ },
+ removeif: function() {
+ var _ref;
+ return (_ref = Batman.DOM.readers).insertif.apply(_ref, __slice.call(arguments).concat([true]));
+ },
+ route: function() {
+ (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.DOM.RouteBinding, arguments, function(){});
+ return true;
+ },
+ view: function() {
+ (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.DOM.ViewBinding, arguments, function(){});
+ return false;
+ },
+ partial: function(node, path, context, renderer) {
+ Batman.DOM.partial(node, path, context, renderer);
+ return true;
+ },
+ defineview: function(node, name, context, renderer) {
+ Batman.onParseExit(node, function() {
+ var _ref;
+ return (_ref = node.parentNode) != null ? _ref.removeChild(node) : void 0;
+ });
+ Batman.DOM.defineView(name, node);
+ return false;
+ },
+ renderif: function(node, key, context, renderer) {
+ new Batman.DOM.DeferredRenderingBinding(node, key, context, renderer);
+ return false;
+ },
+ "yield": function(node, key) {
+ Batman.onParseExit(node, function() {
+ return Batman.DOM.Yield.withName(key).set('containerNode', node);
+ });
+ return true;
+ },
+ contentfor: function(node, key, context, renderer, action) {
+ if (action == null) {
+ action = 'append';
+ }
+ Batman.onParseExit(node, function() {
+ var _ref;
+ if ((_ref = node.parentNode) != null) {
+ _ref.removeChild(node);
+ }
+ return renderer.view.pushYieldAction(key, action, node);
+ });
+ return true;
+ },
+ replace: function(node, key, context, renderer) {
+ Batman.DOM.readers.contentfor(node, key, context, renderer, 'replace');
+ return true;
+ }
+ };
+
+}).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; };
+
+ Batman.DOM.events = {
+ click: function(node, callback, context, eventName) {
+ 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]);
+ });
+ if (node.nodeName.toUpperCase() === 'A' && !node.href) {
+ node.href = '#';
+ }
+ return node;
+ },
+ doubleclick: function(node, callback, context) {
+ return Batman.DOM.events.click(node, callback, context, 'dblclick');
+ },
+ change: function(node, callback, context) {
+ var eventName, eventNames, oldCallback, _i, _len, _results;
+ eventNames = (function() {
+ var _ref;
+ switch (node.nodeName.toUpperCase()) {
+ case 'TEXTAREA':
+ return ['input', 'keyup', 'change'];
+ case 'INPUT':
+ if (_ref = node.type.toLowerCase(), __indexOf.call(Batman.DOM.textInputTypes, _ref) >= 0) {
+ oldCallback = callback;
+ callback = function(node, event) {
+ if (event.type === 'keyup' && Batman.DOM.events.isEnter(event)) {
+ return;
+ }
+ return oldCallback.apply(null, arguments);
+ };
+ return ['input', 'keyup', 'change'];
+ } else {
+ return ['input', 'change'];
+ }
+ break;
+ default:
+ return ['change'];
+ }
+ })();
+ _results = [];
+ for (_i = 0, _len = eventNames.length; _i < _len; _i++) {
+ eventName = eventNames[_i];
+ _results.push(Batman.addEventListener(node, eventName, function() {
+ var args;
+ args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
+ return callback.apply(null, [node].concat(__slice.call(args), [context]));
+ }));
+ }
+ return _results;
+ },
+ isEnter: function(ev) {
+ var _ref, _ref1;
+ return ((13 <= (_ref = ev.keyCode) && _ref <= 14)) || ((13 <= (_ref1 = ev.which) && _ref1 <= 14)) || ev.keyIdentifier === 'Enter' || ev.key === 'Enter';
+ },
+ submit: function(node, callback, context) {
+ if (Batman.DOM.nodeIsEditable(node)) {
+ Batman.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() {
+ 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]);
+ callback.apply(null, [node].concat(__slice.call(args), [context]));
+ }
+ return Batman.DOM._keyCapturingNode = null;
+ }
+ });
+ } else {
+ Batman.addEventListener(node, 'submit', function() {
+ var args;
+ args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
+ Batman.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() {
+ var args;
+ args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
+ return callback.apply(null, [node].concat(__slice.call(args), [context]));
+ });
+ }
+ };
+
+}).call(this);
+
+(function() {
+
+ Batman.DOM.attrReaders = {
+ _parseAttribute: function(value) {
+ if (value === 'false') {
+ value = false;
+ }
+ if (value === 'true') {
+ value = true;
+ }
+ return value;
+ },
+ source: function(node, attr, key, context, renderer) {
+ return Batman.DOM.attrReaders.bind(node, attr, key, context, renderer, 'dataChange');
+ },
+ bind: function(node, attr, key, context, renderer, only) {
+ var bindingClass;
+ bindingClass = (function() {
+ switch (attr) {
+ case 'checked':
+ case 'disabled':
+ case 'selected':
+ return Batman.DOM.CheckedBinding;
+ case 'value':
+ case 'href':
+ case 'src':
+ case 'size':
+ return Batman.DOM.NodeAttributeBinding;
+ case 'class':
+ return Batman.DOM.ClassBinding;
+ case 'style':
+ return Batman.DOM.StyleBinding;
+ default:
+ return Batman.DOM.AttributeBinding;
+ }
+ })();
+ (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;
+ })(bindingClass, arguments, function(){});
+ return true;
+ },
+ context: function(node, contextName, key, context) {
+ return context.descendWithKey(key, contextName);
+ },
+ event: function(node, eventName, key, context) {
+ (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.DOM.EventBinding, arguments, function(){});
+ return true;
+ },
+ addclass: function(node, className, key, context, parentRenderer, invert) {
+ new Batman.DOM.AddClassBinding(node, className, key, context, parentRenderer, false, invert);
+ return true;
+ },
+ removeclass: function(node, className, key, context, parentRenderer) {
+ return Batman.DOM.attrReaders.addclass(node, className, key, context, parentRenderer, true);
+ },
+ foreach: function(node, iteratorName, key, context, parentRenderer) {
+ (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.DOM.IteratorBinding, arguments, function(){});
+ return false;
+ },
+ formfor: function(node, localName, key, context) {
+ (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.DOM.FormBinding, arguments, function(){});
+ return context.descendWithKey(key, localName);
+ }
+ };
+
+}).call(this);
+
+(function() {
+ var BatmanObject,
+ __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;
+
+ BatmanObject.prototype._batmanID = function() {
+ var c;
+ this._batmanID = function() {
+ return c;
+ };
+ 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;
+ }
+ }
+ return obj;
+ };
+
+ 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];
+ }
+ }
+ }
+ 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);
+ }
+ return val = result;
+ };
+ fetcher.call(this, deliver, key);
+ returned = true;
+ return val;
+ },
+ 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;
+ }
+ }
+ return wrapper;
+ };
+
+ BatmanObject._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)) {
+ return Batman.Property.defaultAccessorForBase(this);
+ } else if (keys.length === 0 && ((_ref = Batman.typeOf(accessor)) !== 'Object' && _ref !== 'Function')) {
+ return Batman.Property.accessorForBaseAndKey(this, accessor);
+ } else if (typeof accessor.promise === 'function') {
+ return this._defineWrapAccessor.apply(this, __slice.call(keys).concat([promiseWrapper(accessor.promise)]));
+ }
+ Batman.initializeObject(this);
+ if (keys.length === 0) {
+ return this._batman.defaultAccessor = getAccessorObject(this, accessor);
+ } else {
+ (_base = this._batman).keyAccessors || (_base.keyAccessors = new Batman.SimpleHash);
+ _results = [];
+ for (_j = 0, _len = keys.length; _j < _len; _j++) {
+ key = keys[_j];
+ _results.push(this._batman.keyAccessors.set(key, getAccessorObject(this, accessor)));
+ }
+ return _results;
+ }
+ };
+
+ BatmanObject.prototype._defineAccessor = BatmanObject._defineAccessor;
+
+ BatmanObject._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);
+ if (keys.length === 0) {
+ return this._defineAccessor(wrapSingleAccessor(this._defineAccessor(), wrapper));
+ } else {
+ _results = [];
+ for (_j = 0, _len = keys.length; _j < _len; _j++) {
+ key = keys[_j];
+ _results.push(this._defineAccessor(key, wrapSingleAccessor(this._defineAccessor(key), wrapper)));
+ }
+ return _results;
+ }
+ };
+
+ BatmanObject.prototype._defineWrapAccessor = BatmanObject._defineWrapAccessor;
+
+ BatmanObject.classAccessor = BatmanObject._defineAccessor;
+
+ BatmanObject.accessor = function() {
+ var _ref;
+ return (_ref = this.prototype)._defineAccessor.apply(_ref, arguments);
+ };
+
+ BatmanObject.prototype.accessor = BatmanObject._defineAccessor;
+
+ BatmanObject.wrapClassAccessor = BatmanObject._defineWrapAccessor;
+
+ BatmanObject.wrapAccessor = function() {
+ var _ref;
+ return (_ref = this.prototype)._defineWrapAccessor.apply(_ref, arguments);
+ };
+
+ 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);
+ };
+
+ BatmanObject.singleton = function(singletonMethodName) {
+ if (singletonMethodName == null) {
+ singletonMethodName = "sharedInstance";
+ }
+ return this.classAccessor(singletonMethodName, {
+ get: function() {
+ var _name;
+ return this[_name = "_" + singletonMethodName] || (this[_name] = new this);
+ }
+ });
+ };
+
+ BatmanObject.accessor('_batmanID', function() {
+ return this._batmanID();
+ });
+
+ return BatmanObject;
+
+ })(Object);
+
+ Batman.Object = BatmanObject;
+
+}).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; };
+
+ Batman.Renderer = (function(_super) {
+ var bindingRegexp, bindingSortOrder, bindingSortPositions, k, name, pos, _i, _j, _len, _len1, _ref;
+
+ __extends(Renderer, _super);
+
+ Renderer.prototype.deferEvery = 50;
+
+ function Renderer(node, context, view) {
+ this.node = node;
+ this.context = context;
+ this.view = view;
+ this.resume = __bind(this.resume, this);
+
+ this.start = __bind(this.start, this);
+
+ Renderer.__super__.constructor.call(this);
+ if (!(this.context instanceof Batman.RenderContext)) {
+ Batman.developer.error("Must pass a RenderContext to a renderer for rendering");
+ }
+ this.immediate = Batman.setImmediate(this.start);
+ }
+
+ Renderer.prototype.start = function() {
+ this.startTime = new Date;
+ return this.parseNode(this.node);
+ };
+
+ Renderer.prototype.resume = function() {
+ this.startTime = new Date;
+ return this.parseNode(this.resumeNode);
+ };
+
+ Renderer.prototype.finish = function() {
+ this.startTime = null;
+ this.prevent('stopped');
+ this.fire('parsed');
+ return this.fire('rendered');
+ };
+
+ Renderer.prototype.stop = function() {
+ Batman.clearImmediate(this.immediate);
+ return this.fire('stopped');
+ };
+
+ _ref = ['parsed', 'rendered', 'stopped'];
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ k = _ref[_i];
+ Renderer.prototype.event(k).oneShot = true;
+ }
+
+ bindingRegexp = /^data\-(.*)/;
+
+ bindingSortOrder = ["view", "renderif", "foreach", "formfor", "context", "bind", "source", "target"];
+
+ bindingSortPositions = {};
+
+ for (pos = _j = 0, _len1 = bindingSortOrder.length; _j < _len1; pos = ++_j) {
+ name = bindingSortOrder[pos];
+ bindingSortPositions[name] = pos;
+ }
+
+ Renderer.prototype._sortBindings = function(a, b) {
+ var aindex, bindex;
+ aindex = bindingSortPositions[a[0]];
+ bindex = bindingSortPositions[b[0]];
+ if (aindex == null) {
+ aindex = bindingSortOrder.length;
+ }
+ if (bindex == null) {
+ bindex = bindingSortOrder.length;
+ }
+ if (aindex > bindex) {
+ return 1;
+ } else if (bindex > aindex) {
+ return -1;
+ } else if (a[0] > b[0]) {
+ return 1;
+ } else if (b[0] > a[0]) {
+ return -1;
+ } else {
+ return 0;
+ }
+ };
+
+ Renderer.prototype.parseNode = function(node) {
+ var argument, attribute, bindings, keypath, names, nextNode, oldContext, result, skipChildren, _base, _base1, _k, _l, _len2, _len3, _ref1, _ref2, _ref3, _ref4,
+ _this = this;
+ if (this.deferEvery && (new Date - this.startTime) > this.deferEvery) {
+ this.resumeNode = node;
+ this.timeout = Batman.setImmediate(this.resume);
+ return;
+ }
+ if (node.getAttribute && node.attributes) {
+ bindings = [];
+ _ref1 = node.attributes;
+ for (_k = 0, _len2 = _ref1.length; _k < _len2; _k++) {
+ attribute = _ref1[_k];
+ name = (_ref2 = attribute.nodeName.match(bindingRegexp)) != null ? _ref2[1] : void 0;
+ if (!name) {
+ continue;
+ }
+ bindings.push((names = name.split('-')).length > 1 ? [names[0], names.slice(1, names.length + 1 || 9e9).join('-'), attribute.value] : [name, void 0, attribute.value]);
+ }
+ _ref3 = bindings.sort(this._sortBindings);
+ for (_l = 0, _len3 = _ref3.length; _l < _len3; _l++) {
+ _ref4 = _ref3[_l], name = _ref4[0], argument = _ref4[1], keypath = _ref4[2];
+ result = argument ? typeof (_base = Batman.DOM.attrReaders)[name] === "function" ? _base[name](node, argument, keypath, this.context, this) : void 0 : typeof (_base1 = Batman.DOM.readers)[name] === "function" ? _base1[name](node, keypath, this.context, this) : void 0;
+ if (result === false) {
+ skipChildren = true;
+ break;
+ } else if (result instanceof Batman.RenderContext) {
+ oldContext = this.context;
+ this.context = result;
+ Batman.onParseExit(node, function() {
+ return _this.context = oldContext;
+ });
+ }
+ }
+ }
+ if ((nextNode = this.nextNode(node, skipChildren))) {
+ return this.parseNode(nextNode);
+ } else {
+ return this.finish();
+ }
+ };
+
+ Renderer.prototype.nextNode = function(node, skipChildren) {
+ var children, nextParent, parentSibling, sibling, _ref1, _ref2;
+ if (!skipChildren) {
+ children = node.childNodes;
+ if (children != null ? children.length : void 0) {
+ return children[0];
+ }
+ }
+ sibling = node.nextSibling;
+ if ((_ref1 = Batman.onParseExit(node)) != null) {
+ _ref1.forEach(function(callback) {
+ return callback();
+ });
+ }
+ Batman.forgetParseExit(node);
+ if (this.node === node) {
+ return;
+ }
+ if (sibling) {
+ return sibling;
+ }
+ nextParent = node;
+ while (nextParent = nextParent.parentNode) {
+ parentSibling = nextParent.nextSibling;
+ if ((_ref2 = Batman.onParseExit(nextParent)) != null) {
+ _ref2.forEach(function(callback) {
+ return callback();
+ });
+ }
+ Batman.forgetParseExit(nextParent);
+ if (this.node === nextParent) {
+ return;
+ }
+ if (parentSibling) {
+ return parentSibling;
+ }
+ }
+ };
+
+ return Renderer;
+
+ })(Batman.Object);
+
+}).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; };
+
+ Batman.DOM.AbstractBinding = (function(_super) {
+ var get_dot_rx, get_rx, keypath_rx;
+
+ __extends(AbstractBinding, _super);
+
+ keypath_rx = /(^|,)\s*(?:(true|false)|("[^"]*")|(\{[^\}]*\})|([a-zA-Z][\w\-\.]*[\?\!]?))\s*(?=$|,)/g;
+
+ get_dot_rx = /(?:\]\.)(.+?)(?=[\[\.]|\s*\||$)/;
+
+ get_rx = /(?!^\s*)\[(.*?)\]/g;
+
+ AbstractBinding.accessor('filteredValue', {
+ get: function() {
+ var renderContext, result, self, unfilteredValue;
+ unfilteredValue = this.get('unfilteredValue');
+ self = this;
+ renderContext = this.get('renderContext');
+ if (this.filterFunctions.length > 0) {
+ Batman.developer.currentFilterStack = renderContext;
+ result = this.filterFunctions.reduce(function(value, fn, i) {
+ var args;
+ args = self.filterArguments[i].map(function(argument) {
+ if (argument._keypath) {
+ return self.renderContext.get(argument._keypath);
+ } else {
+ return argument;
+ }
+ });
+ args.unshift(value);
+ while (args.length < (fn.length - 1)) {
+ args.push(void 0);
+ }
+ args.push(self);
+ return fn.apply(renderContext, args);
+ }, unfilteredValue);
+ Batman.developer.currentFilterStack = null;
+ return result;
+ } else {
+ return unfilteredValue;
+ }
+ },
+ set: function(_, newValue) {
+ return this.set('unfilteredValue', newValue);
+ }
+ });
+
+ AbstractBinding.accessor('unfilteredValue', {
+ get: function() {
+ var k;
+ if (k = this.get('key')) {
+ return Batman.RenderContext.deProxy(Batman.getPath(this, ['keyContext', k]));
+ } else {
+ return this.get('value');
+ }
+ },
+ set: function(_, value) {
+ var k, keyContext, prop;
+ if (k = this.get('key')) {
+ keyContext = this.get('keyContext');
+ if (keyContext && keyContext !== Batman.container) {
+ prop = Batman.Property.forBaseAndKey(keyContext, k);
+ return prop.setValue(value);
+ }
+ } else {
+ return this.set('value', value);
+ }
+ }
+ });
+
+ AbstractBinding.accessor('keyContext', function() {
+ return this.renderContext.contextForKey(this.key);
+ });
+
+ AbstractBinding.prototype.bindImmediately = true;
+
+ AbstractBinding.prototype.shouldSet = true;
+
+ AbstractBinding.prototype.isInputBinding = false;
+
+ AbstractBinding.prototype.escapeValue = true;
+
+ function AbstractBinding(node, keyPath, renderContext, renderer, only) {
+ this.node = node;
+ this.keyPath = keyPath;
+ this.renderContext = renderContext;
+ this.renderer = renderer;
+ this.only = only != null ? only : false;
+ this._fireDataChange = __bind(this._fireDataChange, this);
+
+ this._fireNodeChange = __bind(this._fireNodeChange, this);
+
+ this.parseFilter();
+ if (this.bindImmediately) {
+ this.bind();
+ }
+ }
+
+ AbstractBinding.prototype.isTwoWay = function() {
+ return (this.key != null) && this.filterFunctions.length === 0;
+ };
+
+ AbstractBinding.prototype.bind = function() {
+ var _ref, _ref1;
+ if ((this.node != null) && ((_ref = this.only) === false || _ref === 'nodeChange') && Batman.DOM.nodeIsEditable(this.node)) {
+ Batman.DOM.events.change(this.node, this._fireNodeChange);
+ if (this.only === 'nodeChange') {
+ this._fireNodeChange();
+ }
+ }
+ if ((_ref1 = this.only) === false || _ref1 === 'dataChange') {
+ this.observeAndFire('filteredValue', this._fireDataChange);
+ }
+ if (this.node != null) {
+ return Batman.DOM.trackBinding(this, this.node);
+ }
+ };
+
+ AbstractBinding.prototype._fireNodeChange = function(event) {
+ var val;
+ this.shouldSet = false;
+ val = this.value || this.get('keyContext');
+ if (typeof this.nodeChange === "function") {
+ this.nodeChange(this.node, val, event);
+ }
+ this.fire('nodeChange', this.node, val);
+ return this.shouldSet = true;
+ };
+
+ AbstractBinding.prototype._fireDataChange = function(value) {
+ if (this.shouldSet) {
+ if (typeof this.dataChange === "function") {
+ this.dataChange(value, this.node);
+ }
+ return this.fire('dataChange', value, this.node);
+ }
+ };
+
+ AbstractBinding.prototype.die = function() {
+ var _ref;
+ this.forget();
+ if ((_ref = this._batman.properties) != null) {
+ _ref.forEach(function(key, property) {
+ return property.die();
+ });
+ }
+ this.fire('die');
+ this.dead = true;
+ return true;
+ };
+
+ AbstractBinding.prototype.parseFilter = function() {
+ var args, filter, filterName, filterString, filters, key, keyPath, orig, split;
+ this.filterFunctions = [];
+ this.filterArguments = [];
+ keyPath = this.keyPath;
+ while (get_dot_rx.test(keyPath)) {
+ keyPath = keyPath.replace(get_dot_rx, "]['$1']");
+ }
+ filters = keyPath.replace(get_rx, " | get $1 ").replace(/'/g, '"').split(/(?!")\s+\|\s+(?!")/);
+ try {
+ key = this.parseSegment(orig = filters.shift())[0];
+ } catch (e) {
+ Batman.developer.warn(e);
+ Batman.developer.error("Error! Couldn't parse keypath in \"" + orig + "\". Parsing error above.");
+ }
+ if (key && key._keypath) {
+ this.key = key._keypath;
+ } else {
+ this.value = key;
+ }
+ if (filters.length) {
+ while (filterString = filters.shift()) {
+ split = filterString.indexOf(' ');
+ if (split === -1) {
+ split = filterString.length;
+ }
+ filterName = filterString.substr(0, split);
+ args = filterString.substr(split);
+ if (!(filter = Batman.Filters[filterName])) {
+ return Batman.developer.error("Unrecognized filter '" + filterName + "' in key \"" + this.keyPath + "\"!");
+ }
+ this.filterFunctions.push(filter);
+ try {
+ this.filterArguments.push(this.parseSegment(args));
+ } catch (e) {
+ Batman.developer.error("Bad filter arguments \"" + args + "\"!");
+ }
+ }
+ return true;
+ }
+ };
+
+ AbstractBinding.prototype.parseSegment = function(segment) {
+ segment = segment.replace(keypath_rx, function(match, start, bool, string, object, keypath, offset) {
+ var replacement;
+ if (start == null) {
+ start = '';
+ }
+ replacement = keypath ? '{"_keypath": "' + keypath + '"}' : bool || string || object;
+ return start + replacement;
+ });
+ return JSON.parse("[" + segment + "]");
+ };
+
+ return AbstractBinding;
+
+ })(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.DOM.ViewBinding = (function(_super) {
+
+ __extends(ViewBinding, _super);
+
+ function ViewBinding() {
+ ViewBinding.__super__.constructor.apply(this, arguments);
+ this.renderer.prevent('rendered');
+ this.node.removeAttribute('data-view');
+ }
+
+ ViewBinding.prototype.dataChange = function(viewClassOrInstance) {
+ var _this = this;
+ if (viewClassOrInstance == null) {
+ return;
+ }
+ if (viewClassOrInstance.isView) {
+ this.view = viewClassOrInstance;
+ this.view.set('context', this.renderContext);
+ this.view.set('node', this.node);
+ } else {
+ this.view = new viewClassOrInstance({
+ node: this.node,
+ context: this.renderContext,
+ parentView: this.renderer.view
+ });
+ }
+ this.view.on('ready', function() {
+ return _this.renderer.allowAndFire('rendered');
+ });
+ return this.die();
+ };
+
+ return ViewBinding;
+
+ })(Batman.DOM.AbstractBinding);
+
+}).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.DOM.ViewArgumentBinding = (function(_super) {
+
+ __extends(ViewArgumentBinding, _super);
+
+ function ViewArgumentBinding() {
+ return ViewArgumentBinding.__super__.constructor.apply(this, arguments);
+ }
+
+ return ViewArgumentBinding;
+
+ })(Batman.DOM.AbstractBinding);
+
+}).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.DOM.ShowHideBinding = (function(_super) {
+
+ __extends(ShowHideBinding, _super);
+
+ function ShowHideBinding(node, className, key, context, parentRenderer, invert) {
+ var display;
+ this.invert = invert != null ? invert : false;
+ display = node.style.display;
+ if (!display || display === 'none') {
+ display = '';
+ }
+ this.originalDisplay = display;
+ ShowHideBinding.__super__.constructor.apply(this, arguments);
+ }
+
+ ShowHideBinding.prototype.dataChange = function(value) {
+ var hide, view, _ref;
+ view = Batman._data(this.node, 'view');
+ if (!!value === !this.invert) {
+ if (view != null) {
+ view.fire('beforeAppear', this.node);
+ }
+ if ((_ref = Batman.data(this.node, 'show')) != null) {
+ _ref.call(this.node);
+ }
+ this.node.style.display = this.originalDisplay;
+ return view != null ? view.fire('appear', this.node) : void 0;
+ } else {
+ if (view != null) {
+ view.fire('beforeDisappear', this.node);
+ }
+ if (typeof (hide = Batman.data(this.node, 'hide')) === 'function') {
+ hide.call(this.node);
+ } else {
+ Batman.setStyleProperty(this.node, 'display', 'none', 'important');
+ }
+ return view != null ? view.fire('disappear', this.node) : void 0;
+ }
+ };
+
+ return ShowHideBinding;
+
+ })(Batman.DOM.AbstractBinding);
+
+}).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; };
+
+ Batman.DOM.SelectBinding = (function(_super) {
+
+ __extends(SelectBinding, _super);
+
+ SelectBinding.prototype.isInputBinding = true;
+
+ SelectBinding.prototype.firstBind = true;
+
+ function SelectBinding() {
+ this.updateOptionBindings = __bind(this.updateOptionBindings, this);
+
+ this.nodeChange = __bind(this.nodeChange, this);
+
+ this.dataChange = __bind(this.dataChange, this);
+
+ this.childBindingAdded = __bind(this.childBindingAdded, this);
+ this.selectedBindings = new Batman.SimpleSet;
+ SelectBinding.__super__.constructor.apply(this, arguments);
+ }
+
+ SelectBinding.prototype.childBindingAdded = function(binding) {
+ var dataChangeHandler,
+ _this = this;
+ if (binding instanceof Batman.DOM.CheckedBinding) {
+ binding.on('dataChange', dataChangeHandler = function() {
+ return _this.nodeChange();
+ });
+ binding.on('die', function() {
+ binding.forget('dataChange', dataChangeHandler);
+ return _this.selectedBindings.remove(binding);
+ });
+ this.selectedBindings.add(binding);
+ } else if (binding instanceof Batman.DOM.IteratorBinding) {
+ binding.on('nodeAdded', dataChangeHandler = function() {
+ return _this._fireDataChange(_this.get('filteredValue'));
+ });
+ binding.on('nodeRemoved', dataChangeHandler);
+ binding.on('die', function() {
+ binding.forget('nodeAdded', dataChangeHandler);
+ return binding.forget('nodeRemoved', dataChangeHandler);
+ });
+ } else {
+ return;
+ }
+ return this._fireDataChange(this.get('filteredValue'));
+ };
+
+ SelectBinding.prototype.dataChange = function(newValue) {
+ var child, matches, valueToChild, _i, _len, _name, _ref,
+ _this = this;
+ if (newValue != null ? newValue.forEach : void 0) {
+ valueToChild = {};
+ _ref = this.node.children;
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ child = _ref[_i];
+ child.selected = false;
+ matches = valueToChild[_name = child.value] || (valueToChild[_name] = []);
+ matches.push(child);
+ }
+ newValue.forEach(function(value) {
+ var children, node, _j, _len1, _results;
+ if (children = valueToChild[value]) {
+ _results = [];
+ for (_j = 0, _len1 = children.length; _j < _len1; _j++) {
+ node = children[_j];
+ _results.push(node.selected = true);
+ }
+ return _results;
+ }
+ });
+ } else {
+ if (typeof newValue === 'undefined' && this.firstBind) {
+ this.set('unfilteredValue', this.node.value);
+ } else {
+ Batman.DOM.valueForNode(this.node, newValue, this.escapeValue);
+ }
+ this.firstBind = false;
+ }
+ this.updateOptionBindings();
+ };
+
+ SelectBinding.prototype.nodeChange = function() {
+ var c, selections;
+ if (this.isTwoWay()) {
+ selections = this.node.multiple ? (function() {
+ var _i, _len, _ref, _results;
+ _ref = this.node.children;
+ _results = [];
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ c = _ref[_i];
+ if (c.selected) {
+ _results.push(c.value);
+ }
+ }
+ return _results;
+ }).call(this) : this.node.value;
+ if (typeof selections === Array && selections.length === 1) {
+ selections = selections[0];
+ }
+ this.set('unfilteredValue', selections);
+ this.updateOptionBindings();
+ }
+ };
+
+ SelectBinding.prototype.updateOptionBindings = function() {
+ return this.selectedBindings.forEach(function(binding) {
+ return binding._fireNodeChange();
+ });
+ };
+
+ return SelectBinding;
+
+ })(Batman.DOM.AbstractBinding);
+
+}).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.DOM.RouteBinding = (function(_super) {
+
+ __extends(RouteBinding, _super);
+
+ function RouteBinding() {
+ return RouteBinding.__super__.constructor.apply(this, arguments);
+ }
+
+ RouteBinding.prototype.onATag = false;
+
+ RouteBinding.accessor('dispatcher', function() {
+ return this.renderContext.get('dispatcher') || Batman.App.get('current.dispatcher');
+ });
+
+ RouteBinding.prototype.bind = function() {
+ var _this = this;
+ if (this.node.nodeName.toUpperCase() === 'A') {
+ this.onATag = true;
+ }
+ RouteBinding.__super__.bind.apply(this, arguments);
+ return Batman.DOM.events.click(this.node, function(node, event) {
+ var params;
+ if (event.__batmanActionTaken) {
+ return;
+ }
+ event.__batmanActionTaken = true;
+ params = _this.pathFromValue(_this.get('filteredValue'));
+ if (params != null) {
+ return Batman.redirect(params);
+ }
+ });
+ };
+
+ RouteBinding.prototype.dataChange = function(value) {
+ var path;
+ if (value != null) {
+ path = this.pathFromValue(value);
+ }
+ if (this.onATag) {
+ if ((path != null) && (Batman.navigator != null)) {
+ path = Batman.navigator.linkTo(path);
+ } else {
+ path = "#";
+ }
+ return this.node.href = path;
+ }
+ };
+
+ RouteBinding.prototype.pathFromValue = function(value) {
+ var _ref;
+ if (value != null) {
+ if (value.isNamedRouteQuery) {
+ return value.get('path');
+ } else {
+ return (_ref = this.get('dispatcher')) != null ? _ref.pathFromParams(value) : void 0;
+ }
+ }
+ };
+
+ return RouteBinding;
+
+ })(Batman.DOM.AbstractBinding);
+
+}).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.DOM.RadioBinding = (function(_super) {
+
+ __extends(RadioBinding, _super);
+
+ function RadioBinding() {
+ return RadioBinding.__super__.constructor.apply(this, arguments);
+ }
+
+ RadioBinding.accessor('parsedNodeValue', function() {
+ return Batman.DOM.attrReaders._parseAttribute(this.node.value);
+ });
+
+ RadioBinding.prototype.firstBind = true;
+
+ RadioBinding.prototype.dataChange = function(value) {
+ var boundValue;
+ boundValue = this.get('filteredValue');
+ if (boundValue != null) {
+ this.node.checked = boundValue === Batman.DOM.attrReaders._parseAttribute(this.node.value);
+ } else {
+ if (this.firstBind && this.node.checked) {
+ this.set('filteredValue', this.get('parsedNodeValue'));
+ }
+ }
+ return this.firstBind = false;
+ };
+
+ RadioBinding.prototype.nodeChange = function(node) {
+ if (this.isTwoWay()) {
+ return this.set('filteredValue', this.get('parsedNodeValue'));
+ }
+ };
+
+ return RadioBinding;
+
+ })(Batman.DOM.AbstractBinding);
+
+}).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.DOM.MixinBinding = (function(_super) {
+
+ __extends(MixinBinding, _super);
+
+ function MixinBinding() {
+ return MixinBinding.__super__.constructor.apply(this, arguments);
+ }
+
+ MixinBinding.prototype.dataChange = function(value) {
+ if (value != null) {
+ return Batman.mixin(this.node, value);
+ }
+ };
+
+ return MixinBinding;
+
+ })(Batman.DOM.AbstractBinding);
+
+}).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.DOM.FileBinding = (function(_super) {
+
+ __extends(FileBinding, _super);
+
+ function FileBinding() {
+ return FileBinding.__super__.constructor.apply(this, arguments);
+ }
+
+ FileBinding.prototype.isInputBinding = true;
+
+ FileBinding.prototype.nodeChange = function(node, subContext) {
+ if (!this.isTwoWay()) {
+ return;
+ }
+ if (node.hasAttribute('multiple')) {
+ return this.set('filteredValue', Array.prototype.slice.call(node.files));
+ } else {
+ return this.set('filteredValue', node.files[0]);
+ }
+ };
+
+ return FileBinding;
+
+ })(Batman.DOM.AbstractBinding);
+
+}).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.DOM.DeferredRenderingBinding = (function(_super) {
+
+ __extends(DeferredRenderingBinding, _super);
+
+ DeferredRenderingBinding.prototype.rendered = false;
+
+ function DeferredRenderingBinding() {
+ DeferredRenderingBinding.__super__.constructor.apply(this, arguments);
+ this.node.removeAttribute("data-renderif");
+ }
+
+ DeferredRenderingBinding.prototype.nodeChange = function() {};
+
+ DeferredRenderingBinding.prototype.dataChange = function(value) {
+ if (value && !this.rendered) {
+ return this.render();
+ }
+ };
+
+ DeferredRenderingBinding.prototype.render = function() {
+ new Batman.Renderer(this.node, this.renderContext, this.renderer.view);
+ return this.rendered = true;
+ };
+
+ return DeferredRenderingBinding;
+
+ })(Batman.DOM.AbstractBinding);
+
+}).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.DOM.Binding = (function(_super) {
+
+ __extends(Binding, _super);
+
+ function Binding(node) {
+ var _ref;
+ this.isInputBinding = (_ref = node.nodeName.toLowerCase()) === 'input' || _ref === 'textarea';
+ Binding.__super__.constructor.apply(this, arguments);
+ }
+
+ Binding.prototype.nodeChange = function(node, context) {
+ if (this.isTwoWay()) {
+ return this.set('filteredValue', this.node.value);
+ }
+ };
+
+ Binding.prototype.dataChange = function(value, node) {
+ return Batman.DOM.valueForNode(this.node, value, this.escapeValue);
+ };
+
+ return Binding;
+
+ })(Batman.DOM.AbstractBinding);
+
+}).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.DOM.AbstractAttributeBinding = (function(_super) {
+
+ __extends(AbstractAttributeBinding, _super);
+
+ function AbstractAttributeBinding() {
+ var args, attributeName, node;
+ node = arguments[0], attributeName = arguments[1], args = 3 <= arguments.length ? __slice.call(arguments, 2) : [];
+ this.attributeName = attributeName;
+ AbstractAttributeBinding.__super__.constructor.apply(this, [node].concat(__slice.call(args)));
+ }
+
+ return AbstractAttributeBinding;
+
+ })(Batman.DOM.AbstractBinding);
+
+}).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; };
+
+ Batman.DOM.FormBinding = (function(_super) {
+
+ __extends(FormBinding, _super);
+
+ FormBinding.current = null;
+
+ FormBinding.prototype.errorClass = 'error';
+
+ FormBinding.prototype.defaultErrorsListSelector = 'div.errors';
+
+ FormBinding.accessor('errorsListSelector', function() {
+ return this.get('node').getAttribute('data-errors-list') || this.defaultErrorsListSelector;
+ });
+
+ function FormBinding(node, contextName, keyPath, renderContext, renderer, only) {
+ this.childBindingAdded = __bind(this.childBindingAdded, this);
+ FormBinding.__super__.constructor.apply(this, arguments);
+ this.contextName = contextName;
+ delete this.attributeName;
+ Batman.DOM.events.submit(this.get('node'), function(node, e) {
+ return Batman.preventDefault(e);
+ });
+ this.setupErrorsList();
+ }
+
+ FormBinding.prototype.childBindingAdded = function(binding) {
+ var field, index, node;
+ if (binding.isInputBinding && Batman.isChildOf(this.get('node'), binding.get('node'))) {
+ if (~(index = binding.get('key').indexOf(this.contextName))) {
+ node = binding.get('node');
+ field = binding.get('key').slice(index + this.contextName.length + 1);
+ return new Batman.DOM.AddClassBinding(node, this.errorClass, this.get('keyPath') + (" | get 'errors." + field + ".length'"), this.renderContext, this.renderer);
+ }
+ }
+ };
+
+ FormBinding.prototype.setupErrorsList = function() {
+ if (this.errorsListNode = Batman.DOM.querySelector(this.get('node'), this.get('errorsListSelector'))) {
+ Batman.setInnerHTML(this.errorsListNode, this.errorsListHTML());
+ if (!this.errorsListNode.getAttribute('data-showif')) {
+ return this.errorsListNode.setAttribute('data-showif', "" + this.contextName + ".errors.length");
+ }
+ }
+ };
+
+ FormBinding.prototype.errorsListHTML = function() {
+ return "<ul>\n <li data-foreach-error=\"" + this.contextName + ".errors\" data-bind=\"error.fullMessage\"></li>\n</ul>";
+ };
+
+ return FormBinding;
+
+ })(Batman.DOM.AbstractAttributeBinding);
+
+}).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.DOM.EventBinding = (function(_super) {
+
+ __extends(EventBinding, _super);
+
+ EventBinding.prototype.bindImmediately = false;
+
+ function EventBinding(node, eventName, key, context) {
+ var attacher, callback, confirmText,
+ _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]) {
+ attacher(this.node, callback, context);
+ } else {
+ Batman.DOM.events.other(this.node, this.attributeName, callback, context);
+ }
+ this.bind();
+ }
+
+ EventBinding.accessor('callbackContext', function() {
+ var contextKeySegments;
+ contextKeySegments = this.key.split('.');
+ contextKeySegments.pop();
+ if (contextKeySegments.length > 0) {
+ return this.get('keyContext').get(contextKeySegments.join('.'));
+ } else {
+ return this.get('keyContext');
+ }
+ });
+
+ EventBinding.wrapAccessor('unfilteredValue', function(core) {
+ return {
+ get: function() {
+ var functionKey, k, keyContext, keys;
+ if (k = this.get('key')) {
+ keys = k.split('.');
+ if (keys.length > 1) {
+ functionKey = keys.pop();
+ keyContext = Batman.getPath(this, ['keyContext'].concat(keys));
+ if (keyContext != null) {
+ keyContext = Batman.RenderContext.deProxy(keyContext);
+ return keyContext[functionKey];
+ }
+ }
+ }
+ return core.get.apply(this, arguments);
+ }
+ };
+ });
+
+ return EventBinding;
+
+ })(Batman.DOM.AbstractAttributeBinding);
+
+}).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.DOM.NodeAttributeBinding = (function(_super) {
+
+ __extends(NodeAttributeBinding, _super);
+
+ function NodeAttributeBinding() {
+ return NodeAttributeBinding.__super__.constructor.apply(this, arguments);
+ }
+
+ NodeAttributeBinding.prototype.dataChange = function(value) {
+ if (value == null) {
+ value = "";
+ }
+ return this.node[this.attributeName] = value;
+ };
+
+ NodeAttributeBinding.prototype.nodeChange = function(node) {
+ if (this.isTwoWay()) {
+ return this.set('filteredValue', Batman.DOM.attrReaders._parseAttribute(node[this.attributeName]));
+ }
+ };
+
+ return NodeAttributeBinding;
+
+ })(Batman.DOM.AbstractAttributeBinding);
+
+}).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.DOM.CheckedBinding = (function(_super) {
+
+ __extends(CheckedBinding, _super);
+
+ function CheckedBinding() {
+ return CheckedBinding.__super__.constructor.apply(this, arguments);
+ }
+
+ CheckedBinding.prototype.isInputBinding = true;
+
+ CheckedBinding.prototype.dataChange = function(value) {
+ return this.node[this.attributeName] = !!value;
+ };
+
+ return CheckedBinding;
+
+ })(Batman.DOM.NodeAttributeBinding);
+
+}).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.DOM.AttributeBinding = (function(_super) {
+
+ __extends(AttributeBinding, _super);
+
+ function AttributeBinding() {
+ return AttributeBinding.__super__.constructor.apply(this, arguments);
+ }
+
+ AttributeBinding.prototype.dataChange = function(value) {
+ return this.node.setAttribute(this.attributeName, value);
+ };
+
+ AttributeBinding.prototype.nodeChange = function(node) {
+ if (this.isTwoWay()) {
+ return this.set('filteredValue', Batman.DOM.attrReaders._parseAttribute(node.getAttribute(this.attributeName)));
+ }
+ };
+
+ return AttributeBinding;
+
+ })(Batman.DOM.AbstractAttributeBinding);
+
+}).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.DOM.AddClassBinding = (function(_super) {
+
+ __extends(AddClassBinding, _super);
+
+ function AddClassBinding(node, className, keyPath, renderContext, renderer, only, invert) {
+ var name, names;
+ this.invert = invert != null ? invert : false;
+ names = className.split('|');
+ this.classes = (function() {
+ var _i, _len, _results;
+ _results = [];
+ for (_i = 0, _len = names.length; _i < _len; _i++) {
+ name = names[_i];
+ _results.push({
+ name: name,
+ pattern: new RegExp("(?:^|\\s)" + name + "(?:$|\\s)", 'i')
+ });
+ }
+ return _results;
+ })();
+ AddClassBinding.__super__.constructor.apply(this, arguments);
+ delete this.attributeName;
+ }
+
+ AddClassBinding.prototype.dataChange = function(value) {
+ var currentName, includesClassName, name, pattern, _i, _len, _ref, _ref1;
+ currentName = this.node.className;
+ _ref = this.classes;
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ _ref1 = _ref[_i], name = _ref1.name, pattern = _ref1.pattern;
+ includesClassName = pattern.test(currentName);
+ if (!!value === !this.invert) {
+ if (!includesClassName) {
+ this.node.className = "" + currentName + " " + name;
+ }
+ } else {
+ if (includesClassName) {
+ this.node.className = currentName.replace(pattern, ' ');
+ }
+ }
+ }
+ return true;
+ };
+
+ return AddClassBinding;
+
+ })(Batman.DOM.AbstractAttributeBinding);
+
+}).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.DOM.AbstractCollectionBinding = (function(_super) {
+
+ __extends(AbstractCollectionBinding, _super);
+
+ function AbstractCollectionBinding() {
+ return AbstractCollectionBinding.__super__.constructor.apply(this, arguments);
+ }
+
+ AbstractCollectionBinding.prototype.bindCollection = function(newCollection) {
+ var _ref;
+ if (newCollection instanceof Batman.Hash) {
+ newCollection = newCollection.meta;
+ }
+ if (newCollection === this.collection) {
+ return true;
+ } else {
+ this.unbindCollection();
+ this.collection = newCollection;
+ if ((_ref = this.collection) != null ? _ref.isObservable : void 0) {
+ this.collection.observeAndFire('toArray', this.handleArrayChanged);
+ return true;
+ }
+ }
+ return false;
+ };
+
+ AbstractCollectionBinding.prototype.unbindCollection = function() {
+ var _ref;
+ if ((_ref = this.collection) != null ? _ref.isObservable : void 0) {
+ return this.collection.forget('toArray', this.handleArrayChanged);
+ }
+ };
+
+ AbstractCollectionBinding.prototype.handleArrayChanged = function() {};
+
+ AbstractCollectionBinding.prototype.die = function() {
+ this.unbindCollection();
+ return AbstractCollectionBinding.__super__.die.apply(this, arguments);
+ };
+
+ return AbstractCollectionBinding;
+
+ })(Batman.DOM.AbstractAttributeBinding);
+
+}).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.DOM.StyleBinding = (function(_super) {
+
+ __extends(StyleBinding, _super);
+
+ StyleBinding.SingleStyleBinding = (function(_super1) {
+
+ __extends(SingleStyleBinding, _super1);
+
+ SingleStyleBinding.prototype.isTwoWay = function() {
+ return false;
+ };
+
+ function SingleStyleBinding() {
+ var args, parent, _i;
+ args = 2 <= arguments.length ? __slice.call(arguments, 0, _i = arguments.length - 1) : (_i = 0, []), parent = arguments[_i++];
+ this.parent = parent;
+ SingleStyleBinding.__super__.constructor.apply(this, args);
+ }
+
+ SingleStyleBinding.prototype.dataChange = function(value) {
+ return this.parent.setStyle(this.attributeName, value);
+ };
+
+ return SingleStyleBinding;
+
+ })(Batman.DOM.AbstractAttributeBinding);
+
+ function StyleBinding() {
+ this.setStyle = __bind(this.setStyle, this);
+
+ this.handleArrayChanged = __bind(this.handleArrayChanged, this);
+ this.oldStyles = {};
+ this.styleBindings = {};
+ StyleBinding.__super__.constructor.apply(this, arguments);
+ }
+
+ StyleBinding.prototype.dataChange = function(value) {
+ var colonSplitCSSValues, cssName, key, style, _i, _len, _ref, _ref1, _results;
+ if (!value) {
+ this.resetStyles();
+ return;
+ }
+ this.unbindCollection();
+ if (typeof value === 'string') {
+ this.resetStyles();
+ _ref = value.split(';');
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ style = _ref[_i];
+ _ref1 = style.split(":"), cssName = _ref1[0], colonSplitCSSValues = 2 <= _ref1.length ? __slice.call(_ref1, 1) : [];
+ this.setStyle(cssName, colonSplitCSSValues.join(":"));
+ }
+ return;
+ }
+ if (value instanceof Batman.Hash) {
+ return this.bindCollection(value);
+ } else {
+ if (value instanceof Batman.Object) {
+ value = value.toJSON();
+ }
+ this.resetStyles();
+ _results = [];
+ for (key in value) {
+ if (!__hasProp.call(value, key)) continue;
+ _results.push(this.bindSingleAttribute(key, "" + this.keyPath + "." + key));
+ }
+ return _results;
+ }
+ };
+
+ StyleBinding.prototype.handleArrayChanged = function(array) {
+ var _this = this;
+ return this.collection.forEach(function(key, value) {
+ return _this.bindSingleAttribute(key, "" + _this.keyPath + "." + key);
+ });
+ };
+
+ StyleBinding.prototype.bindSingleAttribute = function(attr, keyPath) {
+ return this.styleBindings[attr] = new this.constructor.SingleStyleBinding(this.node, attr, keyPath, this.renderContext, this.renderer, this.only, this);
+ };
+
+ StyleBinding.prototype.setStyle = function(key, value) {
+ key = Batman.helpers.camelize(key.trim(), true);
+ if (this.oldStyles[key] == null) {
+ this.oldStyles[key] = this.node.style[key] || "";
+ }
+ if (value != null ? value.trim : void 0) {
+ value = value.trim();
+ }
+ if (value == null) {
+ value = "";
+ }
+ return this.node.style[key] = value;
+ };
+
+ StyleBinding.prototype.resetStyles = function() {
+ var cssName, cssValue, _ref, _results;
+ _ref = this.oldStyles;
+ _results = [];
+ for (cssName in _ref) {
+ if (!__hasProp.call(_ref, cssName)) continue;
+ cssValue = _ref[cssName];
+ _results.push(this.setStyle(cssName, cssValue));
+ }
+ return _results;
+ };
+
+ StyleBinding.prototype.resetBindings = function() {
+ var attribute, binding, _ref;
+ _ref = this.styleBindings;
+ for (attribute in _ref) {
+ binding = _ref[attribute];
+ binding._fireDataChange('');
+ binding.die();
+ }
+ return this.styleBindings = {};
+ };
+
+ StyleBinding.prototype.unbindCollection = function() {
+ this.resetBindings();
+ return StyleBinding.__super__.unbindCollection.apply(this, arguments);
+ };
+
+ return StyleBinding;
+
+ })(Batman.DOM.AbstractCollectionBinding);
+
+}).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; };
+
+ Batman.DOM.IteratorBinding = (function(_super) {
+
+ __extends(IteratorBinding, _super);
+
+ IteratorBinding.prototype.currentActionNumber = 0;
+
+ IteratorBinding.prototype.queuedActionNumber = 0;
+
+ IteratorBinding.prototype.bindImmediately = false;
+
+ function IteratorBinding(sourceNode, iteratorName, key, context, parentRenderer) {
+ var previousSiblingNode,
+ _this = this;
+ this.iteratorName = iteratorName;
+ this.key = key;
+ this.context = context;
+ this.parentRenderer = parentRenderer;
+ this.handleArrayChanged = __bind(this.handleArrayChanged, this);
+
+ this.nodeMap = new Batman.SimpleHash;
+ this.rendererMap = new Batman.SimpleHash;
+ this.fragment = document.createDocumentFragment();
+ this.prototypeNode = sourceNode.cloneNode(true);
+ this.prototypeNode.removeAttribute("data-foreach-" + this.iteratorName);
+ previousSiblingNode = sourceNode.nextSibling;
+ this.startNode = document.createComment("start " + this.iteratorName + "-" + (this.get('_batmanID')));
+ this.endNode = document.createComment("end " + this.iteratorName + "-" + (this.get('_batmanID')));
+ this.endNode[Batman.expando] = sourceNode[Batman.expando];
+ if (Batman.canDeleteExpando) {
+ delete sourceNode[Batman.expando];
+ }
+ Batman.insertBefore(sourceNode.parentNode, this.startNode, previousSiblingNode);
+ Batman.insertBefore(sourceNode.parentNode, this.endNode, previousSiblingNode);
+ this.parentRenderer.prevent('rendered');
+ Batman.DOM.onParseExit(sourceNode.parentNode, function() {
+ Batman.destroyNode(sourceNode);
+ _this.bind();
+ return _this.parentRenderer.allowAndFire('rendered');
+ });
+ IteratorBinding.__super__.constructor.call(this, this.endNode, this.iteratorName, this.key, this.context, this.parentRenderer);
+ }
+
+ IteratorBinding.prototype.parentNode = function() {
+ return this.endNode.parentNode;
+ };
+
+ IteratorBinding.prototype.die = function() {
+ this.dead = true;
+ return IteratorBinding.__super__.die.apply(this, arguments);
+ };
+
+ IteratorBinding.prototype.dataChange = function(collection) {
+ var items, _items;
+ if (collection != null) {
+ if (!this.bindCollection(collection)) {
+ items = (collection != null ? collection.forEach : void 0) ? (_items = [], collection.forEach(function(item) {
+ return _items.push(item);
+ }), _items) : Object.keys(collection);
+ return this.handleArrayChanged(items);
+ }
+ } else {
+ return this.handleArrayChanged([]);
+ }
+ };
+
+ IteratorBinding.prototype.handleArrayChanged = function(newItems) {
+ var existingNode, index, newItem, node, nodeAtIndex, parentNode, startIndex, unseenNodeMap, _i, _len,
+ _this = this;
+ 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);
+ }
+ }
+ unseenNodeMap.forEach(function(item, node) {
+ return _this._removeItem(item);
+ });
+ };
+
+ IteratorBinding.prototype._itemForNode = function(node) {
+ return Batman._data(node, "" + this.iteratorName + "Item");
+ };
+
+ IteratorBinding.prototype._newNodeForItem = function(newItem) {
+ var newNode, renderer,
+ _this = this;
+ newNode = this.prototypeNode.cloneNode(true);
+ Batman._data(newNode, "" + this.iteratorName + "Item", newItem);
+ this.nodeMap.set(newItem, newNode);
+ 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);
+ _this.fire('nodeAdded', newNode, newItem);
+ return _this.parentRenderer.allowAndFire('rendered');
+ });
+ return newNode;
+ };
+
+ IteratorBinding.prototype._getStartNodeIndex = function() {
+ var index, node, _i, _len, _ref;
+ _ref = this.parentNode().childNodes;
+ for (index = _i = 0, _len = _ref.length; _i < _len; index = ++_i) {
+ node = _ref[index];
+ if (node === this.startNode) {
+ return index;
+ }
+ }
+ return 0;
+ };
+
+ IteratorBinding.prototype._removeItem = function(item) {
+ var node;
+ node = this.nodeMap.unset(item);
+ Batman.destroyNode(node);
+ return this.fire('nodeRemoved', node, item);
+ };
+
+ return IteratorBinding;
+
+ })(Batman.DOM.AbstractCollectionBinding);
+
+}).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; };
+
+ Batman.DOM.ClassBinding = (function(_super) {
+
+ __extends(ClassBinding, _super);
+
+ function ClassBinding() {
+ this.handleArrayChanged = __bind(this.handleArrayChanged, this);
+ return ClassBinding.__super__.constructor.apply(this, arguments);
+ }
+
+ ClassBinding.prototype.dataChange = function(value) {
+ if (value != null) {
+ this.unbindCollection();
+ if (typeof value === 'string') {
+ return this.node.className = value;
+ } else {
+ this.bindCollection(value);
+ return this.updateFromCollection();
+ }
+ }
+ };
+
+ ClassBinding.prototype.updateFromCollection = function() {
+ var array, k, v;
+ if (this.collection) {
+ array = this.collection.map ? this.collection.map(function(x) {
+ return x;
+ }) : (function() {
+ var _ref, _results;
+ _ref = this.collection;
+ _results = [];
+ for (k in _ref) {
+ if (!__hasProp.call(_ref, k)) continue;
+ v = _ref[k];
+ _results.push(k);
+ }
+ return _results;
+ }).call(this);
+ if (array.toArray != null) {
+ array = array.toArray();
+ }
+ return this.node.className = array.join(' ');
+ }
+ };
+
+ ClassBinding.prototype.handleArrayChanged = function() {
+ return this.updateFromCollection();
+ };
+
+ return ClassBinding;
+
+ })(Batman.DOM.AbstractCollectionBinding);
+
+}).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.ValidationError = (function(_super) {
+
+ __extends(ValidationError, _super);
+
+ ValidationError.accessor('fullMessage', function() {
+ return Batman.t('errors.format', {
+ attribute: Batman.helpers.humanize(this.attribute),
+ message: this.message
+ });
+ });
+
+ function ValidationError(attribute, message) {
+ ValidationError.__super__.constructor.call(this, {
+ attribute: attribute,
+ message: message
+ });
+ }
+
+ return ValidationError;
+
+ })(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;
+
+ Batman.StorageAdapter = (function(_super) {
+
+ __extends(StorageAdapter, _super);
+
+ StorageAdapter.StorageError = (function(_super1) {
+
+ __extends(StorageError, _super1);
+
+ StorageError.prototype.name = "StorageError";
+
+ function StorageError(message) {
+ StorageError.__super__.constructor.apply(this, arguments);
+ this.message = message;
+ }
+
+ return StorageError;
+
+ })(Error);
+
+ StorageAdapter.RecordExistsError = (function(_super1) {
+
+ __extends(RecordExistsError, _super1);
+
+ RecordExistsError.prototype.name = 'RecordExistsError';
+
+ function RecordExistsError(message) {
+ RecordExistsError.__super__.constructor.call(this, message || "Can't create this record because it already exists in the store!");
+ }
+
+ return RecordExistsError;
+
+ })(StorageAdapter.StorageError);
+
+ StorageAdapter.NotFoundError = (function(_super1) {
+
+ __extends(NotFoundError, _super1);
+
+ NotFoundError.prototype.name = 'NotFoundError';
+
+ function NotFoundError(message) {
+ NotFoundError.__super__.constructor.call(this, message || "Record couldn't be found in storage!");
+ }
+
+ return NotFoundError;
+
+ })(StorageAdapter.StorageError);
+
+ function StorageAdapter(model) {
+ var constructor;
+ StorageAdapter.__super__.constructor.call(this, {
+ model: model
+ });
+ constructor = this.constructor;
+ if (constructor.ModelMixin) {
+ Batman.extend(model, constructor.ModelMixin);
+ }
+ if (constructor.RecordMixin) {
+ Batman.extend(model.prototype, constructor.RecordMixin);
+ }
+ }
+
+ StorageAdapter.prototype.isStorageAdapter = true;
+
+ StorageAdapter.prototype.storageKey = function(record) {
+ var model;
+ model = (record != null ? record.constructor : void 0) || this.model;
+ return model.get('storageKey') || Batman.helpers.pluralize(Batman.helpers.underscore(model.get('resourceName')));
+ };
+
+ StorageAdapter.prototype.getRecordFromData = function(attributes, constructor) {
+ var record;
+ if (constructor == null) {
+ constructor = this.model;
+ }
+ record = new constructor();
+ record._withoutDirtyTracking(function() {
+ return this.fromJSON(attributes);
+ });
+ return record;
+ };
+
+ StorageAdapter.skipIfError = function(f) {
+ return function(env, next) {
+ if (env.error != null) {
+ return next();
+ } else {
+ return f.call(this, env, next);
+ }
+ };
+ };
+
+ StorageAdapter.prototype.before = function() {
+ return this._addFilter.apply(this, ['before'].concat(__slice.call(arguments)));
+ };
+
+ StorageAdapter.prototype.after = function() {
+ return this._addFilter.apply(this, ['after'].concat(__slice.call(arguments)));
+ };
+
+ StorageAdapter.prototype._inheritFilters = function() {
+ var filtersByKey, filtersList, key, oldFilters, position, _results;
+ if (!this._batman.check(this) || !this._batman.filters) {
+ oldFilters = this._batman.getFirst('filters');
+ this._batman.filters = {
+ before: {},
+ after: {}
+ };
+ if (oldFilters != null) {
+ _results = [];
+ for (position in oldFilters) {
+ filtersByKey = oldFilters[position];
+ _results.push((function() {
+ var _results1;
+ _results1 = [];
+ for (key in filtersByKey) {
+ filtersList = filtersByKey[key];
+ _results1.push(this._batman.filters[position][key] = filtersList.slice(0));
+ }
+ return _results1;
+ }).call(this));
+ }
+ return _results;
+ }
+ }
+ };
+
+ StorageAdapter.prototype._addFilter = function() {
+ var filter, key, keys, position, _base, _i, _j, _len;
+ position = arguments[0], keys = 3 <= arguments.length ? __slice.call(arguments, 1, _i = arguments.length - 1) : (_i = 1, []), filter = arguments[_i++];
+ this._inheritFilters();
+ for (_j = 0, _len = keys.length; _j < _len; _j++) {
+ key = keys[_j];
+ (_base = this._batman.filters[position])[key] || (_base[key] = []);
+ this._batman.filters[position][key].push(filter);
+ }
+ return true;
+ };
+
+ StorageAdapter.prototype.runFilter = function(position, action, env, callback) {
+ var actionFilters, allFilters, filters, next,
+ _this = this;
+ this._inheritFilters();
+ allFilters = this._batman.filters[position].all || [];
+ actionFilters = this._batman.filters[position][action] || [];
+ env.action = action;
+ filters = position === 'before' ? actionFilters.concat(allFilters) : allFilters.concat(actionFilters);
+ next = function(newEnv) {
+ var nextFilter;
+ if (newEnv != null) {
+ env = newEnv;
+ }
+ if ((nextFilter = filters.shift()) != null) {
+ return nextFilter.call(_this, env, next);
+ } else {
+ return callback.call(_this, env);
+ }
+ };
+ return next();
+ };
+
+ StorageAdapter.prototype.runBeforeFilter = function() {
+ return this.runFilter.apply(this, ['before'].concat(__slice.call(arguments)));
+ };
+
+ StorageAdapter.prototype.runAfterFilter = function(action, env, callback) {
+ return this.runFilter('after', action, env, this.exportResult(callback));
+ };
+
+ StorageAdapter.prototype.exportResult = function(callback) {
+ return function(env) {
+ return callback(env.error, env.result, env);
+ };
+ };
+
+ StorageAdapter.prototype._jsonToAttributes = function(json) {
+ return JSON.parse(json);
+ };
+
+ StorageAdapter.prototype.perform = function(key, subject, options, callback) {
+ var env, next,
+ _this = this;
+ options || (options = {});
+ env = {
+ options: options,
+ subject: subject
+ };
+ next = function(newEnv) {
+ if (newEnv != null) {
+ env = newEnv;
+ }
+ return _this.runAfterFilter(key, env, callback);
+ };
+ return this.runBeforeFilter(key, env, function(env) {
+ return this[key](env, next);
+ });
+ };
+
+ return StorageAdapter;
+
+ })(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,
+ __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.RestStorage = (function(_super) {
+ var key, _fn, _i, _len, _ref,
+ _this = this;
+
+ __extends(RestStorage, _super);
+
+ RestStorage.JSONContentType = 'application/json';
+
+ RestStorage.PostBodyContentType = 'application/x-www-form-urlencoded';
+
+ RestStorage.BaseMixin = {
+ request: function(action, options, callback) {
+ if (!callback) {
+ callback = options;
+ options = {};
+ }
+ options.method || (options.method = 'GET');
+ options.action = action;
+ return this._doStorageOperation(options.method.toLowerCase(), options, callback);
+ }
+ };
+
+ RestStorage.ModelMixin = Batman.extend({}, RestStorage.BaseMixin, {
+ urlNestsUnder: function() {
+ var key, keys, parents, _i, _len;
+ keys = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
+ parents = {};
+ for (_i = 0, _len = keys.length; _i < _len; _i++) {
+ key = keys[_i];
+ parents[key + '_id'] = Batman.helpers.pluralize(key);
+ }
+ this.url = function(options) {
+ var childSegment, parentID, plural;
+ childSegment = Batman.helpers.pluralize(this.get('resourceName').toLowerCase());
+ for (key in parents) {
+ plural = parents[key];
+ parentID = options.data[key];
+ if (parentID) {
+ delete options.data[key];
+ return "" + plural + "/" + parentID + "/" + childSegment;
+ }
+ }
+ return childSegment;
+ };
+ return this.prototype.url = function() {
+ var childSegment, id, parentID, plural, url;
+ childSegment = Batman.helpers.pluralize(this.constructor.get('resourceName').toLowerCase());
+ for (key in parents) {
+ plural = parents[key];
+ parentID = this.get('dirtyKeys').get(key);
+ if (parentID === void 0) {
+ parentID = this.get(key);
+ }
+ if (parentID) {
+ url = "" + plural + "/" + parentID + "/" + childSegment;
+ break;
+ }
+ }
+ url || (url = childSegment);
+ if (id = this.get('id')) {
+ url += '/' + id;
+ }
+ return url;
+ };
+ }
+ });
+
+ RestStorage.RecordMixin = Batman.extend({}, RestStorage.BaseMixin);
+
+ RestStorage.prototype.defaultRequestOptions = {
+ type: 'json'
+ };
+
+ RestStorage.prototype._implicitActionNames = ['create', 'read', 'update', 'destroy', 'readAll'];
+
+ RestStorage.prototype.serializeAsForm = true;
+
+ function RestStorage() {
+ RestStorage.__super__.constructor.apply(this, arguments);
+ this.defaultRequestOptions = Batman.extend({}, this.defaultRequestOptions);
+ }
+
+ RestStorage.prototype.recordJsonNamespace = function(record) {
+ return Batman.helpers.singularize(this.storageKey(record));
+ };
+
+ RestStorage.prototype.collectionJsonNamespace = function(constructor) {
+ return Batman.helpers.pluralize(this.storageKey(constructor.prototype));
+ };
+
+ RestStorage.prototype._execWithOptions = function(object, key, options) {
+ if (typeof object[key] === 'function') {
+ return object[key](options);
+ } else {
+ return object[key];
+ }
+ };
+
+ RestStorage.prototype._defaultCollectionUrl = function(model) {
+ return "/" + (this.storageKey(model.prototype));
+ };
+
+ RestStorage.prototype._addParams = function(url, options) {
+ var _ref;
+ if (options && options.action && !(_ref = options.action, __indexOf.call(this._implicitActionNames, _ref) >= 0)) {
+ url += '/' + options.action.toLowerCase();
+ }
+ return url;
+ };
+
+ RestStorage.prototype.urlForRecord = function(record, env) {
+ var id, url;
+ 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);
+ if (env.action !== 'create') {
+ if ((id = record.get('id')) != null) {
+ url = url + "/" + id;
+ } else {
+ throw new this.constructor.StorageError("Couldn't get/set record primary key on " + env.action + "!");
+ }
+ }
+ }
+ url = this._addParams(url, env.options);
+ return this.urlPrefix(record, env) + url + this.urlSuffix(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) || '';
+ };
+
+ RestStorage.prototype.request = function(env, next) {
+ var options;
+ options = Batman.extend(env.options, {
+ autosend: false,
+ success: function(data) {
+ return env.data = data;
+ },
+ error: function(error) {
+ return env.error = error;
+ },
+ loaded: function() {
+ env.response = env.request.get('response');
+ return next();
+ }
+ });
+ env.request = new Batman.Request(options);
+ return env.request.send();
+ };
+
+ RestStorage.prototype.perform = function(key, record, options, callback) {
+ options || (options = {});
+ Batman.extend(options, this.defaultRequestOptions);
+ return RestStorage.__super__.perform.call(this, key, record, options, callback);
+ };
+
+ RestStorage.prototype.before('all', RestStorage.skipIfError(function(env, next) {
+ if (!env.options.url) {
+ try {
+ env.options.url = env.subject.prototype ? this.urlForCollection(env.subject, env) : this.urlForRecord(env.subject, env);
+ } catch (error) {
+ env.error = error;
+ }
+ }
+ return next();
+ }));
+
+ RestStorage.prototype.before('get', 'put', 'post', 'delete', RestStorage.skipIfError(function(env, next) {
+ env.options.method = env.action.toUpperCase();
+ return next();
+ }));
+
+ RestStorage.prototype.before('create', 'update', RestStorage.skipIfError(function(env, next) {
+ var data, json, namespace;
+ json = env.subject.toJSON();
+ if (namespace = this.recordJsonNamespace(env.subject)) {
+ data = {};
+ data[namespace] = json;
+ } else {
+ data = json;
+ }
+ env.options.data = data;
+ return next();
+ }));
+
+ RestStorage.prototype.before('create', 'update', 'put', 'post', RestStorage.skipIfError(function(env, next) {
+ if (this.serializeAsForm) {
+ env.options.contentType = this.constructor.PostBodyContentType;
+ } else {
+ if (env.options.data != null) {
+ env.options.data = JSON.stringify(env.options.data);
+ env.options.contentType = this.constructor.JSONContentType;
+ }
+ }
+ return next();
+ }));
+
+ RestStorage.prototype.after('all', RestStorage.skipIfError(function(env, next) {
+ var json;
+ if (!(env.data != null)) {
+ return next();
+ }
+ if (typeof env.data === 'string') {
+ if (env.data.length > 0) {
+ try {
+ json = this._jsonToAttributes(env.data);
+ } catch (error) {
+ env.error = error;
+ return next();
+ }
+ }
+ } else if (typeof env.data === 'object') {
+ json = env.data;
+ }
+ if (json != null) {
+ env.json = json;
+ }
+ return next();
+ }));
+
+ RestStorage.prototype.extractFromNamespace = function(data, namespace) {
+ if (namespace && (data[namespace] != null)) {
+ return data[namespace];
+ } else {
+ return data;
+ }
+ };
+
+ RestStorage.prototype.after('create', 'read', 'update', RestStorage.skipIfError(function(env, next) {
+ var json;
+ if (env.json != null) {
+ json = this.extractFromNamespace(env.json, this.recordJsonNamespace(env.subject));
+ env.subject._withoutDirtyTracking(function() {
+ return this.fromJSON(json);
+ });
+ }
+ env.result = env.subject;
+ return next();
+ }));
+
+ RestStorage.prototype.after('readAll', RestStorage.skipIfError(function(env, next) {
+ var jsonRecordAttributes, namespace;
+ namespace = this.collectionJsonNamespace(env.subject);
+ env.recordsAttributes = this.extractFromNamespace(env.json, namespace);
+ if (Batman.typeOf(env.recordsAttributes) !== 'Array') {
+ namespace = this.recordJsonNamespace(env.subject.prototype);
+ env.recordsAttributes = [this.extractFromNamespace(env.json, namespace)];
+ }
+ env.result = env.records = (function() {
+ var _i, _len, _ref, _results;
+ _ref = env.recordsAttributes;
+ _results = [];
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ jsonRecordAttributes = _ref[_i];
+ _results.push(this.getRecordFromData(jsonRecordAttributes, env.subject));
+ }
+ return _results;
+ }).call(this);
+ return next();
+ }));
+
+ RestStorage.prototype.after('get', 'put', 'post', 'delete', RestStorage.skipIfError(function(env, next) {
+ var json, namespace;
+ if (env.json != null) {
+ json = env.json;
+ namespace = env.subject.prototype ? this.collectionJsonNamespace(env.subject) : this.recordJsonNamespace(env.subject);
+ env.result = namespace && (env.json[namespace] != null) ? env.json[namespace] : env.json;
+ }
+ return next();
+ }));
+
+ RestStorage.HTTPMethods = {
+ create: 'POST',
+ update: 'PUT',
+ read: 'GET',
+ readAll: 'GET',
+ destroy: 'DELETE'
+ };
+
+ _ref = ['create', 'read', 'update', 'destroy', 'readAll', 'get', 'post', 'put', 'delete'];
+ _fn = function(key) {
+ return RestStorage.prototype[key] = RestStorage.skipIfError(function(env, next) {
+ var _base;
+ (_base = env.options).method || (_base.method = this.constructor.HTTPMethods[key]);
+ return this.request(env, next);
+ });
+ };
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ key = _ref[_i];
+ _fn(key);
+ }
+
+ return RestStorage;
+
+ }).call(this, Batman.StorageAdapter);
+
+}).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.LocalStorage = (function(_super) {
+
+ __extends(LocalStorage, _super);
+
+ function LocalStorage() {
+ if (typeof window.localStorage === 'undefined') {
+ return null;
+ }
+ LocalStorage.__super__.constructor.apply(this, arguments);
+ this.storage = localStorage;
+ }
+
+ LocalStorage.prototype.storageRegExpForRecord = function(record) {
+ return new RegExp("^" + (this.storageKey(record)) + "(\\d+)$");
+ };
+
+ LocalStorage.prototype.nextIdForRecord = function(record) {
+ var nextId, re;
+ re = this.storageRegExpForRecord(record);
+ nextId = 1;
+ this._forAllStorageEntries(function(k, v) {
+ var matches;
+ if (matches = re.exec(k)) {
+ return nextId = Math.max(nextId, parseInt(matches[1], 10) + 1);
+ }
+ });
+ return nextId;
+ };
+
+ LocalStorage.prototype._forAllStorageEntries = function(iterator) {
+ var i, key, _i, _ref;
+ for (i = _i = 0, _ref = this.storage.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
+ key = this.storage.key(i);
+ iterator.call(this, key, this.storage.getItem(key));
+ }
+ return true;
+ };
+
+ LocalStorage.prototype._storageEntriesMatching = function(constructor, options) {
+ var re, records;
+ re = this.storageRegExpForRecord(constructor.prototype);
+ records = [];
+ this._forAllStorageEntries(function(storageKey, storageString) {
+ var data, keyMatches;
+ if (keyMatches = re.exec(storageKey)) {
+ data = this._jsonToAttributes(storageString);
+ data[constructor.primaryKey] = keyMatches[1];
+ if (this._dataMatches(options, data)) {
+ return records.push(data);
+ }
+ }
+ });
+ return records;
+ };
+
+ LocalStorage.prototype._dataMatches = function(conditions, data) {
+ var k, match, v;
+ match = true;
+ for (k in conditions) {
+ v = conditions[k];
+ if (data[k] !== v) {
+ match = false;
+ break;
+ }
+ }
+ return match;
+ };
+
+ LocalStorage.prototype.before('read', 'create', 'update', 'destroy', LocalStorage.skipIfError(function(env, next) {
+ var _this = this;
+ if (env.action === 'create') {
+ env.id = env.subject.get('id') || env.subject._withoutDirtyTracking(function() {
+ return env.subject.set('id', _this.nextIdForRecord(env.subject));
+ });
+ } else {
+ env.id = env.subject.get('id');
+ }
+ if (env.id == null) {
+ env.error = new this.constructor.StorageError("Couldn't get/set record primary key on " + env.action + "!");
+ } else {
+ env.key = this.storageKey(env.subject) + env.id;
+ }
+ return next();
+ }));
+
+ LocalStorage.prototype.before('create', 'update', LocalStorage.skipIfError(function(env, next) {
+ env.recordAttributes = JSON.stringify(env.subject);
+ return next();
+ }));
+
+ LocalStorage.prototype.after('read', LocalStorage.skipIfError(function(env, next) {
+ if (typeof env.recordAttributes === 'string') {
+ try {
+ env.recordAttributes = this._jsonToAttributes(env.recordAttributes);
+ } catch (error) {
+ env.error = error;
+ return next();
+ }
+ }
+ env.subject._withoutDirtyTracking(function() {
+ return this.fromJSON(env.recordAttributes);
+ });
+ return next();
+ }));
+
+ LocalStorage.prototype.after('read', 'create', 'update', 'destroy', LocalStorage.skipIfError(function(env, next) {
+ env.result = env.subject;
+ return next();
+ }));
+
+ LocalStorage.prototype.after('readAll', LocalStorage.skipIfError(function(env, next) {
+ var recordAttributes;
+ env.result = env.records = (function() {
+ var _i, _len, _ref, _results;
+ _ref = env.recordsAttributes;
+ _results = [];
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ recordAttributes = _ref[_i];
+ _results.push(this.getRecordFromData(recordAttributes, env.subject));
+ }
+ return _results;
+ }).call(this);
+ return next();
+ }));
+
+ LocalStorage.prototype.read = LocalStorage.skipIfError(function(env, next) {
+ env.recordAttributes = this.storage.getItem(env.key);
+ if (!env.recordAttributes) {
+ env.error = new this.constructor.NotFoundError();
+ }
+ return next();
+ });
+
+ LocalStorage.prototype.create = LocalStorage.skipIfError(function(_arg, next) {
+ var key, recordAttributes;
+ key = _arg.key, recordAttributes = _arg.recordAttributes;
+ if (this.storage.getItem(key)) {
+ arguments[0].error = new this.constructor.RecordExistsError;
+ } else {
+ this.storage.setItem(key, recordAttributes);
+ }
+ return next();
+ });
+
+ LocalStorage.prototype.update = LocalStorage.skipIfError(function(_arg, next) {
+ var key, recordAttributes;
+ key = _arg.key, recordAttributes = _arg.recordAttributes;
+ this.storage.setItem(key, recordAttributes);
+ return next();
+ });
+
+ LocalStorage.prototype.destroy = LocalStorage.skipIfError(function(_arg, next) {
+ var key;
+ key = _arg.key;
+ this.storage.removeItem(key);
+ return next();
+ });
+
+ LocalStorage.prototype.readAll = LocalStorage.skipIfError(function(env, next) {
+ try {
+ arguments[0].recordsAttributes = this._storageEntriesMatching(env.subject, env.options.data);
+ } catch (error) {
+ arguments[0].error = error;
+ }
+ return next();
+ });
+
+ return LocalStorage;
+
+ })(Batman.StorageAdapter);
+
+}).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.SessionStorage = (function(_super) {
+
+ __extends(SessionStorage, _super);
+
+ function SessionStorage() {
+ if (typeof window.sessionStorage === 'undefined') {
+ return null;
+ }
+ SessionStorage.__super__.constructor.apply(this, arguments);
+ this.storage = sessionStorage;
+ }
+
+ return SessionStorage;
+
+ })(Batman.LocalStorage);
+
+}).call(this);
+
+(function() {
+
+ Batman.Encoders = new 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.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);
+
+ function ParamsReplacer(navigator, params) {
+ this.navigator = navigator;
+ this.params = params;
+ }
+
+ ParamsReplacer.prototype.redirect = function() {
+ return this.navigator.replace(this.toObject());
+ };
+
+ ParamsReplacer.prototype.replace = function(params) {
+ this.params.replace(params);
+ return this.redirect();
+ };
+
+ ParamsReplacer.prototype.update = function(params) {
+ this.params.update(params);
+ return this.redirect();
+ };
+
+ ParamsReplacer.prototype.clear = function() {
+ this.params.clear();
+ return this.redirect();
+ };
+
+ ParamsReplacer.prototype.toObject = function() {
+ return this.params.toObject();
+ };
+
+ ParamsReplacer.accessor({
+ get: function(k) {
+ return this.params.get(k);
+ },
+ set: function(k, v) {
+ var oldValue, result;
+ oldValue = this.params.get(k);
+ result = this.params.set(k, v);
+ if (oldValue !== v) {
+ this.redirect();
+ }
+ return result;
+ },
+ unset: function(k) {
+ var hadKey, result;
+ hadKey = this.params.hasKey(k);
+ result = this.params.unset(k);
+ if (hadKey) {
+ this.redirect();
+ }
+ return result;
+ }
+ });
+
+ return ParamsReplacer;
+
+ })(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.ParamsPusher = (function(_super) {
+
+ __extends(ParamsPusher, _super);
+
+ function ParamsPusher() {
+ return ParamsPusher.__super__.constructor.apply(this, arguments);
+ }
+
+ ParamsPusher.prototype.redirect = function() {
+ return this.navigator.push(this.toObject());
+ };
+
+ return ParamsPusher;
+
+ })(Batman.ParamsReplacer);
+
+}).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.NamedRouteQuery = (function(_super) {
+
+ __extends(NamedRouteQuery, _super);
+
+ NamedRouteQuery.prototype.isNamedRouteQuery = true;
+
+ function NamedRouteQuery(routeMap, args) {
+ var key;
+ if (args == null) {
+ args = [];
+ }
+ NamedRouteQuery.__super__.constructor.call(this, {
+ routeMap: routeMap,
+ args: args
+ });
+ for (key in this.get('routeMap').childrenByName) {
+ this[key] = this._queryAccess.bind(this, key);
+ }
+ }
+
+ NamedRouteQuery.accessor('route', function() {
+ var collectionRoute, memberRoute, route, _i, _len, _ref, _ref1;
+ _ref = this.get('routeMap'), memberRoute = _ref.memberRoute, collectionRoute = _ref.collectionRoute;
+ _ref1 = [memberRoute, collectionRoute];
+ for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
+ route = _ref1[_i];
+ if (route != null) {
+ if (route.namedArguments.length === this.get('args').length) {
+ return route;
+ }
+ }
+ }
+ return collectionRoute || memberRoute;
+ });
+
+ NamedRouteQuery.accessor('path', function() {
+ return this.path();
+ });
+
+ NamedRouteQuery.accessor('routeMap', 'args', 'cardinality', 'hashValue', Batman.Property.defaultAccessor);
+
+ NamedRouteQuery.accessor({
+ get: function(key) {
+ if (key == null) {
+ return;
+ }
+ if (typeof key === 'string') {
+ return this.nextQueryForName(key);
+ } else {
+ return this.nextQueryWithArgument(key);
+ }
+ },
+ cache: false
+ });
+
+ NamedRouteQuery.accessor('withHash', function() {
+ var _this = this;
+ return new Batman.Accessible(function(hashValue) {
+ return _this.withHash(hashValue);
+ });
+ });
+
+ NamedRouteQuery.prototype.withHash = function(hashValue) {
+ var clone;
+ clone = this.clone();
+ clone.set('hashValue', hashValue);
+ return clone;
+ };
+
+ NamedRouteQuery.prototype.nextQueryForName = function(key) {
+ var map;
+ if (map = this.get('routeMap').childrenByName[key]) {
+ return new Batman.NamedRouteQuery(map, this.args);
+ } else {
+ return Batman.developer.error("Couldn't find a route for the name " + key + "!");
+ }
+ };
+
+ NamedRouteQuery.prototype.nextQueryWithArgument = function(arg) {
+ var args;
+ args = this.args.slice(0);
+ args.push(arg);
+ return this.clone(args);
+ };
+
+ NamedRouteQuery.prototype.path = function() {
+ var argumentName, argumentValue, index, namedArguments, params, _i, _len;
+ params = {};
+ namedArguments = this.get('route.namedArguments');
+ for (index = _i = 0, _len = namedArguments.length; _i < _len; index = ++_i) {
+ argumentName = namedArguments[index];
+ if ((argumentValue = this.get('args')[index]) != null) {
+ params[argumentName] = this._toParam(argumentValue);
+ }
+ }
+ if (this.get('hashValue') != null) {
+ params['#'] = this.get('hashValue');
+ }
+ return this.get('route').pathFromParams(params);
+ };
+
+ NamedRouteQuery.prototype.toString = function() {
+ return this.path();
+ };
+
+ NamedRouteQuery.prototype.clone = function(args) {
+ if (args == null) {
+ args = this.args;
+ }
+ return new Batman.NamedRouteQuery(this.routeMap, args);
+ };
+
+ NamedRouteQuery.prototype._toParam = function(arg) {
+ if (arg instanceof Batman.AssociationProxy) {
+ arg = arg.get('target');
+ }
+ if ((arg != null ? arg.toParam : void 0) != null) {
+ return arg.toParam();
+ } else {
+ return arg;
+ }
+ };
+
+ NamedRouteQuery.prototype._queryAccess = function(key, arg) {
+ var query;
+ query = this.nextQueryForName(key);
+ if (arg != null) {
+ query = query.nextQueryWithArgument(arg);
+ }
+ return query;
+ };
+
+ return NamedRouteQuery;
+
+ })(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.Dispatcher = (function(_super) {
+ var ControllerDirectory;
+
+ __extends(Dispatcher, _super);
+
+ Dispatcher.canInferRoute = function(argument) {
+ return argument instanceof Batman.Model || argument instanceof Batman.AssociationProxy || argument.prototype instanceof Batman.Model;
+ };
+
+ Dispatcher.paramsFromArgument = function(argument) {
+ var resourceNameFromModel;
+ resourceNameFromModel = function(model) {
+ return Batman.helpers.camelize(Batman.helpers.pluralize(model.get('resourceName')), true);
+ };
+ if (!this.canInferRoute(argument)) {
+ return argument;
+ }
+ if (argument instanceof Batman.Model || argument instanceof Batman.AssociationProxy) {
+ if (argument.isProxy) {
+ argument = argument.get('target');
+ }
+ if (argument != null) {
+ return {
+ controller: resourceNameFromModel(argument.constructor),
+ action: 'show',
+ id: argument.get('id')
+ };
+ } else {
+ return {};
+ }
+ } else if (argument.prototype instanceof Batman.Model) {
+ return {
+ controller: resourceNameFromModel(argument),
+ action: 'index'
+ };
+ } else {
+ return argument;
+ }
+ };
+
+ ControllerDirectory = (function(_super1) {
+
+ __extends(ControllerDirectory, _super1);
+
+ function ControllerDirectory() {
+ return ControllerDirectory.__super__.constructor.apply(this, arguments);
+ }
+
+ ControllerDirectory.accessor('__app', Batman.Property.defaultAccessor);
+
+ ControllerDirectory.accessor(function(key) {
+ return this.get("__app." + (Batman.helpers.capitalize(key)) + "Controller.sharedController");
+ });
+
+ return ControllerDirectory;
+
+ })(Batman.Object);
+
+ Dispatcher.accessor('controllers', function() {
+ return new ControllerDirectory({
+ __app: this.get('app')
+ });
+ });
+
+ function Dispatcher(app, routeMap) {
+ Dispatcher.__super__.constructor.call(this, {
+ app: app,
+ routeMap: routeMap
+ });
+ }
+
+ Dispatcher.prototype.routeForParams = function(params) {
+ params = this.constructor.paramsFromArgument(params);
+ return this.get('routeMap').routeForParams(params);
+ };
+
+ Dispatcher.prototype.pathFromParams = function(params) {
+ var _ref;
+ if (typeof params === 'string') {
+ return params;
+ }
+ params = this.constructor.paramsFromArgument(params);
+ return (_ref = this.routeForParams(params)) != null ? _ref.pathFromParams(params) : void 0;
+ };
+
+ Dispatcher.prototype.dispatch = function(params) {
+ var inferredParams, path, route, _ref;
+ inferredParams = this.constructor.paramsFromArgument(params);
+ route = this.routeForParams(inferredParams);
+ if (route) {
+ _ref = route.pathAndParamsFromArgument(inferredParams), path = _ref[0], params = _ref[1];
+ this.set('app.currentRoute', route);
+ this.set('app.currentURL', path);
+ this.get('app.currentParams').replace(params || {});
+ route.dispatch(params);
+ } else {
+ if (Batman.typeOf(params) === 'Object' && !this.constructor.canInferRoute(params)) {
+ return this.get('app.currentParams').replace(params);
+ } else {
+ this.get('app.currentParams').clear();
+ }
+ if (params !== '/404') {
+ return Batman.redirect('/404');
+ }
+ }
+ return path;
+ };
+
+ return Dispatcher;
+
+ }).call(this, 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.Route = (function(_super) {
+
+ __extends(Route, _super);
+
+ Route.regexps = {
+ namedParam: /:([\w\d]+)/g,
+ splatParam: /\*([\w\d]+)/g,
+ queryParam: '(?:\\?.+)?',
+ namedOrSplat: /[:|\*]([\w\d]+)/g,
+ namePrefix: '[:|\*]',
+ escapeRegExp: /[-[\]{}+?.,\\^$|#\s]/g,
+ openOptParam: /\(/g,
+ closeOptParam: /\)/g
+ };
+
+ Route.prototype.optionKeys = ['member', 'collection'];
+
+ Route.prototype.testKeys = ['controller', 'action'];
+
+ Route.prototype.isRoute = true;
+
+ function Route(templatePath, baseParams) {
+ var k, matches, namedArguments, pattern, properties, regexp, regexps, _i, _len, _ref;
+ regexps = this.constructor.regexps;
+ if (templatePath.indexOf('/') !== 0) {
+ templatePath = "/" + templatePath;
+ }
+ pattern = templatePath.replace(regexps.escapeRegExp, '\\$&');
+ regexp = RegExp("^" + (pattern.replace(regexps.openOptParam, '(?:').replace(regexps.closeOptParam, ')?').replace(regexps.namedParam, '([^\/]+)').replace(regexps.splatParam, '(.*?)')) + regexps.queryParam + "$");
+ namedArguments = ((function() {
+ var _results;
+ _results = [];
+ while (matches = regexps.namedOrSplat.exec(pattern)) {
+ _results.push(matches[1]);
+ }
+ return _results;
+ })());
+ properties = {
+ templatePath: templatePath,
+ pattern: pattern,
+ regexp: regexp,
+ namedArguments: namedArguments,
+ baseParams: baseParams
+ };
+ _ref = this.optionKeys;
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ k = _ref[_i];
+ properties[k] = baseParams[k];
+ delete baseParams[k];
+ }
+ Route.__super__.constructor.call(this, properties);
+ }
+
+ Route.prototype.paramsFromPath = function(pathAndQuery) {
+ var index, match, matches, name, namedArguments, params, uri, _i, _len;
+ uri = new Batman.URI(pathAndQuery);
+ namedArguments = this.get('namedArguments');
+ params = Batman.extend({
+ path: uri.path
+ }, this.get('baseParams'));
+ matches = this.get('regexp').exec(uri.path).slice(1);
+ for (index = _i = 0, _len = matches.length; _i < _len; index = ++_i) {
+ match = matches[index];
+ name = namedArguments[index];
+ params[name] = match;
+ }
+ return Batman.extend(params, uri.queryParams);
+ };
+
+ Route.prototype.pathFromParams = function(argumentParams) {
+ var hash, key, name, newPath, params, path, query, regexp, regexps, _i, _j, _len, _len1, _ref, _ref1;
+ params = Batman.extend({}, argumentParams);
+ path = this.get('templatePath');
+ regexps = this.constructor.regexps;
+ _ref = this.get('namedArguments');
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ name = _ref[_i];
+ regexp = RegExp("" + regexps.namePrefix + name);
+ newPath = path.replace(regexp, (params[name] != null ? params[name] : ''));
+ if (newPath !== path) {
+ delete params[name];
+ path = newPath;
+ }
+ }
+ path = path.replace(regexps.openOptParam, '').replace(regexps.closeOptParam, '').replace(/([^\/])\/+$/, '$1');
+ _ref1 = this.testKeys;
+ for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
+ key = _ref1[_j];
+ delete params[key];
+ }
+ if (params['#']) {
+ hash = params['#'];
+ delete params['#'];
+ }
+ query = Batman.URI.queryFromParams(params);
+ if (query) {
+ path += "?" + query;
+ }
+ if (hash) {
+ path += "#" + hash;
+ }
+ return path;
+ };
+
+ Route.prototype.test = function(pathOrParams) {
+ var key, path, value, _i, _len, _ref;
+ if (typeof pathOrParams === 'string') {
+ path = pathOrParams;
+ } else if (pathOrParams.path != null) {
+ path = pathOrParams.path;
+ } else {
+ path = this.pathFromParams(pathOrParams);
+ _ref = this.testKeys;
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ key = _ref[_i];
+ if ((value = this.get(key)) != null) {
+ if (pathOrParams[key] !== value) {
+ return false;
+ }
+ }
+ }
+ }
+ return this.get('regexp').test(path);
+ };
+
+ Route.prototype.pathAndParamsFromArgument = function(pathOrParams) {
+ var params, path;
+ if (typeof pathOrParams === 'string') {
+ params = this.paramsFromPath(pathOrParams);
+ path = pathOrParams;
+ } else {
+ params = pathOrParams;
+ path = this.pathFromParams(pathOrParams);
+ }
+ return [path, params];
+ };
+
+ Route.prototype.dispatch = function(params) {
+ if (!this.test(params)) {
+ return false;
+ }
+ return this.get('callback')(params);
+ };
+
+ Route.prototype.callback = function() {
+ throw new Batman.DevelopmentError("Override callback in a Route subclass");
+ };
+
+ return Route;
+
+ })(Batman.Object);
+
+}).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; };
+
+ Batman.ControllerActionRoute = (function(_super) {
+
+ __extends(ControllerActionRoute, _super);
+
+ ControllerActionRoute.prototype.optionKeys = ['member', 'collection', 'app', 'controller', 'action'];
+
+ function ControllerActionRoute(templatePath, options) {
+ this.callback = __bind(this.callback, this);
+
+ var action, controller, _ref;
+ if (options.signature) {
+ _ref = options.signature.split('#'), controller = _ref[0], action = _ref[1];
+ action || (action = 'index');
+ options.controller = controller;
+ options.action = action;
+ delete options.signature;
+ }
+ ControllerActionRoute.__super__.constructor.call(this, templatePath, options);
+ }
+
+ ControllerActionRoute.prototype.callback = function(params) {
+ var controller;
+ controller = this.get("app.dispatcher.controllers." + (this.get('controller')));
+ return controller.dispatch(this.get('action'), params);
+ };
+
+ return ControllerActionRoute;
+
+ })(Batman.Route);
+
+}).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.CallbackActionRoute = (function(_super) {
+
+ __extends(CallbackActionRoute, _super);
+
+ function CallbackActionRoute() {
+ return CallbackActionRoute.__super__.constructor.apply(this, arguments);
+ }
+
+ CallbackActionRoute.prototype.optionKeys = ['member', 'collection', 'callback', 'app'];
+
+ CallbackActionRoute.prototype.controller = false;
+
+ CallbackActionRoute.prototype.action = false;
+
+ return CallbackActionRoute;
+
+ })(Batman.Route);
+
+}).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.Hash = (function(_super) {
+ var k, _fn, _i, _j, _len, _len1, _ref, _ref1,
+ _this = this;
+
+ __extends(Hash, _super);
+
+ Hash.Metadata = (function(_super1) {
+
+ __extends(Metadata, _super1);
+
+ Batman.extend(Metadata.prototype, Batman.Enumerable);
+
+ function Metadata(hash) {
+ this.hash = hash;
+ }
+
+ Metadata.accessor('length', function() {
+ this.hash.registerAsMutableSource();
+ return this.hash.length;
+ });
+
+ Metadata.accessor('isEmpty', 'keys', 'toArray', function(key) {
+ this.hash.registerAsMutableSource();
+ return this.hash[key]();
+ });
+
+ Metadata.prototype.forEach = function() {
+ var _ref;
+ return (_ref = this.hash).forEach.apply(_ref, arguments);
+ };
+
+ return Metadata;
+
+ })(Batman.Object);
+
+ function Hash() {
+ this.meta = new this.constructor.Metadata(this);
+ Batman.SimpleHash.apply(this, arguments);
+ Hash.__super__.constructor.apply(this, arguments);
+ }
+
+ Batman.extend(Hash.prototype, Batman.Enumerable);
+
+ Hash.prototype.propertyClass = Batman.Property;
+
+ Hash.defaultAccessor = {
+ get: Batman.SimpleHash.prototype.get,
+ set: Hash.mutation(function(key, value) {
+ var result;
+ result = Batman.SimpleHash.prototype.set.call(this, key, value);
+ this.fire('itemsWereAdded', key);
+ return result;
+ }),
+ unset: Hash.mutation(function(key) {
+ var result;
+ result = Batman.SimpleHash.prototype.unset.call(this, key);
+ if (result != null) {
+ this.fire('itemsWereRemoved', key);
+ }
+ return result;
+ }),
+ cache: false
+ };
+
+ Hash.accessor(Hash.defaultAccessor);
+
+ Hash.prototype._preventMutationEvents = function(block) {
+ this.prevent('change');
+ this.prevent('itemsWereAdded');
+ this.prevent('itemsWereRemoved');
+ try {
+ return block.call(this);
+ } finally {
+ this.allow('change');
+ this.allow('itemsWereAdded');
+ this.allow('itemsWereRemoved');
+ }
+ };
+
+ Hash.prototype.clear = Hash.mutation(function() {
+ var keys, result;
+ keys = this.keys();
+ this._preventMutationEvents(function() {
+ var _this = this;
+ return this.forEach(function(k) {
+ return _this.unset(k);
+ });
+ });
+ result = Batman.SimpleHash.prototype.clear.call(this);
+ this.fire.apply(this, ['itemsWereRemoved'].concat(__slice.call(keys)));
+ return result;
+ });
+
+ Hash.prototype.update = Hash.mutation(function(object) {
+ var addedKeys;
+ addedKeys = [];
+ this._preventMutationEvents(function() {
+ var _this = this;
+ return Batman.forEach(object, function(k, v) {
+ if (!_this.hasKey(k)) {
+ addedKeys.push(k);
+ }
+ return _this.set(k, v);
+ });
+ });
+ if (addedKeys.length > 0) {
+ return this.fire.apply(this, ['itemsWereAdded'].concat(__slice.call(addedKeys)));
+ }
+ });
+
+ Hash.prototype.replace = Hash.mutation(function(object) {
+ var addedKeys, removedKeys;
+ addedKeys = [];
+ removedKeys = [];
+ this._preventMutationEvents(function() {
+ var _this = this;
+ this.forEach(function(k, _) {
+ if (!Batman.objectHasKey(object, k)) {
+ _this.unset(k);
+ return removedKeys.push(k);
+ }
+ });
+ return Batman.forEach(object, function(k, v) {
+ if (!_this.hasKey(k)) {
+ addedKeys.push(k);
+ }
+ return _this.set(k, v);
+ });
+ });
+ if (addedKeys.length > 0) {
+ this.fire.apply(this, ['itemsWereAdded'].concat(__slice.call(addedKeys)));
+ }
+ if (removedKeys.length > 0) {
+ return this.fire.apply(this, ['itemsWereRemoved'].concat(__slice.call(removedKeys)));
+ }
+ });
+
+ _ref = ['equality', 'hashKeyFor', 'objectKey', 'prefixedKey', 'unprefixedKey'];
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ k = _ref[_i];
+ Hash.prototype[k] = Batman.SimpleHash.prototype[k];
+ }
+
+ _ref1 = ['hasKey', 'forEach', 'isEmpty', 'keys', 'toArray', 'merge', 'toJSON', 'toObject'];
+ _fn = function(k) {
+ return Hash.prototype[k] = function() {
+ this.registerAsMutableSource();
+ return Batman.SimpleHash.prototype[k].apply(this, arguments);
+ };
+ };
+ for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
+ k = _ref1[_j];
+ _fn(k);
+ }
+
+ return Hash;
+
+ }).call(this, 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.RenderCache = (function(_super) {
+
+ __extends(RenderCache, _super);
+
+ RenderCache.prototype.maximumLength = 4;
+
+ function RenderCache() {
+ RenderCache.__super__.constructor.apply(this, arguments);
+ this.keyQueue = [];
+ }
+
+ RenderCache.prototype.viewForOptions = function(options) {
+ var _this = this;
+ if (options.cache === false || options.viewClass.prototype.cache === false) {
+ return this._newViewFromOptions(options);
+ }
+ return this.getOrSet(options, function() {
+ return _this._newViewFromOptions(Batman.extend({}, options));
+ });
+ };
+
+ RenderCache.prototype._newViewFromOptions = function(options) {
+ return new options.viewClass(options);
+ };
+
+ RenderCache.wrapAccessor(function(core) {
+ return {
+ cache: false,
+ get: function(key) {
+ var result;
+ result = core.get.call(this, key);
+ if (result) {
+ this._addOrBubbleKey(key);
+ }
+ return result;
+ },
+ set: function(key, value) {
+ var result;
+ result = core.set.apply(this, arguments);
+ result.set('cached', true);
+ this._addOrBubbleKey(key);
+ this._evictExpiredKeys();
+ return result;
+ },
+ unset: function(key) {
+ var result;
+ result = core.unset.apply(this, arguments);
+ result.set('cached', false);
+ this._removeKeyFromQueue(key);
+ return result;
+ }
+ };
+ });
+
+ RenderCache.prototype.equality = function(incomingOptions, storageOptions) {
+ var key;
+ if (Object.keys(incomingOptions).length !== Object.keys(storageOptions).length) {
+ return false;
+ }
+ for (key in incomingOptions) {
+ if (!(key === 'view')) {
+ if (incomingOptions[key] !== storageOptions[key]) {
+ return false;
+ }
+ }
+ }
+ return true;
+ };
+
+ RenderCache.prototype.reset = function() {
+ var key, _i, _len, _ref, _results;
+ _ref = this.keyQueue.slice(0);
+ _results = [];
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ key = _ref[_i];
+ _results.push(this.unset(key));
+ }
+ return _results;
+ };
+
+ RenderCache.prototype._addOrBubbleKey = function(key) {
+ this._removeKeyFromQueue(key);
+ return this.keyQueue.unshift(key);
+ };
+
+ RenderCache.prototype._removeKeyFromQueue = function(key) {
+ var index, queuedKey, _i, _len, _ref;
+ _ref = this.keyQueue;
+ for (index = _i = 0, _len = _ref.length; _i < _len; index = ++_i) {
+ queuedKey = _ref[index];
+ if (this.equality(queuedKey, key)) {
+ this.keyQueue.splice(index, 1);
+ break;
+ }
+ }
+ return key;
+ };
+
+ RenderCache.prototype._evictExpiredKeys = function() {
+ var currentKeys, i, key, _i, _ref, _ref1;
+ if (this.length > this.maximumLength) {
+ currentKeys = this.keyQueue.slice(0);
+ for (i = _i = _ref = this.maximumLength, _ref1 = currentKeys.length; _ref <= _ref1 ? _i < _ref1 : _i > _ref1; i = _ref <= _ref1 ? ++_i : --_i) {
+ key = currentKeys[i];
+ if (!this.get(key).isInDOM()) {
+ this.unset(key);
+ }
+ }
+ }
+ };
+
+ return RenderCache;
+
+ })(Batman.Hash);
+
+}).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; },
+ __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) {
+ var _optionsFromFilterArguments;
+
+ __extends(Controller, _super);
+
+ Controller.singleton('sharedController');
+
+ Controller.wrapAccessor('routingKey', function(core) {
+ return {
+ get: function() {
+ if (this.routingKey != null) {
+ return this.routingKey;
+ } else {
+ if (Batman.config.minificationErrors) {
+ Batman.developer.error("Please define `routingKey` on the prototype of " + (Batman.functionName(this.constructor)) + " in order for your controller to be minification safe.");
+ }
+ return Batman.functionName(this.constructor).replace(/Controller$/, '');
+ }
+ }
+ };
+ });
+
+ Controller.accessor('_renderContext', function() {
+ return Batman.RenderContext.root().descend(this);
+ });
+
+ _optionsFromFilterArguments = function(options, nameOrFunction) {
+ if (!nameOrFunction) {
+ nameOrFunction = options;
+ options = {};
+ } else {
+ if (typeof options === 'string') {
+ options = {
+ only: [options]
+ };
+ } else {
+ if (options.only && Batman.typeOf(options.only) !== 'Array') {
+ options.only = [options.only];
+ }
+ if (options.except && Batman.typeOf(options.except) !== 'Array') {
+ options.except = [options.except];
+ }
+ }
+ }
+ options.block = nameOrFunction;
+ return options;
+ };
+
+ Controller.beforeFilter = function() {
+ 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);
+ };
+
+ 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);
+ };
+
+ Controller.afterFilter(function(params) {
+ if (this.autoScrollToHash && (params['#'] != null)) {
+ return this.scrollToHash(params['#']);
+ }
+ });
+
+ function Controller() {
+ this.redirect = __bind(this.redirect, this);
+ Controller.__super__.constructor.apply(this, arguments);
+ this._resetActionFrames();
+ }
+
+ Controller.prototype.renderCache = new Batman.RenderCache;
+
+ Controller.prototype.defaultRenderYield = 'main';
+
+ Controller.prototype.autoScrollToHash = true;
+
+ Controller.prototype.dispatch = function(action, params) {
+ var redirectTo;
+ if (params == null) {
+ params = {};
+ }
+ params.controller || (params.controller = this.get('routingKey'));
+ params.action || (params.action = action);
+ params.target || (params.target = this);
+ this._resetActionFrames();
+ this.set('action', action);
+ this.set('params', params);
+ Batman.DOM.Yield.cycleAll();
+ this.executeAction(action, params);
+ Batman.DOM.Yield.clearAllStale();
+ redirectTo = this._afterFilterRedirect;
+ delete this._afterFilterRedirect;
+ if (redirectTo) {
+ return Batman.redirect(redirectTo);
+ }
+ };
+
+ Controller.prototype.executeAction = function(action, params) {
+ var frame, oldRedirect, parentFrame, result, _ref, _ref1,
+ _this = this;
+ if (params == null) {
+ params = this.get('params');
+ }
+ Batman.developer.assert(this[action], "Error! Controller action " + (this.get('routingKey')) + "." + action + " couldn't be found!");
+ parentFrame = this._actionFrames[this._actionFrames.length - 1];
+ frame = new Batman.ControllerActionFrame({
+ parentFrame: parentFrame,
+ action: action
+ }, function() {
+ var _ref;
+ _this._runFilters(action, params, 'afterFilters');
+ _this._resetActionFrames();
+ return (_ref = Batman.navigator) != null ? _ref.redirect = oldRedirect : void 0;
+ });
+ this._actionFrames.push(frame);
+ frame.startOperation({
+ internal: true
+ });
+ oldRedirect = (_ref = Batman.navigator) != null ? _ref.redirect : void 0;
+ if ((_ref1 = Batman.navigator) != null) {
+ _ref1.redirect = this.redirect;
+ }
+ this._runFilters(action, params, 'beforeFilters');
+ result = this[action](params);
+ if (!frame.operationOccurred) {
+ this.render();
+ }
+ frame.finishOperation();
+ return result;
+ };
+
+ Controller.prototype.redirect = function(url) {
+ var frame;
+ frame = this._actionFrames[this._actionFrames.length - 1];
+ if (frame) {
+ if (frame.operationOccurred) {
+ Batman.developer.warn("Warning! Trying to redirect but an action has already been taken during " + (this.get('routingKey')) + "." + (frame.action || this.get('action')));
+ }
+ frame.startAndFinishOperation();
+ if (this._afterFilterRedirect != null) {
+ return Batman.developer.warn("Warning! Multiple actions trying to redirect!");
+ } else {
+ return this._afterFilterRedirect = url;
+ }
+ } else {
+ if (Batman.typeOf(url) === 'Object') {
+ if (!url.controller) {
+ url.controller = this;
+ }
+ }
+ return Batman.redirect(url);
+ }
+ };
+
+ Controller.prototype.render = function(options) {
+ var action, frame, view, _ref, _ref1,
+ _this = this;
+ if (options == null) {
+ options = {};
+ }
+ if (frame = (_ref = this._actionFrames) != null ? _ref[this._actionFrames.length - 1] : void 0) {
+ frame.startOperation();
+ }
+ if (options === false) {
+ frame.finishOperation();
+ return;
+ }
+ action = (frame != null ? frame.action : void 0) || this.get('action');
+ if (options) {
+ options.into || (options.into = this.defaultRenderYield);
+ }
+ if (!options.view) {
+ options.viewClass || (options.viewClass = this._viewClassForAction(action));
+ options.context || (options.context = this.get('_renderContext'));
+ options.source || (options.source = Batman.helpers.underscore(this.get('routingKey') + '/' + action));
+ view = this.renderCache.viewForOptions(options);
+ } else {
+ view = options.view;
+ options.view = null;
+ }
+ if (view) {
+ if ((_ref1 = Batman.currentApp) != null) {
+ _ref1.prevent('ready');
+ }
+ view.on('ready', function() {
+ var _ref2;
+ Batman.DOM.Yield.withName(options.into).replace(view.get('node'));
+ if ((_ref2 = Batman.currentApp) != null) {
+ _ref2.allowAndFire('ready');
+ }
+ return frame != null ? frame.finishOperation() : void 0;
+ });
+ }
+ return view;
+ };
+
+ Controller.prototype.scrollToHash = function(hash) {
+ if (hash == null) {
+ hash = this.get('params')['#'];
+ }
+ return Batman.DOM.scrollIntoView(hash);
+ };
+
+ Controller.prototype._resetActionFrames = function() {
+ return this._actionFrames = [];
+ };
+
+ Controller.prototype._viewClassForAction = function(action) {
+ var classPrefix, _ref;
+ classPrefix = this.get('routingKey').replace('/', '_');
+ return ((_ref = Batman.currentApp) != null ? _ref[Batman.helpers.camelize("" + classPrefix + "_" + action + "_view")] : void 0) || Batman.View;
+ };
+
+ Controller.prototype._runFilters = function(action, params, filters) {
+ var _ref,
+ _this = this;
+ if (filters = (_ref = this.constructor._batman) != null ? _ref.get(filters) : void 0) {
+ return filters.forEach(function(_, options) {
+ var block;
+ if (options.only && __indexOf.call(options.only, action) < 0) {
+ return;
+ }
+ if (options.except && __indexOf.call(options.except, action) >= 0) {
+ return;
+ }
+ block = options.block;
+ if (typeof block === 'function') {
+ return block.call(_this, params);
+ } else {
+ return typeof _this[block] === "function" ? _this[block](params) : void 0;
+ }
+ });
+ }
+ };
+
+ return Controller;
+
+ })(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.Set = (function(_super) {
+ var k, _fn, _i, _j, _len, _len1, _ref, _ref1,
+ _this = this;
+
+ __extends(Set, _super);
+
+ function Set() {
+ Batman.SimpleSet.apply(this, arguments);
+ }
+
+ Batman.extend(Set.prototype, Batman.Enumerable);
+
+ Set._applySetAccessors = function(klass) {
+ var accessor, accessors, key, _results;
+ accessors = {
+ first: function() {
+ return this.toArray()[0];
+ },
+ last: function() {
+ return this.toArray()[this.length - 1];
+ },
+ isEmpty: function() {
+ return this.isEmpty();
+ },
+ toArray: function() {
+ return this.toArray();
+ },
+ length: function() {
+ this.registerAsMutableSource();
+ return this.length;
+ },
+ indexedBy: function() {
+ var _this = this;
+ return new Batman.TerminalAccessible(function(key) {
+ return _this.indexedBy(key);
+ });
+ },
+ indexedByUnique: function() {
+ var _this = this;
+ return new Batman.TerminalAccessible(function(key) {
+ return _this.indexedByUnique(key);
+ });
+ },
+ sortedBy: function() {
+ var _this = this;
+ return new Batman.TerminalAccessible(function(key) {
+ return _this.sortedBy(key);
+ });
+ },
+ sortedByDescending: function() {
+ var _this = this;
+ return new Batman.TerminalAccessible(function(key) {
+ return _this.sortedBy(key, 'desc');
+ });
+ }
+ };
+ _results = [];
+ for (key in accessors) {
+ accessor = accessors[key];
+ _results.push(klass.accessor(key, accessor));
+ }
+ return _results;
+ };
+
+ Set._applySetAccessors(Set);
+
+ _ref = ['add', 'remove', 'clear', 'replace', 'indexedBy', 'indexedByUnique', 'sortedBy', 'equality', '_indexOfItem'];
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ k = _ref[_i];
+ Set.prototype[k] = Batman.SimpleSet.prototype[k];
+ }
+
+ _ref1 = ['find', 'merge', 'forEach', 'toArray', 'isEmpty', 'has'];
+ _fn = function(k) {
+ return Set.prototype[k] = function() {
+ this.registerAsMutableSource();
+ return Batman.SimpleSet.prototype[k].apply(this, arguments);
+ };
+ };
+ for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
+ k = _ref1[_j];
+ _fn(k);
+ }
+
+ Set.prototype.toJSON = Set.prototype.toArray;
+
+ return Set;
+
+ }).call(this, 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.ErrorsSet = (function(_super) {
+
+ __extends(ErrorsSet, _super);
+
+ function ErrorsSet() {
+ return ErrorsSet.__super__.constructor.apply(this, arguments);
+ }
+
+ ErrorsSet.accessor(function(key) {
+ return this.indexedBy('attribute').get(key);
+ });
+
+ ErrorsSet.prototype.add = function(key, error) {
+ return ErrorsSet.__super__.add.call(this, new Batman.ValidationError(key, error));
+ };
+
+ return ErrorsSet;
+
+ })(Batman.Set);
+
+}).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.SetProxy = (function(_super) {
+ var k, _fn, _i, _len, _ref,
+ _this = this;
+
+ __extends(SetProxy, _super);
+
+ function SetProxy(base) {
+ var _this = this;
+ this.base = base;
+ SetProxy.__super__.constructor.call(this);
+ this.length = this.base.length;
+ this.base.on('itemsWereAdded', function() {
+ var items;
+ items = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
+ _this.set('length', _this.base.length);
+ return _this.fire.apply(_this, ['itemsWereAdded'].concat(__slice.call(items)));
+ });
+ this.base.on('itemsWereRemoved', function() {
+ var items;
+ items = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
+ _this.set('length', _this.base.length);
+ return _this.fire.apply(_this, ['itemsWereRemoved'].concat(__slice.call(items)));
+ });
+ }
+
+ Batman.extend(SetProxy.prototype, Batman.Enumerable);
+
+ SetProxy.prototype.filter = function(f) {
+ var r;
+ r = new Batman.Set();
+ return this.reduce((function(r, e) {
+ if (f(e)) {
+ r.add(e);
+ }
+ return r;
+ }), r);
+ };
+
+ SetProxy.prototype.replace = function() {
+ var length, result;
+ length = this.property('length');
+ length.isolate();
+ result = this.base.replace.apply(this, arguments);
+ length.expose();
+ return result;
+ };
+
+ _ref = ['add', 'remove', 'find', 'clear', 'has', 'merge', 'toArray', 'isEmpty', 'indexedBy', 'indexedByUnique', 'sortedBy'];
+ _fn = function(k) {
+ return SetProxy.prototype[k] = function() {
+ var _ref1;
+ return (_ref1 = this.base)[k].apply(_ref1, arguments);
+ };
+ };
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ k = _ref[_i];
+ _fn(k);
+ }
+
+ Batman.Set._applySetAccessors(SetProxy);
+
+ SetProxy.accessor('length', {
+ get: function() {
+ this.registerAsMutableSource();
+ return this.length;
+ },
+ set: function(_, v) {
+ return this.length = v;
+ }
+ });
+
+ return SetProxy;
+
+ }).call(this, Batman.Object);
+
+}).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.BinarySetOperation = (function(_super) {
+
+ __extends(BinarySetOperation, _super);
+
+ function BinarySetOperation(left, right) {
+ this.left = left;
+ this.right = right;
+ this._setup = __bind(this._setup, this);
+
+ BinarySetOperation.__super__.constructor.call(this);
+ this._setup(this.left, this.right);
+ this._setup(this.right, this.left);
+ }
+
+ BinarySetOperation.prototype._setup = function(set, opposite) {
+ var _this = this;
+ set.on('itemsWereAdded', function() {
+ var items;
+ items = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
+ return _this._itemsWereAddedToSource.apply(_this, [set, opposite].concat(__slice.call(items)));
+ });
+ set.on('itemsWereRemoved', function() {
+ var items;
+ items = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
+ return _this._itemsWereRemovedFromSource.apply(_this, [set, opposite].concat(__slice.call(items)));
+ });
+ return this._itemsWereAddedToSource.apply(this, [set, opposite].concat(__slice.call(set.toArray())));
+ };
+
+ BinarySetOperation.prototype.merge = function() {
+ var merged, others, set, _i, _len;
+ others = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
+ merged = new Batman.Set;
+ others.unshift(this);
+ for (_i = 0, _len = others.length; _i < _len; _i++) {
+ set = others[_i];
+ set.forEach(function(v) {
+ return merged.add(v);
+ });
+ }
+ return merged;
+ };
+
+ BinarySetOperation.prototype.filter = Batman.SetProxy.prototype.filter;
+
+ return BinarySetOperation;
+
+ })(Batman.Set);
+
+}).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.SetUnion = (function(_super) {
+
+ __extends(SetUnion, _super);
+
+ function SetUnion() {
+ return SetUnion.__super__.constructor.apply(this, arguments);
+ }
+
+ SetUnion.prototype._itemsWereAddedToSource = function() {
+ var items, opposite, source;
+ source = arguments[0], opposite = arguments[1], items = 3 <= arguments.length ? __slice.call(arguments, 2) : [];
+ return this.add.apply(this, items);
+ };
+
+ SetUnion.prototype._itemsWereRemovedFromSource = function() {
+ var item, items, itemsToRemove, opposite, source;
+ source = arguments[0], opposite = arguments[1], items = 3 <= arguments.length ? __slice.call(arguments, 2) : [];
+ itemsToRemove = (function() {
+ var _i, _len, _results;
+ _results = [];
+ for (_i = 0, _len = items.length; _i < _len; _i++) {
+ item = items[_i];
+ if (!opposite.has(item)) {
+ _results.push(item);
+ }
+ }
+ return _results;
+ })();
+ return this.remove.apply(this, itemsToRemove);
+ };
+
+ return SetUnion;
+
+ })(Batman.BinarySetOperation);
+
+}).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.SetIntersection = (function(_super) {
+
+ __extends(SetIntersection, _super);
+
+ function SetIntersection() {
+ return SetIntersection.__super__.constructor.apply(this, arguments);
+ }
+
+ SetIntersection.prototype._itemsWereAddedToSource = function() {
+ var item, items, itemsToAdd, opposite, source;
+ source = arguments[0], opposite = arguments[1], items = 3 <= arguments.length ? __slice.call(arguments, 2) : [];
+ itemsToAdd = (function() {
+ var _i, _len, _results;
+ _results = [];
+ for (_i = 0, _len = items.length; _i < _len; _i++) {
+ item = items[_i];
+ if (opposite.has(item)) {
+ _results.push(item);
+ }
+ }
+ return _results;
+ })();
+ return this.add.apply(this, itemsToAdd);
+ };
+
+ SetIntersection.prototype._itemsWereRemovedFromSource = function() {
+ var items, opposite, source;
+ source = arguments[0], opposite = arguments[1], items = 3 <= arguments.length ? __slice.call(arguments, 2) : [];
+ return this.remove.apply(this, items);
+ };
+
+ return SetIntersection;
+
+ })(Batman.BinarySetOperation);
+
+}).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.SetComplement = (function(_super) {
+
+ __extends(SetComplement, _super);
+
+ function SetComplement() {
+ return SetComplement.__super__.constructor.apply(this, arguments);
+ }
+
+ SetComplement.prototype._itemsWereAddedToSource = function() {
+ var item, items, itemsToAdd, itemsToRemove, opposite, source;
+ source = arguments[0], opposite = arguments[1], items = 3 <= arguments.length ? __slice.call(arguments, 2) : [];
+ if (source === this.left) {
+ itemsToAdd = (function() {
+ var _i, _len, _results;
+ _results = [];
+ for (_i = 0, _len = items.length; _i < _len; _i++) {
+ item = items[_i];
+ if (!opposite.has(item)) {
+ _results.push(item);
+ }
+ }
+ return _results;
+ })();
+ return this.add.apply(this, itemsToAdd);
+ } else {
+ itemsToRemove = (function() {
+ var _i, _len, _results;
+ _results = [];
+ for (_i = 0, _len = items.length; _i < _len; _i++) {
+ item = items[_i];
+ if (opposite.has(item)) {
+ _results.push(item);
+ }
+ }
+ return _results;
+ })();
+ return this.remove.apply(this, itemsToRemove);
+ }
+ };
+
+ SetComplement.prototype._itemsWereRemovedFromSource = function() {
+ var item, items, itemsToAdd, opposite, source;
+ source = arguments[0], opposite = arguments[1], items = 3 <= arguments.length ? __slice.call(arguments, 2) : [];
+ if (source === this.left) {
+ return this.remove.apply(this, items);
+ } else {
+ itemsToAdd = (function() {
+ var _i, _len, _results;
+ _results = [];
+ for (_i = 0, _len = items.length; _i < _len; _i++) {
+ item = items[_i];
+ if (opposite.has(item)) {
+ _results.push(item);
+ }
+ }
+ return _results;
+ })();
+ return this.add.apply(this, itemsToAdd);
+ }
+ };
+
+ SetComplement.prototype._addComplement = function(items, opposite) {
+ var item;
+ return this.add.apply(this, (function() {
+ var _i, _len, _results;
+ _results = [];
+ for (_i = 0, _len = items.length; _i < _len; _i++) {
+ item = items[_i];
+ if (opposite.has(item)) {
+ _results.push(item);
+ }
+ }
+ return _results;
+ })());
+ };
+
+ return SetComplement;
+
+ })(Batman.BinarySetOperation);
+
+}).call(this);
+
+(function() {
+
+ Batman.mixins = new 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.Accessible = (function(_super) {
+
+ __extends(Accessible, _super);
+
+ function Accessible() {
+ this.accessor.apply(this, arguments);
+ }
+
+ return Accessible;
+
+ })(Batman.Object);
+
+ Batman.TerminalAccessible = (function(_super) {
+
+ __extends(TerminalAccessible, _super);
+
+ function TerminalAccessible() {
+ return TerminalAccessible.__super__.constructor.apply(this, arguments);
+ }
+
+ TerminalAccessible.prototype.propertyClass = Batman.Property;
+
+ return TerminalAccessible;
+
+ })(Batman.Accessible);
+
+}).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.SetObserver = (function(_super) {
+
+ __extends(SetObserver, _super);
+
+ function SetObserver(base) {
+ var _this = this;
+ this.base = base;
+ this._itemObservers = new Batman.SimpleHash;
+ this._setObservers = new Batman.SimpleHash;
+ this._setObservers.set("itemsWereAdded", function() {
+ return _this.fire.apply(_this, ['itemsWereAdded'].concat(__slice.call(arguments)));
+ });
+ this._setObservers.set("itemsWereRemoved", function() {
+ return _this.fire.apply(_this, ['itemsWereRemoved'].concat(__slice.call(arguments)));
+ });
+ this.on('itemsWereAdded', this.startObservingItems.bind(this));
+ this.on('itemsWereRemoved', this.stopObservingItems.bind(this));
+ }
+
+ SetObserver.prototype.observedItemKeys = [];
+
+ SetObserver.prototype.observerForItemAndKey = function(item, key) {};
+
+ SetObserver.prototype._getOrSetObserverForItemAndKey = function(item, key) {
+ var _this = this;
+ return this._itemObservers.getOrSet(item, function() {
+ var observersByKey;
+ observersByKey = new Batman.SimpleHash;
+ return observersByKey.getOrSet(key, function() {
+ return _this.observerForItemAndKey(item, key);
+ });
+ });
+ };
+
+ SetObserver.prototype.startObserving = function() {
+ this._manageItemObservers("observe");
+ return this._manageSetObservers("addHandler");
+ };
+
+ SetObserver.prototype.stopObserving = function() {
+ this._manageItemObservers("forget");
+ return this._manageSetObservers("removeHandler");
+ };
+
+ SetObserver.prototype.startObservingItems = function() {
+ var item, items, _i, _len, _results;
+ items = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
+ _results = [];
+ for (_i = 0, _len = items.length; _i < _len; _i++) {
+ item = items[_i];
+ _results.push(this._manageObserversForItem(item, "observe"));
+ }
+ return _results;
+ };
+
+ SetObserver.prototype.stopObservingItems = function() {
+ var item, items, _i, _len, _results;
+ items = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
+ _results = [];
+ for (_i = 0, _len = items.length; _i < _len; _i++) {
+ item = items[_i];
+ _results.push(this._manageObserversForItem(item, "forget"));
+ }
+ return _results;
+ };
+
+ SetObserver.prototype._manageObserversForItem = function(item, method) {
+ var key, _i, _len, _ref;
+ if (!item.isObservable) {
+ return;
+ }
+ _ref = this.observedItemKeys;
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ key = _ref[_i];
+ item[method](key, this._getOrSetObserverForItemAndKey(item, key));
+ }
+ if (method === "forget") {
+ return this._itemObservers.unset(item);
+ }
+ };
+
+ SetObserver.prototype._manageItemObservers = function(method) {
+ var _this = this;
+ return this.base.forEach(function(item) {
+ return _this._manageObserversForItem(item, method);
+ });
+ };
+
+ SetObserver.prototype._manageSetObservers = function(method) {
+ var _this = this;
+ if (!this.base.isObservable) {
+ return;
+ }
+ return this._setObservers.forEach(function(key, observer) {
+ return _this.base.event(key)[method](observer);
+ });
+ };
+
+ return SetObserver;
+
+ })(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.SetSort = (function(_super) {
+
+ __extends(SetSort, _super);
+
+ function SetSort(base, key, order) {
+ var boundReIndex;
+ this.key = key;
+ if (order == null) {
+ order = "asc";
+ }
+ SetSort.__super__.constructor.call(this, base);
+ this.descending = order.toLowerCase() === "desc";
+ if (this.base.isObservable) {
+ this._setObserver = new Batman.SetObserver(this.base);
+ this._setObserver.observedItemKeys = [this.key];
+ boundReIndex = this._reIndex.bind(this);
+ this._setObserver.observerForItemAndKey = function() {
+ return boundReIndex;
+ };
+ this._setObserver.on('itemsWereAdded', boundReIndex);
+ this._setObserver.on('itemsWereRemoved', boundReIndex);
+ this.startObserving();
+ }
+ this._reIndex();
+ }
+
+ SetSort.prototype.startObserving = function() {
+ var _ref;
+ return (_ref = this._setObserver) != null ? _ref.startObserving() : void 0;
+ };
+
+ SetSort.prototype.stopObserving = function() {
+ var _ref;
+ return (_ref = this._setObserver) != null ? _ref.stopObserving() : void 0;
+ };
+
+ SetSort.prototype.toArray = function() {
+ return this.get('_storage');
+ };
+
+ SetSort.prototype.forEach = function(iterator, ctx) {
+ var e, i, _i, _len, _ref, _results;
+ _ref = this.get('_storage');
+ _results = [];
+ for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) {
+ e = _ref[i];
+ _results.push(iterator.call(ctx, e, i, this));
+ }
+ return _results;
+ };
+
+ SetSort.prototype.compare = function(a, b) {
+ if (a === b) {
+ return 0;
+ }
+ if (a === void 0) {
+ return 1;
+ }
+ if (b === void 0) {
+ return -1;
+ }
+ if (a === null) {
+ return 1;
+ }
+ if (b === null) {
+ return -1;
+ }
+ if (a === false) {
+ return 1;
+ }
+ if (b === false) {
+ return -1;
+ }
+ if (a === true) {
+ return 1;
+ }
+ if (b === true) {
+ return -1;
+ }
+ if (a !== a) {
+ if (b !== b) {
+ return 0;
+ } else {
+ return 1;
+ }
+ }
+ if (b !== b) {
+ return -1;
+ }
+ if (a > b) {
+ return 1;
+ }
+ if (a < b) {
+ return -1;
+ }
+ return 0;
+ };
+
+ SetSort.prototype._reIndex = function() {
+ var newOrder, _ref,
+ _this = this;
+ newOrder = this.base.toArray().sort(function(a, b) {
+ var multiple, valueA, valueB;
+ valueA = Batman.get(a, _this.key);
+ if (typeof valueA === 'function') {
+ valueA = valueA.call(a);
+ }
+ if (valueA != null) {
+ valueA = valueA.valueOf();
+ }
+ valueB = Batman.get(b, _this.key);
+ if (typeof valueB === 'function') {
+ valueB = valueB.call(b);
+ }
+ if (valueB != null) {
+ valueB = valueB.valueOf();
+ }
+ multiple = _this.descending ? -1 : 1;
+ return _this.compare.call(_this, valueA, valueB) * multiple;
+ });
+ if ((_ref = this._setObserver) != null) {
+ _ref.startObservingItems.apply(_ref, newOrder);
+ }
+ return this.set('_storage', newOrder);
+ };
+
+ return SetSort;
+
+ })(Batman.SetProxy);
+
+}).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.AssociationSet = (function(_super) {
+
+ __extends(AssociationSet, _super);
+
+ function AssociationSet(foreignKeyValue, association) {
+ var base;
+ this.foreignKeyValue = foreignKeyValue;
+ this.association = association;
+ base = new Batman.Set;
+ AssociationSet.__super__.constructor.call(this, base, '_batmanID');
+ }
+
+ AssociationSet.prototype.loaded = false;
+
+ AssociationSet.prototype.load = function(callback) {
+ var _this = this;
+ if (this.foreignKeyValue == null) {
+ return callback(void 0, this);
+ }
+ return this.association.getRelatedModel().load(this._getLoadOptions(), function(err, records) {
+ if (!err) {
+ _this.markAsLoaded();
+ }
+ return callback(err, _this);
+ });
+ };
+
+ AssociationSet.prototype._getLoadOptions = function() {
+ var loadOptions;
+ loadOptions = {};
+ loadOptions[this.association.foreignKey] = this.foreignKeyValue;
+ return loadOptions;
+ };
+
+ AssociationSet.accessor('loaded', Batman.Property.defaultAccessor);
+
+ AssociationSet.prototype.markAsLoaded = function() {
+ this.set('loaded', true);
+ return this.fire('loaded');
+ };
+
+ return AssociationSet;
+
+ })(Batman.SetSort);
+
+}).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.PolymorphicAssociationSet = (function(_super) {
+
+ __extends(PolymorphicAssociationSet, _super);
+
+ function PolymorphicAssociationSet(foreignKeyValue, foreignTypeKeyValue, association) {
+ this.foreignKeyValue = foreignKeyValue;
+ this.foreignTypeKeyValue = foreignTypeKeyValue;
+ this.association = association;
+ PolymorphicAssociationSet.__super__.constructor.call(this, this.foreignKeyValue, this.association);
+ }
+
+ PolymorphicAssociationSet.prototype._getLoadOptions = function() {
+ var loadOptions;
+ loadOptions = {};
+ loadOptions[this.association.foreignKey] = this.foreignKeyValue;
+ loadOptions[this.association.foreignTypeKey] = this.foreignTypeKeyValue;
+ return loadOptions;
+ };
+
+ return PolymorphicAssociationSet;
+
+ })(Batman.AssociationSet);
+
+}).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.SetIndex = (function(_super) {
+
+ __extends(SetIndex, _super);
+
+ SetIndex.accessor('toArray', function() {
+ return this.toArray();
+ });
+
+ Batman.extend(SetIndex.prototype, Batman.Enumerable);
+
+ SetIndex.prototype.propertyClass = Batman.Property;
+
+ function SetIndex(base, key) {
+ var _this = this;
+ this.base = base;
+ this.key = key;
+ SetIndex.__super__.constructor.call(this);
+ this._storage = new Batman.Hash;
+ if (this.base.isEventEmitter) {
+ this._setObserver = new Batman.SetObserver(this.base);
+ this._setObserver.observedItemKeys = [this.key];
+ this._setObserver.observerForItemAndKey = this.observerForItemAndKey.bind(this);
+ this._setObserver.on('itemsWereAdded', function() {
+ var item, items, _i, _len, _results;
+ items = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
+ _results = [];
+ for (_i = 0, _len = items.length; _i < _len; _i++) {
+ item = items[_i];
+ _results.push(_this._addItem(item));
+ }
+ return _results;
+ });
+ this._setObserver.on('itemsWereRemoved', function() {
+ var item, items, _i, _len, _results;
+ items = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
+ _results = [];
+ for (_i = 0, _len = items.length; _i < _len; _i++) {
+ item = items[_i];
+ _results.push(_this._removeItem(item));
+ }
+ return _results;
+ });
+ }
+ this.base.forEach(this._addItem.bind(this));
+ this.startObserving();
+ }
+
+ SetIndex.accessor(function(key) {
+ return this._resultSetForKey(key);
+ });
+
+ SetIndex.prototype.startObserving = function() {
+ var _ref;
+ return (_ref = this._setObserver) != null ? _ref.startObserving() : void 0;
+ };
+
+ SetIndex.prototype.stopObserving = function() {
+ var _ref;
+ return (_ref = this._setObserver) != null ? _ref.stopObserving() : void 0;
+ };
+
+ SetIndex.prototype.observerForItemAndKey = function(item, key) {
+ var _this = this;
+ return function(newValue, oldValue) {
+ _this._removeItemFromKey(item, oldValue);
+ return _this._addItemToKey(item, newValue);
+ };
+ };
+
+ SetIndex.prototype.forEach = function(iterator, ctx) {
+ var _this = this;
+ return this._storage.forEach(function(key, set) {
+ if (set.get('length') > 0) {
+ return iterator.call(ctx, key, set, _this);
+ }
+ });
+ };
+
+ SetIndex.prototype.toArray = function() {
+ var results;
+ results = [];
+ this._storage.forEach(function(key, set) {
+ if (set.get('length') > 0) {
+ return results.push(key);
+ }
+ });
+ return results;
+ };
+
+ SetIndex.prototype._addItem = function(item) {
+ return this._addItemToKey(item, this._keyForItem(item));
+ };
+
+ SetIndex.prototype._addItemToKey = function(item, key) {
+ return this._resultSetForKey(key).add(item);
+ };
+
+ SetIndex.prototype._removeItem = function(item) {
+ return this._removeItemFromKey(item, this._keyForItem(item));
+ };
+
+ SetIndex.prototype._removeItemFromKey = function(item, key) {
+ return this._resultSetForKey(key).remove(item);
+ };
+
+ SetIndex.prototype._resultSetForKey = function(key) {
+ return this._storage.getOrSet(key, function() {
+ return new Batman.Set;
+ });
+ };
+
+ SetIndex.prototype._keyForItem = function(item) {
+ return Batman.Keypath.forBaseAndKey(item, this.key).getValue();
+ };
+
+ return SetIndex;
+
+ })(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.PolymorphicAssociationSetIndex = (function(_super) {
+
+ __extends(PolymorphicAssociationSetIndex, _super);
+
+ function PolymorphicAssociationSetIndex(association, type, key) {
+ this.association = association;
+ this.type = type;
+ PolymorphicAssociationSetIndex.__super__.constructor.call(this, this.association.getRelatedModelForType(type).get('loaded'), key);
+ }
+
+ PolymorphicAssociationSetIndex.prototype._resultSetForKey = function(key) {
+ var _this = this;
+ return this._storage.getOrSet(key, function() {
+ return new _this.association.proxyClass(key, _this.type, _this.association);
+ });
+ };
+
+ return PolymorphicAssociationSetIndex;
+
+ })(Batman.SetIndex);
+
+}).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.AssociationSetIndex = (function(_super) {
+
+ __extends(AssociationSetIndex, _super);
+
+ function AssociationSetIndex(association, key) {
+ this.association = association;
+ AssociationSetIndex.__super__.constructor.call(this, this.association.getRelatedModel().get('loaded'), key);
+ }
+
+ AssociationSetIndex.prototype._resultSetForKey = function(key) {
+ var _this = this;
+ return this._storage.getOrSet(key, function() {
+ return new _this.association.proxyClass(key, _this.association);
+ });
+ };
+
+ AssociationSetIndex.prototype._setResultSet = function(key, set) {
+ return this._storage.set(key, set);
+ };
+
+ return AssociationSetIndex;
+
+ })(Batman.SetIndex);
+
+}).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.UniqueSetIndex = (function(_super) {
+
+ __extends(UniqueSetIndex, _super);
+
+ function UniqueSetIndex() {
+ this._uniqueIndex = new Batman.Hash;
+ UniqueSetIndex.__super__.constructor.apply(this, arguments);
+ }
+
+ UniqueSetIndex.accessor(function(key) {
+ return this._uniqueIndex.get(key);
+ });
+
+ UniqueSetIndex.prototype._addItemToKey = function(item, key) {
+ this._resultSetForKey(key).add(item);
+ if (!this._uniqueIndex.hasKey(key)) {
+ return this._uniqueIndex.set(key, item);
+ }
+ };
+
+ UniqueSetIndex.prototype._removeItemFromKey = function(item, key) {
+ var resultSet;
+ resultSet = this._resultSetForKey(key);
+ UniqueSetIndex.__super__._removeItemFromKey.apply(this, arguments);
+ if (resultSet.isEmpty()) {
+ return this._uniqueIndex.unset(key);
+ } else {
+ return this._uniqueIndex.set(key, resultSet.toArray()[0]);
+ }
+ };
+
+ return UniqueSetIndex;
+
+ })(Batman.SetIndex);
+
+}).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.UniqueAssociationSetIndex = (function(_super) {
+
+ __extends(UniqueAssociationSetIndex, _super);
+
+ function UniqueAssociationSetIndex(association, key) {
+ this.association = association;
+ UniqueAssociationSetIndex.__super__.constructor.call(this, this.association.getRelatedModel().get('loaded'), key);
+ }
+
+ return UniqueAssociationSetIndex;
+
+ })(Batman.UniqueSetIndex);
+
+}).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.PolymorphicUniqueAssociationSetIndex = (function(_super) {
+
+ __extends(PolymorphicUniqueAssociationSetIndex, _super);
+
+ function PolymorphicUniqueAssociationSetIndex(association, type, key) {
+ this.association = association;
+ this.type = type;
+ PolymorphicUniqueAssociationSetIndex.__super__.constructor.call(this, this.association.getRelatedModelForType(type).get('loaded'), key);
+ }
+
+ return PolymorphicUniqueAssociationSetIndex;
+
+ })(Batman.UniqueSetIndex);
+
+}).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;
+
+ Batman.Navigator = (function() {
+
+ Navigator.defaultClass = function() {
+ if (Batman.config.usePushState && Batman.PushStateNavigator.isSupported()) {
+ return Batman.PushStateNavigator;
+ } else {
+ return Batman.HashbangNavigator;
+ }
+ };
+
+ Navigator.forApp = function(app) {
+ return new (this.defaultClass())(app);
+ };
+
+ function Navigator(app) {
+ this.app = app;
+ this.handleCurrentLocation = __bind(this.handleCurrentLocation, this);
+
+ }
+
+ Navigator.prototype.start = function() {
+ var _this = this;
+ if (typeof window === 'undefined') {
+ return;
+ }
+ if (this.started) {
+ return;
+ }
+ this.started = true;
+ this.startWatching();
+ Batman.currentApp.prevent('ready');
+ return Batman.setImmediate(function() {
+ if (_this.started && Batman.currentApp) {
+ _this.handleCurrentLocation();
+ return Batman.currentApp.allowAndFire('ready');
+ }
+ });
+ };
+
+ Navigator.prototype.stop = function() {
+ this.stopWatching();
+ return this.started = false;
+ };
+
+ Navigator.prototype.handleLocation = function(location) {
+ var path;
+ path = this.pathFromLocation(location);
+ if (path === this.cachedPath) {
+ return;
+ }
+ return this.dispatch(path);
+ };
+
+ Navigator.prototype.handleCurrentLocation = function() {
+ return this.handleLocation(window.location);
+ };
+
+ Navigator.prototype.dispatch = function(params) {
+ return this.cachedPath = this.app.get('dispatcher').dispatch(params);
+ };
+
+ Navigator.prototype.push = function(params) {
+ var path;
+ path = this.dispatch(params);
+ this.pushState(null, '', path);
+ return path;
+ };
+
+ Navigator.prototype.replace = function(params) {
+ var path;
+ path = this.dispatch(params);
+ this.replaceState(null, '', path);
+ return path;
+ };
+
+ Navigator.prototype.redirect = Navigator.prototype.push;
+
+ Navigator.prototype.normalizePath = function() {
+ var i, seg, segments;
+ segments = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
+ segments = (function() {
+ var _i, _len, _results;
+ _results = [];
+ for (i = _i = 0, _len = segments.length; _i < _len; i = ++_i) {
+ seg = segments[i];
+ _results.push(("" + seg).replace(/^(?!\/)/, '/').replace(/\/+$/, ''));
+ }
+ return _results;
+ })();
+ return segments.join('') || '/';
+ };
+
+ Navigator.normalizePath = Navigator.prototype.normalizePath;
+
+ return Navigator;
+
+ })();
+
+}).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.PushStateNavigator = (function(_super) {
+
+ __extends(PushStateNavigator, _super);
+
+ function PushStateNavigator() {
+ return PushStateNavigator.__super__.constructor.apply(this, arguments);
+ }
+
+ PushStateNavigator.isSupported = function() {
+ var _ref;
+ return (typeof window !== "undefined" && window !== null ? (_ref = window.history) != null ? _ref.pushState : void 0 : void 0) != null;
+ };
+
+ PushStateNavigator.prototype.startWatching = function() {
+ return Batman.addEventListener(window, 'popstate', this.handleCurrentLocation);
+ };
+
+ PushStateNavigator.prototype.stopWatching = function() {
+ return Batman.removeEventListener(window, 'popstate', this.handleCurrentLocation);
+ };
+
+ PushStateNavigator.prototype.pushState = function(stateObject, title, path) {
+ 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));
+ };
+
+ PushStateNavigator.prototype.linkTo = function(url) {
+ return this.normalizePath(Batman.config.pathPrefix, url);
+ };
+
+ PushStateNavigator.prototype.pathFromLocation = function(location) {
+ var fullPath, prefixPattern;
+ fullPath = "" + (location.pathname || '') + (location.search || '');
+ prefixPattern = new RegExp("^" + (this.normalizePath(Batman.config.pathPrefix)));
+ return this.normalizePath(fullPath.replace(prefixPattern, ''));
+ };
+
+ PushStateNavigator.prototype.handleLocation = function(location) {
+ var hashbangPath, path;
+ path = this.pathFromLocation(location);
+ if (path === '/' && (hashbangPath = Batman.HashbangNavigator.prototype.pathFromLocation(location)) !== '/') {
+ return this.replace(hashbangPath);
+ } else {
+ return PushStateNavigator.__super__.handleLocation.apply(this, arguments);
+ }
+ };
+
+ return PushStateNavigator;
+
+ })(Batman.Navigator);
+
+}).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.HashbangNavigator = (function(_super) {
+
+ __extends(HashbangNavigator, _super);
+
+ function HashbangNavigator() {
+ return HashbangNavigator.__super__.constructor.apply(this, arguments);
+ }
+
+ HashbangNavigator.prototype.HASH_PREFIX = '#!';
+
+ if ((typeof window !== "undefined" && window !== null) && 'onhashchange' in window) {
+ HashbangNavigator.prototype.startWatching = function() {
+ return Batman.addEventListener(window, 'hashchange', this.handleCurrentLocation);
+ };
+ HashbangNavigator.prototype.stopWatching = function() {
+ return Batman.removeEventListener(window, 'hashchange', this.handleCurrentLocation);
+ };
+ } else {
+ HashbangNavigator.prototype.startWatching = function() {
+ return this.interval = setInterval(this.handleCurrentLocation, 100);
+ };
+ HashbangNavigator.prototype.stopWatching = function() {
+ return this.interval = clearInterval(this.interval);
+ };
+ }
+
+ HashbangNavigator.prototype.pushState = function(stateObject, title, path) {
+ return window.location.hash = this.linkTo(path);
+ };
+
+ HashbangNavigator.prototype.replaceState = function(stateObject, title, path) {
+ var loc;
+ loc = window.location;
+ return loc.replace("" + loc.pathname + loc.search + (this.linkTo(path)));
+ };
+
+ HashbangNavigator.prototype.linkTo = function(url) {
+ return this.HASH_PREFIX + url;
+ };
+
+ HashbangNavigator.prototype.pathFromLocation = function(location) {
+ var hash;
+ hash = location.hash;
+ if ((hash != null ? hash.substr(0, 2) : void 0) === this.HASH_PREFIX) {
+ return this.normalizePath(hash.substr(2));
+ } else {
+ return '/';
+ }
+ };
+
+ HashbangNavigator.prototype.handleLocation = function(location) {
+ var realPath;
+ if (!Batman.config.usePushState) {
+ return HashbangNavigator.__super__.handleLocation.apply(this, arguments);
+ }
+ realPath = Batman.PushStateNavigator.prototype.pathFromLocation(location);
+ if (realPath === '/') {
+ return HashbangNavigator.__super__.handleLocation.apply(this, arguments);
+ } else {
+ return location.replace(this.normalizePath("" + Batman.config.pathPrefix + (this.linkTo(realPath))));
+ }
+ };
+
+ return HashbangNavigator;
+
+ })(Batman.Navigator);
+
+}).call(this);
+
+(function() {
+
+ Batman.RouteMap = (function() {
+
+ RouteMap.prototype.memberRoute = null;
+
+ RouteMap.prototype.collectionRoute = null;
+
+ function RouteMap() {
+ this.childrenByOrder = [];
+ this.childrenByName = {};
+ }
+
+ RouteMap.prototype.routeForParams = function(params) {
+ var route, _i, _len, _ref;
+ _ref = this.childrenByOrder;
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ route = _ref[_i];
+ if (route.test(params)) {
+ return route;
+ }
+ }
+ return void 0;
+ };
+
+ RouteMap.prototype.addRoute = function(name, route) {
+ var base, names,
+ _this = this;
+ this.childrenByOrder.push(route);
+ if (name.length > 0 && (names = name.split('.')).length > 0) {
+ base = names.shift();
+ if (!this.childrenByName[base]) {
+ this.childrenByName[base] = new Batman.RouteMap;
+ }
+ this.childrenByName[base].addRoute(names.join('.'), route);
+ } else {
+ if (route.get('member')) {
+ Batman.developer["do"](function() {
+ if (_this.memberRoute) {
+ return Batman.developer.error("Member route with name " + name + " already exists!");
+ }
+ });
+ this.memberRoute = route;
+ } else {
+ Batman.developer["do"](function() {
+ if (_this.collectionRoute) {
+ return Batman.developer.error("Collection route with name " + name + " already exists!");
+ }
+ });
+ this.collectionRoute = route;
+ }
+ }
+ return true;
+ };
+
+ return RouteMap;
+
+ })();
+
+}).call(this);
+
+(function() {
+ var __slice = [].slice;
+
+ Batman.RouteMapBuilder = (function() {
+
+ RouteMapBuilder.BUILDER_FUNCTIONS = ['resources', 'member', 'collection', 'route', 'root'];
+
+ RouteMapBuilder.ROUTES = {
+ index: {
+ cardinality: 'collection',
+ path: function(resource) {
+ return resource;
+ },
+ name: function(resource) {
+ return resource;
+ }
+ },
+ "new": {
+ cardinality: 'collection',
+ path: function(resource) {
+ return "" + resource + "/new";
+ },
+ name: function(resource) {
+ return "" + resource + ".new";
+ }
+ },
+ show: {
+ cardinality: 'member',
+ path: function(resource) {
+ return "" + resource + "/:id";
+ },
+ name: function(resource) {
+ return resource;
+ }
+ },
+ edit: {
+ cardinality: 'member',
+ path: function(resource) {
+ return "" + resource + "/:id/edit";
+ },
+ name: function(resource) {
+ return "" + resource + ".edit";
+ }
+ },
+ collection: {
+ cardinality: 'collection',
+ path: function(resource, name) {
+ return "" + resource + "/" + name;
+ },
+ name: function(resource, name) {
+ return "" + resource + "." + name;
+ }
+ },
+ member: {
+ cardinality: 'member',
+ path: function(resource, name) {
+ return "" + resource + "/:id/" + name;
+ },
+ name: function(resource, name) {
+ return "" + resource + "." + name;
+ }
+ }
+ };
+
+ function RouteMapBuilder(app, routeMap, parent, baseOptions) {
+ this.app = app;
+ this.routeMap = routeMap;
+ this.parent = parent;
+ this.baseOptions = baseOptions != null ? baseOptions : {};
+ if (this.parent) {
+ this.rootPath = this.parent._nestingPath();
+ this.rootName = this.parent._nestingName();
+ } else {
+ this.rootPath = '';
+ this.rootName = '';
+ }
+ }
+
+ RouteMapBuilder.prototype.resources = function() {
+ var action, actions, arg, args, as, callback, childBuilder, controller, included, k, options, path, resourceName, resourceNames, resourceRoot, routeOptions, routeTemplate, v, _i, _j, _k, _len, _len1, _len2, _ref, _ref1;
+ args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
+ resourceNames = (function() {
+ var _i, _len, _results;
+ _results = [];
+ for (_i = 0, _len = args.length; _i < _len; _i++) {
+ arg = args[_i];
+ if (typeof arg === 'string') {
+ _results.push(arg);
+ }
+ }
+ return _results;
+ })();
+ if (typeof args[args.length - 1] === 'function') {
+ callback = args.pop();
+ }
+ if (typeof args[args.length - 1] === 'object') {
+ options = args.pop();
+ } else {
+ options = {};
+ }
+ actions = {
+ index: true,
+ "new": true,
+ show: true,
+ edit: true
+ };
+ if (options.except) {
+ _ref = options.except;
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ k = _ref[_i];
+ actions[k] = false;
+ }
+ delete options.except;
+ } else if (options.only) {
+ for (k in actions) {
+ v = actions[k];
+ actions[k] = false;
+ }
+ _ref1 = options.only;
+ for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
+ k = _ref1[_j];
+ actions[k] = true;
+ }
+ delete options.only;
+ }
+ for (_k = 0, _len2 = resourceNames.length; _k < _len2; _k++) {
+ resourceName = resourceNames[_k];
+ resourceRoot = Batman.helpers.pluralize(resourceName);
+ controller = Batman.helpers.camelize(resourceRoot, true);
+ childBuilder = this._childBuilder({
+ controller: controller
+ });
+ if (callback != null) {
+ callback.call(childBuilder);
+ }
+ for (action in actions) {
+ included = actions[action];
+ if (!(included)) {
+ continue;
+ }
+ routeTemplate = this.constructor.ROUTES[action];
+ as = routeTemplate.name(resourceRoot);
+ path = routeTemplate.path(resourceRoot);
+ routeOptions = Batman.extend({
+ controller: controller,
+ action: action,
+ path: path,
+ as: as
+ }, options);
+ childBuilder[routeTemplate.cardinality](action, routeOptions);
+ }
+ }
+ return true;
+ };
+
+ RouteMapBuilder.prototype.member = function() {
+ return this._addRoutesWithCardinality.apply(this, ['member'].concat(__slice.call(arguments)));
+ };
+
+ RouteMapBuilder.prototype.collection = function() {
+ return this._addRoutesWithCardinality.apply(this, ['collection'].concat(__slice.call(arguments)));
+ };
+
+ RouteMapBuilder.prototype.root = function(signature, options) {
+ return this.route('/', signature, options);
+ };
+
+ RouteMapBuilder.prototype.route = function(path, signature, options, callback) {
+ if (!callback) {
+ if (typeof options === 'function') {
+ callback = options;
+ options = void 0;
+ } else if (typeof signature === 'function') {
+ callback = signature;
+ signature = void 0;
+ }
+ }
+ if (!options) {
+ if (typeof signature === 'string') {
+ options = {
+ signature: signature
+ };
+ } else {
+ options = signature;
+ }
+ options || (options = {});
+ } else {
+ if (signature) {
+ options.signature = signature;
+ }
+ }
+ if (callback) {
+ options.callback = callback;
+ }
+ options.as || (options.as = this._nameFromPath(path));
+ options.path = path;
+ return this._addRoute(options);
+ };
+
+ RouteMapBuilder.prototype._addRoutesWithCardinality = function() {
+ var cardinality, name, names, options, resourceRoot, routeOptions, routeTemplate, _i, _j, _len;
+ cardinality = arguments[0], names = 3 <= arguments.length ? __slice.call(arguments, 1, _i = arguments.length - 1) : (_i = 1, []), options = arguments[_i++];
+ if (typeof options === 'string') {
+ names.push(options);
+ options = {};
+ }
+ options = Batman.extend({}, this.baseOptions, options);
+ options[cardinality] = true;
+ routeTemplate = this.constructor.ROUTES[cardinality];
+ resourceRoot = options.controller;
+ for (_j = 0, _len = names.length; _j < _len; _j++) {
+ name = names[_j];
+ routeOptions = Batman.extend({
+ action: name
+ }, options);
+ if (routeOptions.path == null) {
+ routeOptions.path = routeTemplate.path(resourceRoot, name);
+ }
+ if (routeOptions.as == null) {
+ routeOptions.as = routeTemplate.name(resourceRoot, name);
+ }
+ this._addRoute(routeOptions);
+ }
+ return true;
+ };
+
+ RouteMapBuilder.prototype._addRoute = function(options) {
+ var klass, name, path, route;
+ if (options == null) {
+ options = {};
+ }
+ path = this.rootPath + options.path;
+ name = this.rootName + Batman.helpers.camelize(options.as, true);
+ delete options.as;
+ delete options.path;
+ klass = options.callback ? Batman.CallbackActionRoute : Batman.ControllerActionRoute;
+ options.app = this.app;
+ route = new klass(path, options);
+ return this.routeMap.addRoute(name, route);
+ };
+
+ RouteMapBuilder.prototype._nameFromPath = function(path) {
+ path = path.replace(Batman.Route.regexps.namedOrSplat, '').replace(/\/+/g, '.').replace(/(^\.)|(\.$)/g, '');
+ return path;
+ };
+
+ RouteMapBuilder.prototype._nestingPath = function() {
+ var nestingParam, nestingSegment;
+ if (!this.parent) {
+ return "";
+ } else {
+ nestingParam = ":" + Batman.helpers.singularize(this.baseOptions.controller) + "Id";
+ nestingSegment = Batman.helpers.underscore(this.baseOptions.controller);
+ return "" + (this.parent._nestingPath()) + "/" + nestingSegment + "/" + nestingParam + "/";
+ }
+ };
+
+ RouteMapBuilder.prototype._nestingName = function() {
+ if (!this.parent) {
+ return "";
+ } else {
+ return this.baseOptions.controller + ".";
+ }
+ };
+
+ RouteMapBuilder.prototype._childBuilder = function(baseOptions) {
+ if (baseOptions == null) {
+ baseOptions = {};
+ }
+ return new Batman.RouteMapBuilder(this.app, this.routeMap, this, baseOptions);
+ };
+
+ return RouteMapBuilder;
+
+ })();
+
+}).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.App = (function(_super) {
+ var name, _fn, _i, _len, _ref,
+ _this = this;
+
+ __extends(App, _super);
+
+ function App() {
+ return App.__super__.constructor.apply(this, arguments);
+ }
+
+ App.classAccessor('currentParams', {
+ get: function() {
+ return new Batman.Hash;
+ },
+ 'final': true
+ });
+
+ App.classAccessor('paramsManager', {
+ get: function() {
+ var nav, params;
+ if (!(nav = this.get('navigator'))) {
+ return;
+ }
+ params = this.get('currentParams');
+ return params.replacer = new Batman.ParamsReplacer(nav, params);
+ },
+ 'final': true
+ });
+
+ App.classAccessor('paramsPusher', {
+ get: function() {
+ var nav, params;
+ if (!(nav = this.get('navigator'))) {
+ return;
+ }
+ params = this.get('currentParams');
+ return params.pusher = new Batman.ParamsPusher(nav, params);
+ },
+ 'final': true
+ });
+
+ App.classAccessor('routes', function() {
+ return new Batman.NamedRouteQuery(this.get('routeMap'));
+ });
+
+ App.classAccessor('routeMap', function() {
+ return new Batman.RouteMap;
+ });
+
+ App.classAccessor('routeMapBuilder', function() {
+ return new Batman.RouteMapBuilder(this, this.get('routeMap'));
+ });
+
+ App.classAccessor('dispatcher', function() {
+ return new Batman.Dispatcher(this, this.get('routeMap'));
+ });
+
+ App.classAccessor('controllers', function() {
+ return this.get('dispatcher.controllers');
+ });
+
+ App.classAccessor('_renderContext', function() {
+ return Batman.RenderContext.base.descend(this);
+ });
+
+ App.requirePath = '';
+
+ Batman.developer["do"](function() {
+ App.require = function() {
+ var base, name, names, path, _i, _len,
+ _this = this;
+ path = arguments[0], names = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
+ base = this.requirePath + path;
+ for (_i = 0, _len = names.length; _i < _len; _i++) {
+ name = names[_i];
+ this.prevent('run');
+ path = base + '/' + name + '.coffee';
+ new Batman.Request({
+ url: path,
+ type: 'html',
+ success: function(response) {
+ CoffeeScript["eval"](response);
+ _this.allow('run');
+ if (!_this.isPrevented('run')) {
+ _this.fire('loaded');
+ }
+ if (_this.wantsToRun) {
+ return _this.run();
+ }
+ }
+ });
+ }
+ return this;
+ };
+ App.controller = function() {
+ var names;
+ names = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
+ names = names.map(function(n) {
+ return n + '_controller';
+ });
+ return this.require.apply(this, ['controllers'].concat(__slice.call(names)));
+ };
+ App.model = function() {
+ return this.require.apply(this, ['models'].concat(__slice.call(arguments)));
+ };
+ return App.view = function() {
+ return this.require.apply(this, ['views'].concat(__slice.call(arguments)));
+ };
+ });
+
+ App.layout = void 0;
+
+ _ref = Batman.RouteMapBuilder.BUILDER_FUNCTIONS;
+ _fn = function(name) {
+ return App[name] = function() {
+ var _ref1;
+ return (_ref1 = this.get('routeMapBuilder'))[name].apply(_ref1, arguments);
+ };
+ };
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ name = _ref[_i];
+ _fn(name);
+ }
+
+ App.event('ready').oneShot = true;
+
+ App.event('run').oneShot = true;
+
+ App.run = function() {
+ var layout, layoutClass,
+ _this = this;
+ if (Batman.currentApp) {
+ if (Batman.currentApp === this) {
+ return;
+ }
+ Batman.currentApp.stop();
+ }
+ if (this.hasRun) {
+ return false;
+ }
+ if (this.isPrevented('run')) {
+ this.wantsToRun = true;
+ return false;
+ } else {
+ delete this.wantsToRun;
+ }
+ Batman.currentApp = this;
+ Batman.App.set('current', this);
+ if (this.get('dispatcher') == null) {
+ this.set('dispatcher', new Batman.Dispatcher(this, this.get('routeMap')));
+ this.set('controllers', this.get('dispatcher.controllers'));
+ }
+ if (this.get('navigator') == null) {
+ this.set('navigator', Batman.Navigator.forApp(this));
+ this.on('run', function() {
+ Batman.navigator = _this.get('navigator');
+ if (Object.keys(_this.get('dispatcher').routeMap).length > 0) {
+ return Batman.navigator.start();
+ }
+ });
+ }
+ this.observe('layout', function(layout) {
+ return layout != null ? layout.on('ready', function() {
+ return _this.fire('ready');
+ }) : void 0;
+ });
+ layout = this.get('layout');
+ if (layout) {
+ if (typeof layout === 'string') {
+ layoutClass = this[Batman.helpers.camelize(layout) + 'View'];
+ }
+ } else {
+ if (layout !== null) {
+ layoutClass = Batman.View;
+ }
+ }
+ if (layoutClass) {
+ layout = this.set('layout', new layoutClass({
+ context: this,
+ node: document
+ }));
+ }
+ this.hasRun = true;
+ this.fire('run');
+ return this;
+ };
+
+ App.event('ready').oneShot = true;
+
+ App.event('stop').oneShot = true;
+
+ App.stop = function() {
+ var _ref1;
+ if ((_ref1 = this.navigator) != null) {
+ _ref1.stop();
+ }
+ Batman.navigator = null;
+ this.hasRun = false;
+ this.fire('stop');
+ return this;
+ };
+
+ return App;
+
+ }).call(this, Batman.Object);
+
+}).call(this);
+
+(function() {
+
+ Batman.Association = (function() {
+
+ Association.prototype.associationType = '';
+
+ Association.prototype.isPolymorphic = false;
+
+ Association.prototype.defaultOptions = {
+ saveInline: true,
+ autoload: true,
+ nestUrl: false
+ };
+
+ function Association(model, label, options) {
+ var defaultOptions, encoder, getAccessor, self;
+ this.model = model;
+ this.label = label;
+ if (options == null) {
+ options = {};
+ }
+ defaultOptions = {
+ namespace: Batman.currentApp,
+ name: Batman.helpers.camelize(Batman.helpers.singularize(this.label))
+ };
+ this.options = Batman.extend(defaultOptions, this.defaultOptions, options);
+ if (this.options.nestUrl) {
+ if (!(this.model.urlNestsUnder != null)) {
+ developer.error("You must persist the the model " + this.model.constructor.name + " to use the url helpers on an association");
+ }
+ this.model.urlNestsUnder(Batman.helpers.underscore(this.getRelatedModel().get('resourceName')));
+ }
+ if (this.options.extend != null) {
+ Batman.extend(this, this.options.extend);
+ }
+ encoder = {
+ encode: this.options.saveInline ? this.encoder() : false,
+ decode: this.decoder()
+ };
+ this.model.encode(this.label, encoder);
+ self = this;
+ getAccessor = function() {
+ return self.getAccessor.call(this, self, this.model, this.label);
+ };
+ this.model.accessor(this.label, {
+ get: getAccessor,
+ set: model.defaultAccessor.set,
+ unset: model.defaultAccessor.unset
+ });
+ }
+
+ Association.prototype.getRelatedModel = function() {
+ var className, relatedModel, scope;
+ scope = this.options.namespace || Batman.currentApp;
+ className = this.options.name;
+ relatedModel = scope != null ? scope[className] : void 0;
+ Batman.developer["do"](function() {
+ if ((Batman.currentApp != null) && !relatedModel) {
+ return Batman.developer.warn("Related model " + className + " hasn't loaded yet.");
+ }
+ });
+ return relatedModel;
+ };
+
+ Association.prototype.getFromAttributes = function(record) {
+ return record.get("attributes." + this.label);
+ };
+
+ Association.prototype.setIntoAttributes = function(record, value) {
+ return record.get('attributes').set(this.label, value);
+ };
+
+ Association.prototype.inverse = function() {
+ var inverse, relatedAssocs,
+ _this = this;
+ if (relatedAssocs = this.getRelatedModel()._batman.get('associations')) {
+ if (this.options.inverseOf) {
+ return relatedAssocs.getByLabel(this.options.inverseOf);
+ }
+ inverse = null;
+ relatedAssocs.forEach(function(label, assoc) {
+ if (assoc.getRelatedModel() === _this.model) {
+ return inverse = assoc;
+ }
+ });
+ return inverse;
+ }
+ };
+
+ Association.prototype.reset = function() {
+ delete this.index;
+ return true;
+ };
+
+ return Association;
+
+ })();
+
+}).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.PluralAssociation = (function(_super) {
+
+ __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);
+ } else {
+ return new this.proxyClass(void 0, this);
+ }
+ });
+
+ PluralAssociation.prototype.getAccessor = function(self, model, label) {
+ var relatedRecords, setInAttributes,
+ _this = this;
+ if (!self.getRelatedModel()) {
+ return;
+ }
+ if (setInAttributes = self.getFromAttributes(this)) {
+ return setInAttributes;
+ } else {
+ relatedRecords = self.setForRecord(this);
+ self.setIntoAttributes(this, relatedRecords);
+ Batman.Property.withoutTracking(function() {
+ if (self.options.autoload && !_this.isNew() && !relatedRecords.loaded) {
+ return relatedRecords.load(function(error, records) {
+ if (error) {
+ throw error;
+ }
+ });
+ }
+ });
+ return relatedRecords;
+ }
+ };
+
+ PluralAssociation.prototype.setIndex = function() {
+ this.index || (this.index = new Batman.AssociationSetIndex(this, this[this.indexRelatedModelOn]));
+ return this.index;
+ };
+
+ return PluralAssociation;
+
+ })(Batman.Association);
+
+}).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.HasManyAssociation = (function(_super) {
+
+ __extends(HasManyAssociation, _super);
+
+ HasManyAssociation.prototype.associationType = 'hasMany';
+
+ HasManyAssociation.prototype.indexRelatedModelOn = 'foreignKey';
+
+ function HasManyAssociation(model, label, options) {
+ if (options != null ? options.as : void 0) {
+ 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.PolymorphicHasManyAssociation, arguments, function(){});
+ }
+ HasManyAssociation.__super__.constructor.apply(this, arguments);
+ this.primaryKey = this.options.primaryKey || "id";
+ this.foreignKey = this.options.foreignKey || ("" + (Batman.helpers.underscore(model.get('resourceName'))) + "_id");
+ }
+
+ HasManyAssociation.prototype.apply = function(baseSaveError, base) {
+ var relations, set,
+ _this = this;
+ if (!baseSaveError) {
+ if (relations = this.getFromAttributes(base)) {
+ relations.forEach(function(model) {
+ return model.set(_this.foreignKey, base.get(_this.primaryKey));
+ });
+ }
+ base.set(this.label, set = this.setForRecord(base));
+ if (base.lifecycle.get('state') === 'creating') {
+ return set.markAsLoaded();
+ }
+ }
+ };
+
+ HasManyAssociation.prototype.encoder = function() {
+ var association;
+ association = this;
+ return function(relationSet, _, __, record) {
+ var jsonArray;
+ if (relationSet != null) {
+ jsonArray = [];
+ relationSet.forEach(function(relation) {
+ var relationJSON;
+ relationJSON = relation.toJSON();
+ if (!association.inverse() || association.inverse().options.encodeForeignKey) {
+ relationJSON[association.foreignKey] = record.get(association.primaryKey);
+ }
+ return jsonArray.push(relationJSON);
+ });
+ }
+ return jsonArray;
+ };
+ };
+
+ HasManyAssociation.prototype.decoder = function() {
+ var association;
+ association = this;
+ return function(data, key, _, __, parentRecord) {
+ var existingRecord, existingRelations, jsonObject, newRelations, record, relatedModel, savedRecord, _i, _len;
+ if (relatedModel = association.getRelatedModel()) {
+ existingRelations = association.getFromAttributes(parentRecord) || association.setForRecord(parentRecord);
+ newRelations = existingRelations.filter(function(relation) {
+ return relation.isNew();
+ }).toArray();
+ for (_i = 0, _len = data.length; _i < _len; _i++) {
+ jsonObject = data[_i];
+ record = new relatedModel();
+ record._withoutDirtyTracking(function() {
+ return this.fromJSON(jsonObject);
+ });
+ existingRecord = relatedModel.get('loaded').indexedByUnique('id').get(record.get('id'));
+ if (existingRecord != null) {
+ existingRecord._withoutDirtyTracking(function() {
+ return this.fromJSON(jsonObject);
+ });
+ record = existingRecord;
+ } else {
+ if (newRelations.length > 0) {
+ savedRecord = newRelations.shift();
+ savedRecord._withoutDirtyTracking(function() {
+ return this.fromJSON(jsonObject);
+ });
+ record = savedRecord;
+ }
+ }
+ record = relatedModel._mapIdentity(record);
+ existingRelations.add(record);
+ if (association.options.inverseOf) {
+ record.set(association.options.inverseOf, parentRecord);
+ }
+ }
+ existingRelations.markAsLoaded();
+ } else {
+ Batman.developer.error("Can't decode model " + association.options.name + " because it hasn't been loaded yet!");
+ }
+ return existingRelations;
+ };
+ };
+
+ return HasManyAssociation;
+
+ })(Batman.PluralAssociation);
+
+}).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.PolymorphicHasManyAssociation = (function(_super) {
+
+ __extends(PolymorphicHasManyAssociation, _super);
+
+ PolymorphicHasManyAssociation.prototype.proxyClass = Batman.PolymorphicAssociationSet;
+
+ PolymorphicHasManyAssociation.prototype.isPolymorphic = true;
+
+ function PolymorphicHasManyAssociation(model, label, options) {
+ options.inverseOf = this.foreignLabel = options.as;
+ delete options.as;
+ options.foreignKey || (options.foreignKey = "" + this.foreignLabel + "_id");
+ PolymorphicHasManyAssociation.__super__.constructor.call(this, model, label, options);
+ this.foreignTypeKey = options.foreignTypeKey || ("" + this.foreignLabel + "_type");
+ this.model.encode(this.foreignTypeKey);
+ }
+
+ PolymorphicHasManyAssociation.prototype.apply = function(baseSaveError, base) {
+ var relations,
+ _this = this;
+ if (!baseSaveError) {
+ if (relations = this.getFromAttributes(base)) {
+ PolymorphicHasManyAssociation.__super__.apply.apply(this, arguments);
+ relations.forEach(function(model) {
+ return model.set(_this.foreignTypeKey, _this.modelType());
+ });
+ }
+ }
+ return true;
+ };
+
+ PolymorphicHasManyAssociation.prototype.getRelatedModelForType = function() {
+ return this.getRelatedModel();
+ };
+
+ PolymorphicHasManyAssociation.prototype.modelType = function() {
+ return this.model.get('resourceName');
+ };
+
+ PolymorphicHasManyAssociation.prototype.setIndex = function() {
+ if (!this.typeIndex) {
+ this.typeIndex = new Batman.PolymorphicAssociationSetIndex(this, this.modelType(), this[this.indexRelatedModelOn]);
+ }
+ return this.typeIndex;
+ };
+
+ PolymorphicHasManyAssociation.prototype.encoder = function() {
+ var association;
+ association = this;
+ return function(relationSet, _, __, record) {
+ var jsonArray;
+ if (relationSet != null) {
+ jsonArray = [];
+ relationSet.forEach(function(relation) {
+ var relationJSON;
+ relationJSON = relation.toJSON();
+ relationJSON[association.foreignKey] = record.get(association.primaryKey);
+ relationJSON[association.foreignTypeKey] = association.modelType();
+ return jsonArray.push(relationJSON);
+ });
+ }
+ return jsonArray;
+ };
+ };
+
+ return PolymorphicHasManyAssociation;
+
+ })(Batman.HasManyAssociation);
+
+}).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.SingularAssociation = (function(_super) {
+
+ __extends(SingularAssociation, _super);
+
+ function SingularAssociation() {
+ return SingularAssociation.__super__.constructor.apply(this, arguments);
+ }
+
+ SingularAssociation.prototype.isSingular = true;
+
+ SingularAssociation.prototype.getAccessor = function(self, model, label) {
+ var proxy, recordInAttributes;
+ 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();
+ }
+ });
+ return proxy;
+ }
+ };
+
+ SingularAssociation.prototype.setIndex = function() {
+ this.index || (this.index = new Batman.UniqueAssociationSetIndex(this, this[this.indexRelatedModelOn]));
+ return this.index;
+ };
+
+ return SingularAssociation;
+
+ })(Batman.Association);
+
+}).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.HasOneAssociation = (function(_super) {
+
+ __extends(HasOneAssociation, _super);
+
+ HasOneAssociation.prototype.associationType = 'hasOne';
+
+ HasOneAssociation.prototype.proxyClass = Batman.HasOneProxy;
+
+ HasOneAssociation.prototype.indexRelatedModelOn = 'foreignKey';
+
+ function HasOneAssociation() {
+ HasOneAssociation.__super__.constructor.apply(this, arguments);
+ this.primaryKey = this.options.primaryKey || "id";
+ this.foreignKey = this.options.foreignKey || ("" + (Batman.helpers.underscore(this.model.get('resourceName'))) + "_id");
+ }
+
+ HasOneAssociation.prototype.apply = function(baseSaveError, base) {
+ var relation;
+ if (relation = this.getFromAttributes(base)) {
+ return relation.set(this.foreignKey, base.get(this.primaryKey));
+ }
+ };
+
+ HasOneAssociation.prototype.encoder = function() {
+ var association;
+ association = this;
+ return function(val, key, object, record) {
+ var json;
+ if (!association.options.saveInline) {
+ return;
+ }
+ if (json = val.toJSON()) {
+ json[association.foreignKey] = record.get(association.primaryKey);
+ }
+ return json;
+ };
+ };
+
+ HasOneAssociation.prototype.decoder = function() {
+ var association;
+ association = this;
+ return function(data, _, __, ___, parentRecord) {
+ var record, relatedModel;
+ relatedModel = association.getRelatedModel();
+ record = new relatedModel();
+ record._withoutDirtyTracking(function() {
+ return this.fromJSON(data);
+ });
+ if (association.options.inverseOf) {
+ record.set(association.options.inverseOf, parentRecord);
+ }
+ record = relatedModel._mapIdentity(record);
+ return record;
+ };
+ };
+
+ return HasOneAssociation;
+
+ })(Batman.SingularAssociation);
+
+}).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.BelongsToAssociation = (function(_super) {
+
+ __extends(BelongsToAssociation, _super);
+
+ BelongsToAssociation.prototype.associationType = 'belongsTo';
+
+ BelongsToAssociation.prototype.proxyClass = Batman.BelongsToProxy;
+
+ BelongsToAssociation.prototype.indexRelatedModelOn = 'primaryKey';
+
+ BelongsToAssociation.prototype.defaultOptions = {
+ saveInline: false,
+ autoload: true,
+ encodeForeignKey: true
+ };
+
+ function BelongsToAssociation(model, label, options) {
+ if (options != null ? options.polymorphic : void 0) {
+ delete options.polymorphic;
+ 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.PolymorphicBelongsToAssociation, arguments, function(){});
+ }
+ BelongsToAssociation.__super__.constructor.apply(this, arguments);
+ this.foreignKey = this.options.foreignKey || ("" + this.label + "_id");
+ this.primaryKey = this.options.primaryKey || "id";
+ if (this.options.encodeForeignKey) {
+ this.model.encode(this.foreignKey);
+ }
+ }
+
+ BelongsToAssociation.prototype.encoder = function() {
+ return function(val) {
+ return val.toJSON();
+ };
+ };
+
+ BelongsToAssociation.prototype.decoder = function() {
+ var association;
+ association = this;
+ 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);
+ if (association.options.inverseOf) {
+ if (inverse = association.inverse()) {
+ if (inverse instanceof Batman.HasManyAssociation) {
+ childRecord.set(association.foreignKey, record.get(association.primaryKey));
+ } else {
+ record.set(inverse.label, childRecord);
+ }
+ }
+ }
+ childRecord.set(association.label, record);
+ return record;
+ };
+ };
+
+ BelongsToAssociation.prototype.apply = function(base) {
+ var foreignValue, model;
+ if (model = base.get(this.label)) {
+ foreignValue = model.get(this.primaryKey);
+ if (foreignValue !== void 0) {
+ return base.set(this.foreignKey, foreignValue);
+ }
+ }
+ };
+
+ return BelongsToAssociation;
+
+ })(Batman.SingularAssociation);
+
+}).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.PolymorphicBelongsToAssociation = (function(_super) {
+
+ __extends(PolymorphicBelongsToAssociation, _super);
+
+ PolymorphicBelongsToAssociation.prototype.isPolymorphic = true;
+
+ PolymorphicBelongsToAssociation.prototype.proxyClass = Batman.PolymorphicBelongsToProxy;
+
+ PolymorphicBelongsToAssociation.prototype.defaultOptions = Batman.mixin({}, Batman.BelongsToAssociation.prototype.defaultOptions, {
+ encodeForeignTypeKey: true
+ });
+
+ function PolymorphicBelongsToAssociation() {
+ PolymorphicBelongsToAssociation.__super__.constructor.apply(this, arguments);
+ this.foreignTypeKey = this.options.foreignTypeKey || ("" + this.label + "_type");
+ if (this.options.encodeForeignTypeKey) {
+ this.model.encode(this.foreignTypeKey);
+ }
+ this.typeIndicies = {};
+ }
+
+ PolymorphicBelongsToAssociation.prototype.getRelatedModel = false;
+
+ PolymorphicBelongsToAssociation.prototype.setIndex = false;
+
+ PolymorphicBelongsToAssociation.prototype.inverse = false;
+
+ PolymorphicBelongsToAssociation.prototype.apply = function(base) {
+ var foreignTypeValue, instanceOrProxy, model;
+ PolymorphicBelongsToAssociation.__super__.apply.apply(this, arguments);
+ if (instanceOrProxy = base.get(this.label)) {
+ if (instanceOrProxy instanceof Batman.AssociationProxy) {
+ model = instanceOrProxy.association.model;
+ } else {
+ model = instanceOrProxy.constructor;
+ }
+ foreignTypeValue = model.get('resourceName');
+ return base.set(this.foreignTypeKey, foreignTypeValue);
+ }
+ };
+
+ PolymorphicBelongsToAssociation.prototype.getAccessor = function(self, model, label) {
+ var proxy, recordInAttributes;
+ if (recordInAttributes = self.getFromAttributes(this)) {
+ return recordInAttributes;
+ }
+ if (self.getRelatedModelForType(this.get(self.foreignTypeKey))) {
+ proxy = this.associationProxy(self);
+ Batman.Property.withoutTracking(function() {
+ if (!proxy.get('loaded') && self.options.autoload) {
+ return proxy.load();
+ }
+ });
+ return proxy;
+ }
+ };
+
+ PolymorphicBelongsToAssociation.prototype.url = function(recordOptions) {
+ var ending, helper, id, inverse, root, type, _ref, _ref1;
+ type = (_ref = recordOptions.data) != null ? _ref[this.foreignTypeKey] : void 0;
+ if (type && (inverse = this.inverseForType(type))) {
+ root = Batman.helpers.pluralize(type).toLowerCase();
+ id = (_ref1 = recordOptions.data) != null ? _ref1[this.foreignKey] : void 0;
+ helper = inverse.isSingular ? "singularize" : "pluralize";
+ ending = Batman.helpers[helper](inverse.label);
+ return "/" + root + "/" + id + "/" + ending;
+ }
+ };
+
+ PolymorphicBelongsToAssociation.prototype.getRelatedModelForType = function(type) {
+ var relatedModel, scope;
+ scope = this.options.namespace || Batman.currentApp;
+ if (type) {
+ relatedModel = scope != null ? scope[type] : void 0;
+ relatedModel || (relatedModel = scope != null ? scope[Batman.helpers.camelize(type)] : void 0);
+ }
+ Batman.developer["do"](function() {
+ if ((Batman.currentApp != null) && !relatedModel) {
+ return Batman.developer.warn("Related model " + type + " for polymorphic association not found.");
+ }
+ });
+ return relatedModel;
+ };
+
+ PolymorphicBelongsToAssociation.prototype.setIndexForType = function(type) {
+ var _base;
+ (_base = this.typeIndicies)[type] || (_base[type] = new Batman.PolymorphicUniqueAssociationSetIndex(this, type, this.primaryKey));
+ return this.typeIndicies[type];
+ };
+
+ PolymorphicBelongsToAssociation.prototype.inverseForType = function(type) {
+ var inverse, relatedAssocs, _ref,
+ _this = this;
+ if (relatedAssocs = (_ref = this.getRelatedModelForType(type)) != null ? _ref._batman.get('associations') : void 0) {
+ if (this.options.inverseOf) {
+ return relatedAssocs.getByLabel(this.options.inverseOf);
+ }
+ inverse = null;
+ relatedAssocs.forEach(function(label, assoc) {
+ if (assoc.getRelatedModel() === _this.model) {
+ return inverse = assoc;
+ }
+ });
+ return inverse;
+ }
+ };
+
+ PolymorphicBelongsToAssociation.prototype.decoder = function() {
+ var association;
+ association = this;
+ return function(data, key, response, ___, childRecord) {
+ 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);
+ if (association.options.inverseOf) {
+ if (inverse = association.inverseForType(foreignTypeValue)) {
+ if (inverse instanceof Batman.PolymorphicHasManyAssociation) {
+ childRecord.set(association.foreignKey, record.get(association.primaryKey));
+ childRecord.set(association.foreignTypeKey, foreignTypeValue);
+ } else {
+ record.set(inverse.label, childRecord);
+ }
+ }
+ }
+ childRecord.set(association.label, record);
+ return record;
+ };
+ };
+
+ return PolymorphicBelongsToAssociation;
+
+ })(Batman.BelongsToAssociation);
+
+}).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.Validator = (function(_super) {
+
+ __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.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);
+ } else {
+ return this._batman.options = options;
+ }
+ };
+
+ Validator.matches = function(options) {
+ var key, results, shouldReturn, value, _ref, _ref1;
+ results = {};
+ 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)) {
+ results[key] = value;
+ shouldReturn = true;
+ }
+ }
+ if (shouldReturn) {
+ return results;
+ }
+ };
+
+ return Validator;
+
+ })(Batman.Object);
+
+}).call(this);
+
+(function() {
+
+ Batman.Validators = [];
+
+ Batman.extend(Batman.translate.messages, {
+ errors: {
+ format: "%{attribute} %{message}",
+ messages: {
+ too_short: "must be at least %{count} characters",
+ too_long: "must be less than %{count} characters",
+ wrong_length: "must be %{count} characters",
+ blank: "can't be blank",
+ not_numeric: "must be a number",
+ not_matching: "is not valid"
+ }
+ }
+ });
+
+}).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.RegExpValidator = (function(_super) {
+
+ __extends(RegExpValidator, _super);
+
+ RegExpValidator.options('regexp', 'pattern');
+
+ function RegExpValidator(options) {
+ var _ref;
+ this.regexp = (_ref = options.regexp) != null ? _ref : options.pattern;
+ RegExpValidator.__super__.constructor.apply(this, arguments);
+ }
+
+ 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'));
+ }
+ }
+ return callback();
+ };
+
+ return RegExpValidator;
+
+ })(Batman.Validator);
+
+ Batman.Validators.push(Batman.RegExpValidator);
+
+}).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.PresenceValidator = (function(_super) {
+
+ __extends(PresenceValidator, _super);
+
+ function PresenceValidator() {
+ return PresenceValidator.__super__.constructor.apply(this, arguments);
+ }
+
+ PresenceValidator.options('presence');
+
+ PresenceValidator.prototype.validateEach = function(errors, record, key, callback) {
+ var value;
+ value = record.get(key);
+ if (this.options.presence && (!(value != null) || value === '')) {
+ errors.add(key, this.format(key, 'blank'));
+ }
+ return callback();
+ };
+
+ return PresenceValidator;
+
+ })(Batman.Validator);
+
+ Batman.Validators.push(Batman.PresenceValidator);
+
+}).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.NumericValidator = (function(_super) {
+
+ __extends(NumericValidator, _super);
+
+ function NumericValidator() {
+ return NumericValidator.__super__.constructor.apply(this, arguments);
+ }
+
+ NumericValidator.options('numeric');
+
+ NumericValidator.prototype.validateEach = function(errors, record, key, callback) {
+ var value;
+ value = record.get(key);
+ if (this.options.numeric && isNaN(parseFloat(value))) {
+ errors.add(key, this.format(key, 'not_numeric'));
+ }
+ return callback();
+ };
+
+ return NumericValidator;
+
+ })(Batman.Validator);
+
+ Batman.Validators.push(Batman.NumericValidator);
+
+}).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.LengthValidator = (function(_super) {
+
+ __extends(LengthValidator, _super);
+
+ LengthValidator.options('minLength', 'maxLength', 'length', 'lengthWithin', 'lengthIn');
+
+ function LengthValidator(options) {
+ var range;
+ if (range = options.lengthIn || options.lengthWithin) {
+ options.minLength = range[0];
+ options.maxLength = range[1] || -1;
+ delete options.lengthWithin;
+ delete options.lengthIn;
+ }
+ LengthValidator.__super__.constructor.apply(this, arguments);
+ }
+
+ LengthValidator.prototype.validateEach = function(errors, record, key, callback) {
+ var options, value, _ref;
+ options = this.options;
+ value = (_ref = record.get(key)) != null ? _ref : [];
+ if (options.minLength && value.length < options.minLength) {
+ errors.add(key, this.format(key, 'too_short', {
+ count: options.minLength
+ }));
+ }
+ if (options.maxLength && value.length > options.maxLength) {
+ errors.add(key, this.format(key, 'too_long', {
+ count: options.maxLength
+ }));
+ }
+ if (options.length && value.length !== options.length) {
+ errors.add(key, this.format(key, 'wrong_length', {
+ count: options.length
+ }));
+ }
+ return callback();
+ };
+
+ return LengthValidator;
+
+ })(Batman.Validator);
+
+ Batman.Validators.push(Batman.LengthValidator);
+
+}).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);
+
+ ControllerActionFrame.prototype.operationOccurred = false;
+
+ ControllerActionFrame.prototype.remainingOperations = 0;
+
+ ControllerActionFrame.prototype.event('complete').oneShot = true;
+
+ function ControllerActionFrame(options, onComplete) {
+ ControllerActionFrame.__super__.constructor.call(this, options);
+ this.on('complete', onComplete);
+ }
+
+ ControllerActionFrame.prototype.startOperation = function(options) {
+ if (options == null) {
+ options = {};
+ }
+ if (!options.internal) {
+ this.operationOccurred = true;
+ }
+ this._changeOperationsCounter(1);
+ return true;
+ };
+
+ ControllerActionFrame.prototype.finishOperation = function() {
+ this._changeOperationsCounter(-1);
+ return true;
+ };
+
+ ControllerActionFrame.prototype.startAndFinishOperation = function(options) {
+ this.startOperation(options);
+ this.finishOperation(options);
+ return true;
+ };
+
+ ControllerActionFrame.prototype._changeOperationsCounter = function(delta) {
+ var _ref;
+ this.remainingOperations += delta;
+ if (this.remainingOperations === 0) {
+ this.fire('complete');
+ }
+ if ((_ref = this.parentFrame) != null) {
+ _ref._changeOperationsCounter(delta);
+ }
+ };
+
+ return ControllerActionFrame;
+
+ })(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.DOM.InsertionBinding = (function(_super) {
+
+ __extends(InsertionBinding, _super);
+
+ InsertionBinding.prototype.isTwoWay = false;
+
+ InsertionBinding.prototype.bindImmediately = false;
+
+ function InsertionBinding(node, className, key, context, parentRenderer, invert) {
+ var result,
+ _this = this;
+ this.invert = invert != null ? invert : false;
+ this.placeholderNode = document.createComment("detached node " + (this.get('_batmanID')));
+ result = InsertionBinding.__super__.constructor.apply(this, arguments);
+ Batman.DOM.onParseExit(this.node, function() {
+ _this.bind();
+ if (_this.placeholderNode != null) {
+ return Batman.DOM.trackBinding(_this, _this.placeholderNode);
+ }
+ });
+ result;
+
+ }
+
+ InsertionBinding.prototype.dataChange = function(value) {
+ var parentNode;
+ parentNode = this.placeholderNode.parentNode || this.node.parentNode;
+ if (!!value === !this.invert) {
+ if (!(this.node.parentNode != null)) {
+ Batman.DOM.insertBefore(parentNode, this.node, this.placeholderNode);
+ return parentNode.removeChild(this.placeholderNode);
+ }
+ } else {
+ parentNode.insertBefore(this.placeholderNode, this.node);
+ return Batman.DOM.removeNode(this.node);
+ }
+ };
+
+ InsertionBinding.prototype.die = function() {
+ if (this.dead) {
+ return;
+ }
+ InsertionBinding.__super__.die.apply(this, arguments);
+ if (!!this.get('filteredValue') === !this.invert) {
+ return Batman.DOM.destroyNode(this.placeholderNode);
+ } else {
+ return Batman.DOM.destroyNode(this.node);
+ }
+ };
+
+ return InsertionBinding;
+
+ })(Batman.DOM.AbstractBinding);
+
+}).call(this);
+
+(function() {
+ var isEmptyDataObject;
+
+ isEmptyDataObject = function(obj) {
+ var name;
+ for (name in obj) {
+ return false;
+ }
+ return true;
+ };
+
+ Batman.extend(Batman, {
+ cache: {},
+ uuid: 0,
+ expando: "batman" + Math.random().toString().replace(/\D/g, ''),
+ canDeleteExpando: (function() {
+ var div;
+ try {
+ div = document.createElement('div');
+ return delete div.test;
+ } catch (e) {
+ return Batman.canDeleteExpando = false;
+ }
+ })(),
+ noData: {
+ "embed": true,
+ "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",
+ "applet": true
+ },
+ hasData: function(elem) {
+ elem = (elem.nodeType ? Batman.cache[elem[Batman.expando]] : elem[Batman.expando]);
+ return !!elem && !isEmptyDataObject(elem);
+ },
+ data: function(elem, name, data, pvt) {
+ var cache, getByName, id, internalKey, ret, thisCache;
+ if (!Batman.acceptData(elem)) {
+ return;
+ }
+ internalKey = Batman.expando;
+ getByName = typeof name === "string";
+ cache = Batman.cache;
+ id = elem[Batman.expando];
+ if ((!id || (pvt && id && (cache[id] && !cache[id][internalKey]))) && getByName && data === void 0) {
+ return;
+ }
+ if (!id) {
+ if (elem.nodeType !== 3) {
+ elem[Batman.expando] = id = ++Batman.uuid;
+ } else {
+ id = Batman.expando;
+ }
+ }
+ if (!cache[id]) {
+ cache[id] = {};
+ }
+ if (typeof name === "object" || typeof name === "function") {
+ if (pvt) {
+ cache[id][internalKey] = Batman.extend(cache[id][internalKey], name);
+ } else {
+ cache[id] = Batman.extend(cache[id], name);
+ }
+ }
+ thisCache = cache[id];
+ if (pvt) {
+ thisCache[internalKey] || (thisCache[internalKey] = {});
+ thisCache = thisCache[internalKey];
+ }
+ if (data !== void 0) {
+ thisCache[name] = data;
+ }
+ if (getByName) {
+ ret = thisCache[name];
+ } else {
+ ret = thisCache;
+ }
+ return ret;
+ },
+ removeData: function(elem, name, pvt) {
+ var cache, id, internalCache, internalKey, isNode, thisCache;
+ if (!Batman.acceptData(elem)) {
+ return;
+ }
+ internalKey = Batman.expando;
+ isNode = elem.nodeType;
+ cache = Batman.cache;
+ id = elem[Batman.expando];
+ if (!cache[id]) {
+ return;
+ }
+ if (name) {
+ thisCache = pvt ? cache[id][internalKey] : cache[id];
+ if (thisCache) {
+ delete thisCache[name];
+ if (!isEmptyDataObject(thisCache)) {
+ return;
+ }
+ }
+ }
+ if (pvt) {
+ delete cache[id][internalKey];
+ if (!isEmptyDataObject(cache[id])) {
+ return;
+ }
+ }
+ internalCache = cache[id][internalKey];
+ if (Batman.canDeleteExpando || !cache.setInterval) {
+ delete cache[id];
+ } else {
+ cache[id] = null;
+ }
+ if (internalCache) {
+ cache[id] = {};
+ return cache[id][internalKey] = internalCache;
+ } else {
+ if (Batman.canDeleteExpando) {
+ return delete elem[Batman.expando];
+ } else if (elem.removeAttribute) {
+ return elem.removeAttribute(Batman.expando);
+ } else {
+ return elem[Batman.expando] = null;
+ }
+ }
+ },
+ _data: function(elem, name, data) {
+ return Batman.data(elem, name, data, true);
+ },
+ acceptData: function(elem) {
+ var match;
+ if (elem.nodeName) {
+ match = Batman.noData[elem.nodeName.toLowerCase()];
+ if (match) {
+ return !(match === true || elem.getAttribute("classid") !== match);
+ }
+ }
+ return true;
+ }
+ });
+
+}).call(this);
+
+(function() {
+ var buntUndefined, defaultAndOr,
+ __slice = [].slice;
+
+ buntUndefined = function(f) {
+ return function(value) {
+ if (typeof value === 'undefined') {
+ return void 0;
+ } else {
+ return f.apply(this, arguments);
+ }
+ };
+ };
+
+ defaultAndOr = function(lhs, rhs) {
+ return lhs || rhs;
+ };
+
+ Batman.Filters = {
+ raw: buntUndefined(function(value, binding) {
+ binding.escapeValue = false;
+ return value;
+ }),
+ get: buntUndefined(function(value, key) {
+ if (value.get != null) {
+ return value.get(key);
+ } else {
+ return value[key];
+ }
+ }),
+ equals: buntUndefined(function(lhs, rhs, binding) {
+ return lhs === rhs;
+ }),
+ and: function(lhs, rhs) {
+ return lhs && rhs;
+ },
+ or: function(lhs, rhs, binding) {
+ return lhs || rhs;
+ },
+ not: function(value, binding) {
+ return !!!value;
+ },
+ matches: buntUndefined(function(value, searchFor) {
+ return value.indexOf(searchFor) !== -1;
+ }),
+ truncate: buntUndefined(function(value, length, end, binding) {
+ if (end == null) {
+ end = "...";
+ }
+ if (!binding) {
+ binding = end;
+ end = "...";
+ }
+ if (value.length > length) {
+ value = value.substr(0, length - end.length) + end;
+ }
+ return value;
+ }),
+ "default": function(value, defaultValue, binding) {
+ if ((value != null) && value !== '') {
+ return value;
+ } else {
+ return defaultValue;
+ }
+ },
+ prepend: function(value, string, binding) {
+ return string + value;
+ },
+ append: function(value, string, binding) {
+ return value + string;
+ },
+ replace: buntUndefined(function(value, searchFor, replaceWith, flags, binding) {
+ if (!binding) {
+ binding = flags;
+ flags = void 0;
+ }
+ if (flags === void 0) {
+ return value.replace(searchFor, replaceWith);
+ } else {
+ return value.replace(searchFor, replaceWith, flags);
+ }
+ }),
+ downcase: buntUndefined(function(value) {
+ return value.toLowerCase();
+ }),
+ upcase: buntUndefined(function(value) {
+ return value.toUpperCase();
+ }),
+ pluralize: buntUndefined(function(string, count, includeCount, binding) {
+ if (!binding) {
+ binding = includeCount;
+ includeCount = true;
+ if (!binding) {
+ binding = count;
+ count = void 0;
+ }
+ }
+ if (count) {
+ return Batman.helpers.pluralize(count, string, void 0, includeCount);
+ } else {
+ return Batman.helpers.pluralize(string);
+ }
+ }),
+ humanize: buntUndefined(function(string, binding) {
+ return Batman.helpers.humanize(string);
+ }),
+ join: buntUndefined(function(value, withWhat, binding) {
+ if (withWhat == null) {
+ withWhat = '';
+ }
+ if (!binding) {
+ binding = withWhat;
+ withWhat = '';
+ }
+ return value.join(withWhat);
+ }),
+ sort: buntUndefined(function(value) {
+ return value.sort();
+ }),
+ map: buntUndefined(function(value, key) {
+ return value.map(function(x) {
+ return Batman.get(x, key);
+ });
+ }),
+ has: function(set, item) {
+ if (set == null) {
+ return false;
+ }
+ return Batman.contains(set, item);
+ },
+ first: buntUndefined(function(value) {
+ return value[0];
+ }),
+ meta: buntUndefined(function(value, keypath) {
+ Batman.developer.assert(value.meta, "Error, value doesn't have a meta to filter on!");
+ return value.meta.get(keypath);
+ }),
+ interpolate: function(string, interpolationKeypaths, binding) {
+ var k, v, values;
+ if (!binding) {
+ binding = interpolationKeypaths;
+ interpolationKeypaths = void 0;
+ }
+ if (!string) {
+ return;
+ }
+ values = {};
+ for (k in interpolationKeypaths) {
+ v = interpolationKeypaths[k];
+ values[k] = this.get(v);
+ if (!(values[k] != null)) {
+ Batman.developer.warn("Warning! Undefined interpolation key " + k + " for interpolation", string);
+ values[k] = '';
+ }
+ }
+ return Batman.helpers.interpolate(string, values);
+ },
+ withArguments: function() {
+ var binding, block, curryArgs, _i;
+ block = arguments[0], curryArgs = 3 <= arguments.length ? __slice.call(arguments, 1, _i = arguments.length - 1) : (_i = 1, []), binding = arguments[_i++];
+ if (!block) {
+ return;
+ }
+ return function() {
+ var regularArgs;
+ regularArgs = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
+ return block.call.apply(block, [this].concat(__slice.call(curryArgs), __slice.call(regularArgs)));
+ };
+ },
+ routeToAction: buntUndefined(function(model, action) {
+ var params;
+ params = Batman.Dispatcher.paramsFromArgument(model);
+ params.action = action;
+ return params;
+ }),
+ escape: buntUndefined(Batman.escapeHTML)
+ };
+
+ (function() {
+ var k, _i, _len, _ref, _results;
+ _ref = ['capitalize', 'singularize', 'underscore', 'camelize'];
+ _results = [];
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ k = _ref[_i];
+ _results.push(Batman.Filters[k] = buntUndefined(Batman.helpers[k]));
+ }
+ return _results;
+ })();
+
+ Batman.developer.addFilters();
+
+}).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.RenderContext = (function() {
+ var ContextProxy;
+
+ RenderContext.deProxy = function(object) {
+ if ((object != null) && object.isContextProxy) {
+ return object.get('proxiedObject');
+ } else {
+ return object;
+ }
+ };
+
+ RenderContext.root = function() {
+ var root;
+ if (Batman.currentApp != null) {
+ root = Batman.currentApp.get('_renderContext');
+ }
+ return root != null ? root : root = this.base;
+ };
+
+ RenderContext.prototype.windowWrapper = {
+ window: Batman.container
+ };
+
+ function RenderContext(object, parent) {
+ this.object = object;
+ this.parent = parent;
+ }
+
+ RenderContext.prototype.findKey = function(key) {
+ var base, currentNode, val;
+ base = key.split('.')[0].split('|')[0].trim();
+ currentNode = this;
+ while (currentNode) {
+ val = Batman.get(currentNode.object, base);
+ if (typeof val !== 'undefined') {
+ val = Batman.get(currentNode.object, key);
+ return [val, currentNode.object].map(this.constructor.deProxy);
+ }
+ currentNode = currentNode.parent;
+ }
+ return [Batman.get(this.windowWrapper, key), this.windowWrapper];
+ };
+
+ RenderContext.prototype.get = function(key) {
+ return this.findKey(key)[0];
+ };
+
+ RenderContext.prototype.contextForKey = function(key) {
+ return this.findKey(key)[1];
+ };
+
+ RenderContext.prototype.descend = function(object, scopedKey) {
+ var oldObject;
+ if (scopedKey) {
+ oldObject = object;
+ object = new Batman.Object();
+ object[scopedKey] = oldObject;
+ }
+ return new this.constructor(object, this);
+ };
+
+ RenderContext.prototype.descendWithKey = function(key, scopedKey) {
+ var proxy;
+ proxy = new ContextProxy(this, key);
+ return this.descend(proxy, scopedKey);
+ };
+
+ RenderContext.prototype.chain = function() {
+ var parent, x;
+ x = [];
+ parent = this;
+ while (parent) {
+ x.push(parent.object);
+ parent = parent.parent;
+ }
+ return x;
+ };
+
+ RenderContext.ContextProxy = ContextProxy = (function(_super) {
+
+ __extends(ContextProxy, _super);
+
+ ContextProxy.prototype.isContextProxy = true;
+
+ ContextProxy.accessor('proxiedObject', function() {
+ return this.binding.get('filteredValue');
+ });
+
+ ContextProxy.accessor({
+ get: function(key) {
+ return this.get("proxiedObject." + key);
+ },
+ set: function(key, value) {
+ return this.set("proxiedObject." + key, value);
+ },
+ unset: function(key) {
+ return this.unset("proxiedObject." + key);
+ }
+ });
+
+ function ContextProxy(renderContext, keyPath, localKey) {
+ this.renderContext = renderContext;
+ this.keyPath = keyPath;
+ this.localKey = localKey;
+ this.binding = new Batman.DOM.AbstractBinding(void 0, this.keyPath, this.renderContext);
+ }
+
+ return ContextProxy;
+
+ })(Batman.Object);
+
+ return RenderContext;
+
+ }).call(this);
+
+ Batman.RenderContext.base = new Batman.RenderContext(Batman.RenderContext.prototype.windowWrapper);
+
+}).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.ViewStore = (function(_super) {
+
+ __extends(ViewStore, _super);
+
+ ViewStore.prefix = 'views';
+
+ ViewStore.fetchFromRemote = true;
+
+ function ViewStore() {
+ ViewStore.__super__.constructor.apply(this, arguments);
+ this._viewContents = {};
+ this._requestedPaths = new Batman.SimpleSet;
+ }
+
+ ViewStore.prototype.propertyClass = Batman.Property;
+
+ ViewStore.prototype.fetchView = function(path) {
+ var _this = this;
+ return new Batman.Request({
+ url: Batman.Navigator.normalizePath(this.constructor.prefix, "" + path + ".html"),
+ type: 'html',
+ success: function(response) {
+ return _this.set(path, response);
+ },
+ error: function(response) {
+ throw new Error("Could not load view from " + path);
+ }
+ });
+ };
+
+ ViewStore.accessor({
+ 'final': true,
+ get: function(path) {
+ var contents;
+ if (path[0] !== '/') {
+ return this.get("/" + path);
+ }
+ if (this._viewContents[path]) {
+ return this._viewContents[path];
+ }
+ if (this._requestedPaths.has(path)) {
+ return;
+ }
+ if (contents = this._sourceFromDOM(path)) {
+ return contents;
+ }
+ if (this.constructor.fetchFromRemote) {
+ this.fetchView(path);
+ } else {
+ throw new Error("Couldn't find view source for \'" + path + "\'!");
+ }
+ },
+ set: function(path, content) {
+ if (path[0] !== '/') {
+ return this.set("/" + path, content);
+ }
+ this._requestedPaths.add(path);
+ return this._viewContents[path] = content;
+ }
+ });
+
+ ViewStore.prototype.prefetch = function(path) {
+ this.get(path);
+ return true;
+ };
+
+ ViewStore.prototype._sourceFromDOM = function(path) {
+ var node, relativePath;
+ relativePath = path.slice(1);
+ if (node = Batman.DOM.querySelector(document, "[data-defineview*='" + relativePath + "']")) {
+ Batman.setImmediate(function() {
+ var _ref;
+ return (_ref = node.parentNode) != null ? _ref.removeChild(node) : void 0;
+ });
+ return Batman.DOM.defineView(path, node);
+ }
+ };
+
+ return ViewStore;
+
+ })(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;
+
+ Batman.View = (function(_super) {
+
+ __extends(View, _super);
+
+ View.YieldStorage = (function(_super1) {
+
+ __extends(YieldStorage, _super1);
+
+ function YieldStorage() {
+ return YieldStorage.__super__.constructor.apply(this, arguments);
+ }
+
+ YieldStorage.wrapAccessor(function(core) {
+ return {
+ get: function(key) {
+ var val;
+ val = core.get.call(this, key);
+ if (!(val != null)) {
+ val = this.set(key, []);
+ }
+ return val;
+ }
+ };
+ });
+
+ return YieldStorage;
+
+ })(Batman.Hash);
+
+ View.store = new Batman.ViewStore();
+
+ View.option = function() {
+ var keys,
+ _this = this;
+ 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;
+ }]));
+ };
+
+ View.prototype.isView = true;
+
+ View.prototype.cache = true;
+
+ View.prototype._rendered = false;
+
+ View.prototype.node = null;
+
+ View.prototype.event('ready').oneShot = true;
+
+ View.accessor('html', {
+ get: function() {
+ var source;
+ if (this.html && this.html.length > 0) {
+ return this.html;
+ }
+ if (!(source = this.get('source'))) {
+ return;
+ }
+ source = Batman.Navigator.normalizePath(source);
+ return this.html = this.constructor.store.get(source);
+ },
+ set: function(_, html) {
+ return this.html = html;
+ }
+ });
+
+ View.accessor('node', {
+ get: function() {
+ var html;
+ if (this.node == null) {
+ html = this.get('html');
+ if (!(html && html.length > 0)) {
+ return;
+ }
+ this.node = document.createElement('div');
+ this._setNodeOwner(this.node);
+ Batman.setInnerHTML(this.node, html);
+ }
+ return this.node;
+ },
+ set: function(_, node) {
+ var updateHTML,
+ _this = this;
+ this.node = node;
+ this._setNodeOwner(node);
+ updateHTML = function(html) {
+ if (html != null) {
+ Batman.setInnerHTML(_this.node, html);
+ return _this.forget('html', updateHTML);
+ }
+ };
+ this.observeAndFire('html', updateHTML);
+ return node;
+ }
+ });
+
+ View.accessor('yields', function() {
+ return new this.constructor.YieldStorage;
+ });
+
+ View.accessor('fetched?', function() {
+ return this.get('source') != null;
+ });
+
+ View.accessor('readyToRender', function() {
+ var _ref;
+ return this.get('node') && (this.get('fetched?') ? ((_ref = this.get('html')) != null ? _ref.length : void 0) > 0 : true);
+ });
+
+ function View(options) {
+ var context,
+ _this = this;
+ if (options == null) {
+ options = {};
+ }
+ context = options.context;
+ if (context) {
+ if (!(context instanceof Batman.RenderContext)) {
+ context = Batman.RenderContext.root().descend(context);
+ }
+ } else {
+ context = Batman.RenderContext.root();
+ }
+ options.context = context.descend(this);
+ View.__super__.constructor.call(this, options);
+ Batman.Property.withoutTracking(function() {
+ return _this.observeAndFire('readyToRender', function(ready) {
+ if (ready) {
+ return _this.render();
+ }
+ });
+ });
+ }
+
+ View.prototype.render = function() {
+ var node,
+ _this = this;
+ if (this._rendered) {
+ return;
+ }
+ this._rendered = true;
+ this._renderer = new Batman.Renderer(node = this.get('node'), this.get('context'), this);
+ return this._renderer.on('rendered', function() {
+ return _this.fire('ready', node);
+ });
+ };
+
+ View.prototype.isInDOM = function() {
+ var node;
+ if ((node = this.get('node'))) {
+ return (node.parentNode != null) || this.get('yields').some(function(name, nodes) {
+ var _i, _len;
+ for (_i = 0, _len = nodes.length; _i < _len; _i++) {
+ node = nodes[_i].node;
+ if (node.parentNode != null) {
+ return true;
+ }
+ }
+ return false;
+ });
+ } else {
+ return false;
+ }
+ };
+
+ View.prototype.applyYields = function() {
+ return this.get('yields').forEach(function(name, nodes) {
+ var action, node, yieldObject, _i, _len, _ref, _results;
+ yieldObject = Batman.DOM.Yield.withName(name);
+ _results = [];
+ for (_i = 0, _len = nodes.length; _i < _len; _i++) {
+ _ref = nodes[_i], node = _ref.node, action = _ref.action;
+ _results.push(yieldObject[action](node));
+ }
+ return _results;
+ });
+ };
+
+ View.prototype.retractYields = function() {
+ return this.get('yields').forEach(function(name, nodes) {
+ var node, _i, _len, _ref, _results;
+ _results = [];
+ for (_i = 0, _len = nodes.length; _i < _len; _i++) {
+ node = nodes[_i].node;
+ _results.push((_ref = node.parentNode) != null ? _ref.removeChild(node) : void 0);
+ }
+ return _results;
+ });
+ };
+
+ View.prototype.pushYieldAction = function(key, action, node) {
+ this._setNodeYielder(node);
+ return this.get("yields").get(key).push({
+ node: node,
+ action: action
+ });
+ };
+
+ View.prototype._argumentBindingKey = function(key) {
+ return "_" + key + "ArgumentBinding";
+ };
+
+ View.prototype._setNodeOwner = function(node) {
+ return Batman._data(node, 'view', this);
+ };
+
+ View.prototype._setNodeYielder = function(node) {
+ return Batman._data(node, 'yielder', this);
+ };
+
+ View.prototype.on('ready', function() {
+ return typeof this.ready === "function" ? this.ready.apply(this, arguments) : void 0;
+ });
+
+ View.prototype.on('appear', function() {
+ return typeof this.viewDidAppear === "function" ? this.viewDidAppear.apply(this, arguments) : void 0;
+ });
+
+ View.prototype.on('disappear', function() {
+ return typeof this.viewDidDisappear === "function" ? this.viewDidDisappear.apply(this, arguments) : void 0;
+ });
+
+ View.prototype.on('beforeAppear', function() {
+ return typeof this.viewWillAppear === "function" ? this.viewWillAppear.apply(this, arguments) : void 0;
+ });
+
+ View.prototype.on('beforeDisappear', function() {
+ return typeof this.viewWillDisappear === "function" ? this.viewWillDisappear.apply(this, arguments) : void 0;
+ });
+
+ return View;
+
+ }).call(this, Batman.Object);
+
+}).call(this);
+
+(function() {
+ var Yield,
+ __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.DOM.Yield = Yield = (function(_super) {
+
+ __extends(Yield, _super);
+
+ Yield.yields = {};
+
+ Yield.queued = function(fn) {
+ return function() {
+ var args, handler,
+ _this = this;
+ args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
+ if (this.containerNode != null) {
+ return fn.apply(this, args);
+ } else {
+ return handler = this.observe('containerNode', function() {
+ var result;
+ result = fn.apply(_this, args);
+ _this.forget('containerNode', handler);
+ return result;
+ });
+ }
+ };
+ };
+
+ Yield.reset = function() {
+ return this.yields = {};
+ };
+
+ Yield.withName = function(name) {
+ var _base;
+ (_base = this.yields)[name] || (_base[name] = new this({
+ name: name
+ }));
+ return this.yields[name];
+ };
+
+ Yield.forEach = function(f) {
+ var name, yieldObject, _ref;
+ _ref = this.yields;
+ for (name in _ref) {
+ yieldObject = _ref[name];
+ f(yieldObject);
+ }
+ };
+
+ Yield.clearAll = function() {
+ return this.forEach(function(yieldObject) {
+ return yieldObject.clear();
+ });
+ };
+
+ Yield.cycleAll = function() {
+ return this.forEach(function(yieldObject) {
+ return yieldObject.cycle();
+ });
+ };
+
+ Yield.clearAllStale = function() {
+ return this.forEach(function(yieldObject) {
+ return yieldObject.clearStale();
+ });
+ };
+
+ function Yield() {
+ this.cycle();
+ }
+
+ Yield.prototype.cycle = function() {
+ return this.currentVersionNodes = [];
+ };
+
+ Yield.prototype.clear = Yield.queued(function() {
+ var child, _i, _len, _ref, _results;
+ this.cycle();
+ _ref = (function() {
+ var _j, _len, _ref, _results1;
+ _ref = this.containerNode.childNodes;
+ _results1 = [];
+ for (_j = 0, _len = _ref.length; _j < _len; _j++) {
+ child = _ref[_j];
+ _results1.push(child);
+ }
+ return _results1;
+ }).call(this);
+ _results = [];
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ child = _ref[_i];
+ _results.push(Batman.removeOrDestroyNode(child));
+ }
+ return _results;
+ });
+
+ Yield.prototype.clearStale = Yield.queued(function() {
+ var child, _i, _len, _ref, _results;
+ _ref = (function() {
+ var _j, _len, _ref, _results1;
+ _ref = this.containerNode.childNodes;
+ _results1 = [];
+ for (_j = 0, _len = _ref.length; _j < _len; _j++) {
+ child = _ref[_j];
+ _results1.push(child);
+ }
+ return _results1;
+ }).call(this);
+ _results = [];
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ child = _ref[_i];
+ if (!~this.currentVersionNodes.indexOf(child)) {
+ _results.push(Batman.removeOrDestroyNode(child));
+ }
+ }
+ return _results;
+ });
+
+ Yield.prototype.append = Yield.queued(function(node) {
+ this.currentVersionNodes.push(node);
+ return Batman.appendChild(this.containerNode, node, true);
+ });
+
+ Yield.prototype.replace = Yield.queued(function(node) {
+ this.clear();
+ return this.append(node);
+ });
+
+ return Yield;
+
+ })(Batman.Object);
+
+}).call(this);
+
+(function() {
+
+
+
+}).call(this); \ No newline at end of file