12367 lines
401 KiB
JavaScript
12367 lines
401 KiB
JavaScript
(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.13.0';
|
|
|
|
Batman.config = {
|
|
pathPrefix: '/',
|
|
viewPrefix: 'views',
|
|
fetchRemoteViews: true,
|
|
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 _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 = {
|
|
"&": "&",
|
|
"<": "<",
|
|
">": ">",
|
|
"\"": """,
|
|
"'": "'"
|
|
};
|
|
return function(s) {
|
|
return ("" + s).replace(/[&<>'"]/g, function(c) {
|
|
return replacements[c];
|
|
});
|
|
};
|
|
})();
|
|
|
|
Batman.translate = function(x, values) {
|
|
if (values == null) {
|
|
values = {};
|
|
}
|
|
return Batman.helpers.interpolate(Batman.get(Batman.translate.messages, x), values);
|
|
};
|
|
|
|
Batman.translate.messages = {};
|
|
|
|
Batman.t = function() {
|
|
return Batman.translate.apply(Batman, arguments);
|
|
};
|
|
|
|
Batman.redirect = function(url) {
|
|
var _ref;
|
|
return (_ref = Batman.navigator) != null ? _ref.redirect(url) : void 0;
|
|
};
|
|
|
|
Batman.initializeObject = function(object) {
|
|
if (object._batman != null) {
|
|
return object._batman.check(object);
|
|
} else {
|
|
return object._batman = new Batman._Batman(object);
|
|
}
|
|
};
|
|
|
|
}).call(this);
|
|
|
|
(function() {
|
|
var __slice = [].slice,
|
|
__indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
|
|
|
|
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 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() {
|
|
var handler, key, keys, _i, _j, _len, _results;
|
|
keys = 2 <= arguments.length ? __slice.call(arguments, 0, _i = arguments.length - 1) : (_i = 0, []), handler = arguments[_i++];
|
|
_results = [];
|
|
for (_j = 0, _len = keys.length; _j < _len; _j++) {
|
|
key = keys[_j];
|
|
_results.push(this.event(key).addHandler(handler));
|
|
}
|
|
return _results;
|
|
},
|
|
once: function(key, handler) {
|
|
var event, handlerWrapper;
|
|
event = this.event(key);
|
|
handlerWrapper = function() {
|
|
handler.apply(this, arguments);
|
|
return event.removeHandler(handlerWrapper);
|
|
};
|
|
return event.addHandler(handlerWrapper);
|
|
},
|
|
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;
|
|
},
|
|
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.DOM.setInnerHTML(container, '');
|
|
Batman.DOM.appendChild(container, view.get('node'));
|
|
return renderer.allowAndFire('rendered');
|
|
});
|
|
},
|
|
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: 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.DOM.propagateBindingEvents(child);
|
|
}
|
|
if (bindings = Batman._data(newNode, 'bindings')) {
|
|
for (_j = 0, _len1 = bindings.length; _j < _len1; _j++) {
|
|
binding = bindings[_j];
|
|
Batman.DOM.propagateBindingEvent(binding, newNode);
|
|
}
|
|
}
|
|
},
|
|
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.DOM.propagateBindingEvent(binding, node);
|
|
return true;
|
|
},
|
|
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: 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;
|
|
},
|
|
setStyleProperty: function(node, property, value, importance) {
|
|
if (node.style.setProperty) {
|
|
return node.style.setProperty(property, value, importance);
|
|
} else {
|
|
return node.style.setAttribute(property, value, importance);
|
|
}
|
|
},
|
|
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: function(parentNode, newNode, referenceNode) {
|
|
if (referenceNode == null) {
|
|
referenceNode = null;
|
|
}
|
|
if (!referenceNode || parentNode.childNodes.length <= 0) {
|
|
return Batman.DOM.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.DOM.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: 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.DOM.hasAddEventListener) {
|
|
return node.addEventListener(eventName, callback, false);
|
|
} else {
|
|
return node.attachEvent("on" + eventName, callback);
|
|
}
|
|
},
|
|
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.DOM.hasAddEventListener) {
|
|
return node.removeEventListener(eventName, callback, false);
|
|
} else {
|
|
return node.detachEvent('on' + eventName, callback);
|
|
}
|
|
},
|
|
hasAddEventListener: !!(typeof window !== "undefined" && window !== null ? window.addEventListener : void 0),
|
|
preventDefault: function(e) {
|
|
if (typeof e.preventDefault === "function") {
|
|
return e.preventDefault();
|
|
} else {
|
|
return e.returnValue = false;
|
|
}
|
|
},
|
|
stopPropagation: 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.DOM.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.DOM.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.DOM.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.DOM.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.DOM.addEventListener(node, eventName, function() {
|
|
var args, event;
|
|
event = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
|
|
if (event.metaKey || event.ctrlKey) {
|
|
return;
|
|
}
|
|
Batman.DOM.preventDefault(event);
|
|
if (!Batman.DOM.eventIsAllowed(eventName, event)) {
|
|
return;
|
|
}
|
|
return callback.apply(null, [node, event].concat(__slice.call(args), [context]));
|
|
});
|
|
if (node.nodeName.toUpperCase() === 'A' && !node.href) {
|
|
node.href = '#';
|
|
}
|
|
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.DOM.addEventListener(node, eventName, function() {
|
|
var args;
|
|
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
|
|
return callback.apply(null, [node].concat(__slice.call(args), [context]));
|
|
}));
|
|
}
|
|
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.DOM.addEventListener(node, 'keydown', function() {
|
|
var args;
|
|
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
|
|
if (Batman.DOM.events.isEnter(args[0])) {
|
|
return Batman.DOM._keyCapturingNode = node;
|
|
}
|
|
});
|
|
Batman.DOM.addEventListener(node, 'keyup', function() {
|
|
var args;
|
|
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
|
|
if (Batman.DOM.events.isEnter(args[0])) {
|
|
if (Batman.DOM._keyCapturingNode === node) {
|
|
Batman.DOM.preventDefault(args[0]);
|
|
callback.apply(null, [node].concat(__slice.call(args), [context]));
|
|
}
|
|
return Batman.DOM._keyCapturingNode = null;
|
|
}
|
|
});
|
|
} else {
|
|
Batman.DOM.addEventListener(node, 'submit', function() {
|
|
var args;
|
|
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
|
|
Batman.DOM.preventDefault(args[0]);
|
|
return callback.apply(null, [node].concat(__slice.call(args), [context]));
|
|
});
|
|
}
|
|
return node;
|
|
},
|
|
other: function(node, eventName, callback, context) {
|
|
return Batman.DOM.addEventListener(node, eventName, function() {
|
|
var args;
|
|
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
|
|
return callback.apply(null, [node].concat(__slice.call(args), [context]));
|
|
});
|
|
}
|
|
};
|
|
|
|
Batman.DOM.eventIsAllowed = function(eventName, event) {
|
|
var delegate, _ref, _ref1;
|
|
if (delegate = (_ref = Batman.currentApp) != null ? (_ref1 = _ref.shouldAllowEvent) != null ? _ref1[eventName] : void 0 : void 0) {
|
|
if (delegate(event) === false) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
};
|
|
|
|
}).call(this);
|
|
|
|
(function() {
|
|
|
|
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, ObjectFunctions, getAccessorObject, promiseWrapper, wrapSingleAccessor,
|
|
__slice = [].slice,
|
|
__hasProp = {}.hasOwnProperty,
|
|
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
|
|
|
|
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(defaultAccessor) {
|
|
return {
|
|
get: function(key) {
|
|
var asyncDeliver, existingValue, newValue, _base, _base1, _ref, _ref1,
|
|
_this = this;
|
|
if ((existingValue = defaultAccessor.get.apply(this, arguments)) != null) {
|
|
return existingValue;
|
|
}
|
|
asyncDeliver = false;
|
|
newValue = void 0;
|
|
if ((_ref = (_base = this._batman).promises) == null) {
|
|
_base.promises = {};
|
|
}
|
|
if ((_ref1 = (_base1 = this._batman.promises)[key]) == null) {
|
|
_base1[key] = (function() {
|
|
var deliver, returnValue;
|
|
deliver = function(err, result) {
|
|
if (asyncDeliver) {
|
|
_this.set(key, result);
|
|
}
|
|
return newValue = result;
|
|
};
|
|
returnValue = fetcher.call(_this, deliver, key);
|
|
if (newValue == null) {
|
|
newValue = returnValue;
|
|
}
|
|
return true;
|
|
})();
|
|
}
|
|
asyncDeliver = true;
|
|
return newValue;
|
|
},
|
|
cache: true
|
|
};
|
|
};
|
|
};
|
|
|
|
wrapSingleAccessor = function(core, wrapper) {
|
|
var k, v;
|
|
wrapper = (typeof wrapper === "function" ? wrapper(core) : void 0) || wrapper;
|
|
for (k in core) {
|
|
v = core[k];
|
|
if (!(k in wrapper)) {
|
|
wrapper[k] = v;
|
|
}
|
|
}
|
|
return wrapper;
|
|
};
|
|
|
|
ObjectFunctions = {
|
|
_defineAccessor: function() {
|
|
var accessor, key, keys, _base, _i, _j, _len, _ref, _results;
|
|
keys = 2 <= arguments.length ? __slice.call(arguments, 0, _i = arguments.length - 1) : (_i = 0, []), accessor = arguments[_i++];
|
|
if (!(accessor != null)) {
|
|
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;
|
|
}
|
|
},
|
|
_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;
|
|
}
|
|
},
|
|
_resetPromises: function() {
|
|
var key;
|
|
if (this._batman.promises == null) {
|
|
return;
|
|
}
|
|
for (key in this._batman.promises) {
|
|
this._resetPromise(key);
|
|
}
|
|
},
|
|
_resetPromise: function(key) {
|
|
this.unset(key);
|
|
this.property(key).cached = false;
|
|
delete this._batman.promises[key];
|
|
}
|
|
};
|
|
|
|
BatmanObject = (function(_super) {
|
|
var counter;
|
|
|
|
__extends(BatmanObject, _super);
|
|
|
|
Batman.initializeObject(BatmanObject);
|
|
|
|
Batman.initializeObject(BatmanObject.prototype);
|
|
|
|
Batman.mixin(BatmanObject.prototype, ObjectFunctions, Batman.EventEmitter, Batman.Observable);
|
|
|
|
Batman.mixin(BatmanObject, ObjectFunctions, Batman.EventEmitter, Batman.Observable);
|
|
|
|
BatmanObject.classMixin = function() {
|
|
return Batman.mixin.apply(Batman, [this].concat(__slice.call(arguments)));
|
|
};
|
|
|
|
BatmanObject.mixin = function() {
|
|
return this.classMixin.apply(this.prototype, arguments);
|
|
};
|
|
|
|
BatmanObject.prototype.mixin = BatmanObject.classMixin;
|
|
|
|
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;
|
|
|
|
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();
|
|
});
|
|
|
|
function BatmanObject() {
|
|
var mixins;
|
|
mixins = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
|
|
this._batman = new Batman._Batman(this);
|
|
this.mixin.apply(this, mixins);
|
|
}
|
|
|
|
counter = 0;
|
|
|
|
BatmanObject.prototype._batmanID = function() {
|
|
var _base, _ref;
|
|
this._batman.check(this);
|
|
if ((_ref = (_base = this._batman).id) == null) {
|
|
_base.id = counter++;
|
|
}
|
|
return this._batman.id;
|
|
};
|
|
|
|
BatmanObject.prototype.hashKey = function() {
|
|
var key;
|
|
if (typeof this.isEqual === 'function') {
|
|
return;
|
|
}
|
|
this.hashKey = function() {
|
|
return key;
|
|
};
|
|
return key = "<Batman.Object " + (this._batmanID()) + ">";
|
|
};
|
|
|
|
BatmanObject.prototype.toJSON = function() {
|
|
var key, obj, value;
|
|
obj = {};
|
|
for (key in this) {
|
|
if (!__hasProp.call(this, key)) continue;
|
|
value = this[key];
|
|
if (key !== "_batman" && key !== "hashKey" && key !== "_batmanID") {
|
|
obj[key] = (value != null ? value.toJSON : void 0) ? value.toJSON() : value;
|
|
}
|
|
}
|
|
return obj;
|
|
};
|
|
|
|
return BatmanObject;
|
|
|
|
})(Object);
|
|
|
|
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;
|
|
this.prevent('parsed');
|
|
this.prevent('rendered');
|
|
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.allowAndFire('parsed');
|
|
return this.allowAndFire('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.DOM.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.DOM.onParseExit(node)) != null) {
|
|
_ref1.forEach(function(callback) {
|
|
return callback();
|
|
});
|
|
}
|
|
Batman.DOM.forgetParseExit(node);
|
|
if (this.node === node) {
|
|
return;
|
|
}
|
|
if (sibling) {
|
|
return sibling;
|
|
}
|
|
nextParent = node;
|
|
while (nextParent = nextParent.parentNode) {
|
|
parentSibling = nextParent.nextSibling;
|
|
if ((_ref2 = Batman.DOM.onParseExit(nextParent)) != null) {
|
|
_ref2.forEach(function(callback) {
|
|
return callback();
|
|
});
|
|
}
|
|
Batman.DOM.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.DOM.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.canSetImplicitly = 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.lastKeyContext = null;
|
|
|
|
SelectBinding.prototype.dataChange = function(newValue) {
|
|
var child, matches, valueToChild, _i, _len, _name, _ref,
|
|
_this = this;
|
|
this.lastKeyContext || (this.lastKeyContext = this.get('keyContext'));
|
|
if (this.lastKeyContext !== this.get('keyContext')) {
|
|
this.canSetImplicitly = true;
|
|
this.lastKeyContext = this.get('keyContext');
|
|
}
|
|
if (newValue != null ? newValue.forEach : void 0) {
|
|
valueToChild = {};
|
|
_ref = this.node.children;
|
|
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 (!(newValue != null) && this.canSetImplicitly) {
|
|
if (this.node.value) {
|
|
this.canSetImplicitly = false;
|
|
this.set('unfilteredValue', this.node.value);
|
|
}
|
|
} else {
|
|
this.canSetImplicitly = false;
|
|
Batman.DOM.valueForNode(this.node, newValue, this.escapeValue);
|
|
}
|
|
}
|
|
this.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.DOM.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.DOM.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,
|
|
_this = this;
|
|
EventBinding.__super__.constructor.apply(this, arguments);
|
|
callback = function() {
|
|
var _ref;
|
|
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));
|
|
keyContext = Batman.RenderContext.deProxy(keyContext);
|
|
if (keyContext != null) {
|
|
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.DOM.insertBefore(sourceNode.parentNode, this.startNode, previousSiblingNode);
|
|
Batman.DOM.insertBefore(sourceNode.parentNode, this.endNode, previousSiblingNode);
|
|
this.parentRenderer.prevent('rendered');
|
|
Batman.DOM.onParseExit(sourceNode.parentNode, function() {
|
|
Batman.DOM.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();
|
|
if (newItems != null) {
|
|
for (index = _i = 0, _len = newItems.length; _i < _len; index = ++_i) {
|
|
newItem = newItems[index];
|
|
nodeAtIndex = parentNode.childNodes[startIndex + index];
|
|
if ((nodeAtIndex != null) && this._itemForNode(nodeAtIndex) === newItem) {
|
|
unseenNodeMap.unset(newItem);
|
|
continue;
|
|
} else {
|
|
node = (existingNode = this.nodeMap.get(newItem)) ? (unseenNodeMap.unset(newItem), existingNode) : this._newNodeForItem(newItem);
|
|
Batman.DOM.insertBefore(this.parentNode(), node, nodeAtIndex);
|
|
}
|
|
}
|
|
}
|
|
unseenNodeMap.forEach(function(item, node) {
|
|
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.DOM.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.DOM.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);
|
|
|
|
StorageAdapter.NotAllowedError = (function(_super1) {
|
|
|
|
__extends(NotAllowedError, _super1);
|
|
|
|
NotAllowedError.prototype.name = "NotAllowedError";
|
|
|
|
function NotAllowedError(message) {
|
|
NotAllowedError.__super__.constructor.call(this, message || "Storage operation denied access to the operation!");
|
|
}
|
|
|
|
return NotAllowedError;
|
|
|
|
})(StorageAdapter.StorageError);
|
|
|
|
StorageAdapter.NotAcceptableError = (function(_super1) {
|
|
|
|
__extends(NotAcceptableError, _super1);
|
|
|
|
NotAcceptableError.prototype.name = "NotAcceptableError";
|
|
|
|
function NotAcceptableError(message) {
|
|
NotAcceptableError.__super__.constructor.call(this, message || "Storage operation permitted but the request was malformed!");
|
|
}
|
|
|
|
return NotAcceptableError;
|
|
|
|
})(StorageAdapter.StorageError);
|
|
|
|
StorageAdapter.UnprocessableRecordError = (function(_super1) {
|
|
|
|
__extends(UnprocessableRecordError, _super1);
|
|
|
|
UnprocessableRecordError.prototype.name = "UnprocessableRecordError";
|
|
|
|
function UnprocessableRecordError(message) {
|
|
UnprocessableRecordError.__super__.constructor.call(this, message || "Storage adapter could not process the record!");
|
|
}
|
|
|
|
return UnprocessableRecordError;
|
|
|
|
})(StorageAdapter.StorageError);
|
|
|
|
StorageAdapter.InternalStorageError = (function(_super1) {
|
|
|
|
__extends(InternalStorageError, _super1);
|
|
|
|
InternalStorageError.prototype.name = "InternalStorageError";
|
|
|
|
function InternalStorageError(message) {
|
|
InternalStorageError.__super__.constructor.call(this, message || "An error occured during the storage operation!");
|
|
}
|
|
|
|
return InternalStorageError;
|
|
|
|
})(StorageAdapter.StorageError);
|
|
|
|
StorageAdapter.NotImplementedError = (function(_super1) {
|
|
|
|
__extends(NotImplementedError, _super1);
|
|
|
|
NotImplementedError.prototype.name = "NotImplementedError";
|
|
|
|
function NotImplementedError(message) {
|
|
NotImplementedError.__super__.constructor.call(this, message || "This operation is not implemented by the storage adpater!");
|
|
}
|
|
|
|
return NotImplementedError;
|
|
|
|
})(StorageAdapter.StorageError);
|
|
|
|
function StorageAdapter(model) {
|
|
var constructor;
|
|
StorageAdapter.__super__.constructor.call(this, {
|
|
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);
|
|
};
|
|
this.runBeforeFilter(key, env, function(env) {
|
|
return this[key](env, next);
|
|
});
|
|
return void 0;
|
|
};
|
|
|
|
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.CommunicationError = (function(_super1) {
|
|
|
|
__extends(CommunicationError, _super1);
|
|
|
|
CommunicationError.prototype.name = 'CommunicationError';
|
|
|
|
function CommunicationError(message) {
|
|
CommunicationError.__super__.constructor.call(this, message || "A communication error has occurred!");
|
|
}
|
|
|
|
return CommunicationError;
|
|
|
|
})(RestStorage.StorageError);
|
|
|
|
RestStorage.JSONContentType = 'application/json';
|
|
|
|
RestStorage.PostBodyContentType = 'application/x-www-form-urlencoded';
|
|
|
|
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, context) {
|
|
if (context == null) {
|
|
context = object;
|
|
}
|
|
if (typeof object[key] === 'function') {
|
|
return object[key].call(context, 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._addUrlAffixes = function(url, subject, env) {
|
|
var prefix, segments;
|
|
segments = [url, this.urlSuffix(subject, env)];
|
|
if (url.charAt(0) !== '/') {
|
|
prefix = this.urlPrefix(subject, env);
|
|
if (prefix.charAt(prefix.length - 1) !== '/') {
|
|
segments.unshift('/');
|
|
}
|
|
segments.unshift(prefix);
|
|
}
|
|
return segments.join('');
|
|
};
|
|
|
|
RestStorage.prototype.urlPrefix = function(object, env) {
|
|
return this._execWithOptions(object, 'urlPrefix', env.options) || '';
|
|
};
|
|
|
|
RestStorage.prototype.urlSuffix = function(object, env) {
|
|
return this._execWithOptions(object, 'urlSuffix', env.options) || '';
|
|
};
|
|
|
|
RestStorage.prototype.urlForRecord = function(record, env) {
|
|
var id, url, _ref;
|
|
if ((_ref = env.options) != null ? _ref.recordUrl : void 0) {
|
|
url = this._execWithOptions(env.options, 'recordUrl', env.options, record);
|
|
} else if (record.url) {
|
|
url = this._execWithOptions(record, 'url', env.options);
|
|
} else {
|
|
url = record.constructor.url ? this._execWithOptions(record.constructor, 'url', env.options) : this._defaultCollectionUrl(record.constructor);
|
|
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 + "!");
|
|
}
|
|
}
|
|
}
|
|
return this._addUrlAffixes(this._addParams(url, env.options), record, env);
|
|
};
|
|
|
|
RestStorage.prototype.urlForCollection = function(model, env) {
|
|
var url, _ref;
|
|
url = ((_ref = env.options) != null ? _ref.collectionUrl : void 0) ? this._execWithOptions(env.options, 'collectionUrl', env.options, env.options.urlContext) : model.url ? this._execWithOptions(model, 'url', env.options) : this._defaultCollectionUrl(model, env.options);
|
|
return this._addUrlAffixes(this._addParams(url, env.options), model, env);
|
|
};
|
|
|
|
RestStorage.prototype.request = function(env, next) {
|
|
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);
|
|
}
|
|
|
|
RestStorage.prototype.after('all', function(env, next) {
|
|
if (env.error) {
|
|
env.error = this._errorFor(env.error, env);
|
|
}
|
|
return next();
|
|
});
|
|
|
|
RestStorage._statusCodeErrors = {
|
|
'0': RestStorage.CommunicationError,
|
|
'403': RestStorage.NotAllowedError,
|
|
'404': RestStorage.NotFoundError,
|
|
'406': RestStorage.NotAcceptableError,
|
|
'422': RestStorage.UnprocessableRecordError,
|
|
'500': RestStorage.InternalStorageError,
|
|
'501': RestStorage.NotImplementedError
|
|
};
|
|
|
|
RestStorage.prototype._errorFor = function(error, env) {
|
|
var errorClass, request;
|
|
if (error instanceof Error || !(error.request != null)) {
|
|
return error;
|
|
}
|
|
if (errorClass = this.constructor._statusCodeErrors[error.request.status]) {
|
|
request = error.request;
|
|
error = new errorClass;
|
|
error.request = request;
|
|
error.env = env;
|
|
}
|
|
return error;
|
|
};
|
|
|
|
return RestStorage;
|
|
|
|
}).call(this, Batman.StorageAdapter);
|
|
|
|
}).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.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 error, inferredParams, path, route, _ref, _ref1;
|
|
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();
|
|
}
|
|
error = {
|
|
type: '404',
|
|
isPrevented: false,
|
|
preventDefault: function() {
|
|
return this.isPrevented = true;
|
|
}
|
|
};
|
|
if ((_ref1 = Batman.currentApp) != null) {
|
|
_ref1.fire('error', error);
|
|
}
|
|
if (error.isPrevented) {
|
|
return params;
|
|
}
|
|
if (params !== '/404') {
|
|
return Batman.redirect('/404');
|
|
}
|
|
}
|
|
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 + "$");
|
|
regexps.namedOrSplat.lastIndex = 0;
|
|
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; },
|
|
__slice = [].slice,
|
|
__indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
|
|
|
|
Batman.Controller = (function(_super) {
|
|
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 = []);
|
|
return filters.push(options);
|
|
};
|
|
|
|
Controller.afterFilter = function() {
|
|
var filters, options, _base;
|
|
Batman.initializeObject(this);
|
|
options = _optionsFromFilterArguments.apply(null, arguments);
|
|
filters = (_base = this._batman).afterFilters || (_base.afterFilters = []);
|
|
return filters.push(options);
|
|
};
|
|
|
|
Controller.afterFilter(function(params) {
|
|
if (this.autoScrollToHash && (params['#'] != null)) {
|
|
return this.scrollToHash(params['#']);
|
|
}
|
|
});
|
|
|
|
Controller.catchError = function() {
|
|
var currentHandlers, error, errors, handlers, options, _base, _i, _j, _len, _results;
|
|
errors = 2 <= arguments.length ? __slice.call(arguments, 0, _i = arguments.length - 1) : (_i = 0, []), options = arguments[_i++];
|
|
Batman.initializeObject(this);
|
|
(_base = this._batman).errorHandlers || (_base.errorHandlers = new Batman.SimpleHash);
|
|
handlers = Batman.typeOf(options["with"]) === 'Array' ? options["with"] : [options["with"]];
|
|
_results = [];
|
|
for (_j = 0, _len = errors.length; _j < _len; _j++) {
|
|
error = errors[_j];
|
|
currentHandlers = this._batman.errorHandlers.get(error) || [];
|
|
_results.push(this._batman.errorHandlers.set(error, currentHandlers.concat(handlers)));
|
|
}
|
|
return _results;
|
|
};
|
|
|
|
Controller.prototype.errorHandler = function(callback) {
|
|
var errorFrame, _ref,
|
|
_this = this;
|
|
errorFrame = (_ref = this._actionFrames) != null ? _ref[this._actionFrames.length - 1] : void 0;
|
|
return function(err, result, env) {
|
|
if (err) {
|
|
if (errorFrame != null ? errorFrame.error : void 0) {
|
|
return;
|
|
}
|
|
if (errorFrame != null) {
|
|
errorFrame.error = err;
|
|
}
|
|
if (!_this.handleError(err)) {
|
|
throw err;
|
|
}
|
|
} else {
|
|
return typeof callback === "function" ? callback(result, env) : void 0;
|
|
}
|
|
};
|
|
};
|
|
|
|
Controller.prototype.handleError = function(error) {
|
|
var handled, _ref,
|
|
_this = this;
|
|
handled = false;
|
|
if ((_ref = this.constructor._batman.getAll('errorHandlers')) != null) {
|
|
_ref.forEach(function(hash) {
|
|
return hash.forEach(function(key, value) {
|
|
var handler, _i, _len, _results;
|
|
if (error instanceof key) {
|
|
handled = true;
|
|
_results = [];
|
|
for (_i = 0, _len = value.length; _i < _len; _i++) {
|
|
handler = value[_i];
|
|
_results.push(handler.call(_this, error));
|
|
}
|
|
return _results;
|
|
}
|
|
});
|
|
});
|
|
}
|
|
return handled;
|
|
};
|
|
|
|
function Controller() {
|
|
this.redirect = __bind(this.redirect, this);
|
|
|
|
this.handleError = __bind(this.handleError, this);
|
|
|
|
this.errorHandler = __bind(this.errorHandler, this);
|
|
Controller.__super__.constructor.apply(this, arguments);
|
|
this._resetActionFrames();
|
|
}
|
|
|
|
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;
|
|
if (!_this._afterFilterRedirect) {
|
|
_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');
|
|
if (!this._afterFilterRedirect) {
|
|
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 block, options, _i, _len, _ref;
|
|
if (filters = (_ref = this.constructor._batman) != null ? _ref.get(filters) : void 0) {
|
|
for (_i = 0, _len = filters.length; _i < _len; _i++) {
|
|
options = filters[_i];
|
|
if (options.only && __indexOf.call(options.only, action) < 0) {
|
|
continue;
|
|
}
|
|
if (options.except && __indexOf.call(options.except, action) >= 0) {
|
|
continue;
|
|
}
|
|
if (this._afterFilterRedirect) {
|
|
return;
|
|
}
|
|
block = options.block;
|
|
if (typeof block === 'function') {
|
|
block.call(this, params);
|
|
} else {
|
|
if (typeof this[block] === "function") {
|
|
this[block](params);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
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;
|
|
};
|
|
|
|
Batman.Set._applySetAccessors(SetProxy);
|
|
|
|
_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);
|
|
}
|
|
|
|
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() {
|
|
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.storageKey = null;
|
|
|
|
Model.primaryKey = 'id';
|
|
|
|
Model.persist = function() {
|
|
var mechanism, options;
|
|
mechanism = arguments[0], options = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
|
|
Batman.initializeObject(this.prototype);
|
|
mechanism = mechanism.isStorageAdapter ? mechanism : new mechanism(this);
|
|
if (options.length > 0) {
|
|
Batman.mixin.apply(Batman, [mechanism].concat(__slice.call(options)));
|
|
}
|
|
this.prototype._batman.storage = mechanism;
|
|
return mechanism;
|
|
};
|
|
|
|
Model.storageAdapter = function() {
|
|
Batman.initializeObject(this.prototype);
|
|
return this.prototype._batman.storage;
|
|
};
|
|
|
|
Model.encode = function() {
|
|
var encoder, encoderForKey, encoderOrLastKey, key, keys, _base, _i, _j, _len;
|
|
keys = 2 <= arguments.length ? __slice.call(arguments, 0, _i = arguments.length - 1) : (_i = 0, []), encoderOrLastKey = arguments[_i++];
|
|
Batman.initializeObject(this.prototype);
|
|
(_base = this.prototype._batman).encoders || (_base.encoders = new Batman.SimpleHash);
|
|
encoder = {};
|
|
switch (Batman.typeOf(encoderOrLastKey)) {
|
|
case 'String':
|
|
keys.push(encoderOrLastKey);
|
|
break;
|
|
case 'Function':
|
|
encoder.encode = encoderOrLastKey;
|
|
break;
|
|
default:
|
|
encoder = encoderOrLastKey;
|
|
}
|
|
for (_j = 0, _len = keys.length; _j < _len; _j++) {
|
|
key = keys[_j];
|
|
encoderForKey = Batman.extend({
|
|
as: key
|
|
}, this.defaultEncoder, encoder);
|
|
this.prototype._batman.encoders.set(key, encoderForKey);
|
|
}
|
|
};
|
|
|
|
Model.defaultEncoder = {
|
|
encode: function(x) {
|
|
return x;
|
|
},
|
|
decode: function(x) {
|
|
return x;
|
|
}
|
|
};
|
|
|
|
Model.observeAndFire('primaryKey', function(newPrimaryKey, oldPrimaryKey) {
|
|
this.encode(oldPrimaryKey, {
|
|
encode: false,
|
|
decode: false
|
|
});
|
|
return this.encode(newPrimaryKey, {
|
|
encode: false,
|
|
decode: this.defaultEncoder.decode
|
|
});
|
|
});
|
|
|
|
Model.validate = function() {
|
|
var keys, matches, optionsOrFunction, validatorClass, validators, _base, _i, _j, _len, _ref, _results;
|
|
keys = 2 <= arguments.length ? __slice.call(arguments, 0, _i = arguments.length - 1) : (_i = 0, []), optionsOrFunction = arguments[_i++];
|
|
Batman.initializeObject(this.prototype);
|
|
validators = (_base = this.prototype._batman).validators || (_base.validators = []);
|
|
if (typeof optionsOrFunction === 'function') {
|
|
return validators.push({
|
|
keys: keys,
|
|
callback: optionsOrFunction
|
|
});
|
|
} else {
|
|
_ref = Batman.Validators;
|
|
_results = [];
|
|
for (_j = 0, _len = _ref.length; _j < _len; _j++) {
|
|
validatorClass = _ref[_j];
|
|
if ((matches = validatorClass.matches(optionsOrFunction))) {
|
|
_results.push(validators.push({
|
|
keys: keys,
|
|
validator: new validatorClass(matches)
|
|
}));
|
|
} else {
|
|
_results.push(void 0);
|
|
}
|
|
}
|
|
return _results;
|
|
}
|
|
};
|
|
|
|
Model.classAccessor('resourceName', {
|
|
get: function() {
|
|
if (this.resourceName != null) {
|
|
return this.resourceName;
|
|
} else {
|
|
if (Batman.config.minificationErrors) {
|
|
Batman.developer.error("Please define " + (Batman.functionName(this)) + ".resourceName in order for your model to be minification safe.");
|
|
}
|
|
return Batman.helpers.underscore(Batman.functionName(this));
|
|
}
|
|
}
|
|
});
|
|
|
|
Model.classAccessor('all', {
|
|
get: function() {
|
|
this._batman.check(this);
|
|
if (this.prototype.hasStorage() && !this._batman.allLoadTriggered) {
|
|
this.load();
|
|
this._batman.allLoadTriggered = true;
|
|
}
|
|
return this.get('loaded');
|
|
},
|
|
set: function(k, v) {
|
|
return this.set('loaded', v);
|
|
}
|
|
});
|
|
|
|
Model.classAccessor('loaded', {
|
|
get: function() {
|
|
return this._loaded || (this._loaded = new Batman.Set);
|
|
},
|
|
set: function(k, v) {
|
|
return this._loaded = v;
|
|
}
|
|
});
|
|
|
|
Model.classAccessor('first', function() {
|
|
return this.get('all').toArray()[0];
|
|
});
|
|
|
|
Model.classAccessor('last', function() {
|
|
var x;
|
|
x = this.get('all').toArray();
|
|
return x[x.length - 1];
|
|
});
|
|
|
|
Model.clear = function() {
|
|
var result, _ref;
|
|
Batman.initializeObject(this);
|
|
result = this.get('loaded').clear();
|
|
if ((_ref = this._batman.get('associations')) != null) {
|
|
_ref.reset();
|
|
}
|
|
this._resetPromises();
|
|
return result;
|
|
};
|
|
|
|
Model.find = function(id, callback) {
|
|
return this.findWithOptions(id, void 0, callback);
|
|
};
|
|
|
|
Model.findWithOptions = function(id, options, callback) {
|
|
var record;
|
|
if (options == null) {
|
|
options = {};
|
|
}
|
|
Batman.developer.assert(callback, "Must call find with a callback!");
|
|
record = new this();
|
|
record._withoutDirtyTracking(function() {
|
|
return this.set('id', id);
|
|
});
|
|
record.loadWithOptions(options, callback);
|
|
return record;
|
|
};
|
|
|
|
Model.load = function(options, callback) {
|
|
var _ref;
|
|
if ((_ref = typeof options) === 'function' || _ref === 'undefined') {
|
|
callback = options;
|
|
options = {};
|
|
} else {
|
|
options = {
|
|
data: options
|
|
};
|
|
}
|
|
return this.loadWithOptions(options, callback);
|
|
};
|
|
|
|
Model.loadWithOptions = function(options, callback) {
|
|
var _this = this;
|
|
this.fire('loading', options);
|
|
return this._doStorageOperation('readAll', options, function(err, records, env) {
|
|
var mappedRecords, record;
|
|
if (err != null) {
|
|
_this.fire('error', err);
|
|
return typeof callback === "function" ? callback(err, []) : void 0;
|
|
} else {
|
|
mappedRecords = (function() {
|
|
var _i, _len, _results;
|
|
_results = [];
|
|
for (_i = 0, _len = records.length; _i < _len; _i++) {
|
|
record = records[_i];
|
|
_results.push(this._mapIdentity(record));
|
|
}
|
|
return _results;
|
|
}).call(_this);
|
|
_this.fire('loaded', mappedRecords, env);
|
|
return typeof callback === "function" ? callback(err, mappedRecords, env) : void 0;
|
|
}
|
|
});
|
|
};
|
|
|
|
Model.create = function(attrs, callback) {
|
|
var obj, _ref;
|
|
if (!callback) {
|
|
_ref = [{}, attrs], attrs = _ref[0], callback = _ref[1];
|
|
}
|
|
obj = new this(attrs);
|
|
obj.save(callback);
|
|
return obj;
|
|
};
|
|
|
|
Model.findOrCreate = function(attrs, callback) {
|
|
var foundRecord, record;
|
|
record = new this(attrs);
|
|
if (record.isNew()) {
|
|
record.save(callback);
|
|
} else {
|
|
foundRecord = this._mapIdentity(record);
|
|
callback(void 0, foundRecord);
|
|
}
|
|
return record;
|
|
};
|
|
|
|
Model.createFromJSON = function(json) {
|
|
var record;
|
|
record = new this;
|
|
record._withoutDirtyTracking(function() {
|
|
return this.fromJSON(json);
|
|
});
|
|
return this._mapIdentity(record);
|
|
};
|
|
|
|
Model._mapIdentity = function(record) {
|
|
var existing, id, _ref;
|
|
if (typeof (id = record.get('id')) === 'undefined' || id === '') {
|
|
return record;
|
|
} else {
|
|
existing = (_ref = this.get("loaded.indexedBy.id").get(id)) != null ? _ref.toArray()[0] : void 0;
|
|
if (existing) {
|
|
existing._withoutDirtyTracking(function() {
|
|
var _ref1;
|
|
return this.updateAttributes(((_ref1 = record.get('attributes')) != null ? _ref1.toObject() : void 0) || {});
|
|
});
|
|
return existing;
|
|
} else {
|
|
this.get('loaded').add(record);
|
|
return record;
|
|
}
|
|
}
|
|
};
|
|
|
|
Model._doStorageOperation = function(operation, options, callback) {
|
|
var adapter;
|
|
Batman.developer.assert(this.prototype.hasStorage(), "Can't " + operation + " model " + (Batman.functionName(this.constructor)) + " without any storage adapters!");
|
|
adapter = this.prototype._batman.get('storage');
|
|
return adapter.perform(operation, this, options, callback);
|
|
};
|
|
|
|
_ref = ['find', 'load', 'create'];
|
|
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
|
functionName = _ref[_i];
|
|
Model[functionName] = Batman.Property.wrapTrackingPrevention(Model[functionName]);
|
|
}
|
|
|
|
Model.InstanceLifecycleStateMachine = (function(_super1) {
|
|
|
|
__extends(InstanceLifecycleStateMachine, _super1);
|
|
|
|
function InstanceLifecycleStateMachine() {
|
|
return InstanceLifecycleStateMachine.__super__.constructor.apply(this, arguments);
|
|
}
|
|
|
|
InstanceLifecycleStateMachine.transitions({
|
|
load: {
|
|
from: ['dirty', 'clean'],
|
|
to: 'loading'
|
|
},
|
|
create: {
|
|
from: ['dirty', 'clean'],
|
|
to: 'creating'
|
|
},
|
|
save: {
|
|
from: ['dirty', 'clean'],
|
|
to: 'saving'
|
|
},
|
|
destroy: {
|
|
from: ['dirty', 'clean'],
|
|
to: 'destroying'
|
|
},
|
|
failedValidation: {
|
|
from: ['saving', 'creating'],
|
|
to: 'dirty'
|
|
},
|
|
loaded: {
|
|
loading: 'clean'
|
|
},
|
|
created: {
|
|
creating: 'clean'
|
|
},
|
|
saved: {
|
|
saving: 'clean'
|
|
},
|
|
destroyed: {
|
|
destroying: 'destroyed'
|
|
},
|
|
set: {
|
|
from: ['dirty', 'clean'],
|
|
to: 'dirty'
|
|
},
|
|
error: {
|
|
from: ['saving', 'creating', 'loading', 'destroying'],
|
|
to: 'error'
|
|
}
|
|
});
|
|
|
|
return InstanceLifecycleStateMachine;
|
|
|
|
})(Batman.DelegatingStateMachine);
|
|
|
|
function Model(idOrAttributes) {
|
|
if (idOrAttributes == null) {
|
|
idOrAttributes = {};
|
|
}
|
|
this.destroy = __bind(this.destroy, this);
|
|
|
|
this.save = __bind(this.save, this);
|
|
|
|
this.loadWithOptions = __bind(this.loadWithOptions, this);
|
|
|
|
this.load = __bind(this.load, this);
|
|
|
|
Batman.developer.assert(this instanceof Batman.Object, "constructors must be called with new");
|
|
if (Batman.typeOf(idOrAttributes) === 'Object') {
|
|
Model.__super__.constructor.call(this, idOrAttributes);
|
|
} else {
|
|
Model.__super__.constructor.call(this);
|
|
this.set('id', idOrAttributes);
|
|
}
|
|
}
|
|
|
|
Model.accessor('lifecycle', function() {
|
|
return this.lifecycle || (this.lifecycle = new Batman.Model.InstanceLifecycleStateMachine('clean', this));
|
|
});
|
|
|
|
Model.accessor('attributes', function() {
|
|
return this.attributes || (this.attributes = new Batman.Hash);
|
|
});
|
|
|
|
Model.accessor('dirtyKeys', function() {
|
|
return this.dirtyKeys || (this.dirtyKeys = new Batman.Hash);
|
|
});
|
|
|
|
Model.accessor('_dirtiedKeys', function() {
|
|
return this._dirtiedKeys || (this._dirtiedKeys = new Batman.SimpleSet);
|
|
});
|
|
|
|
Model.accessor('errors', function() {
|
|
return this.errors || (this.errors = new Batman.ErrorsSet);
|
|
});
|
|
|
|
Model.accessor('isNew', function() {
|
|
return this.isNew();
|
|
});
|
|
|
|
Model.accessor('isDirty', function() {
|
|
return this.isDirty();
|
|
});
|
|
|
|
Model.accessor(Model.defaultAccessor = {
|
|
get: function(k) {
|
|
return Batman.getPath(this, ['attributes', k]);
|
|
},
|
|
set: function(k, v) {
|
|
if (this._willSet(k)) {
|
|
return this.get('attributes').set(k, v);
|
|
} else {
|
|
return this.get(k);
|
|
}
|
|
},
|
|
unset: function(k) {
|
|
return this.get('attributes').unset(k);
|
|
}
|
|
});
|
|
|
|
Model.wrapAccessor('id', function(core) {
|
|
return {
|
|
get: function() {
|
|
var primaryKey;
|
|
primaryKey = this.constructor.primaryKey;
|
|
if (primaryKey === 'id') {
|
|
return core.get.apply(this, arguments);
|
|
} else {
|
|
return this.get(primaryKey);
|
|
}
|
|
},
|
|
set: function(key, value) {
|
|
var parsedValue, primaryKey;
|
|
if ((typeof value === "string") && (value.match(/[^0-9]/) === null) && (("" + (parsedValue = parseInt(value, 10))) === value)) {
|
|
value = parsedValue;
|
|
}
|
|
primaryKey = this.constructor.primaryKey;
|
|
if (primaryKey === 'id') {
|
|
this._willSet(key);
|
|
return core.set.apply(this, arguments);
|
|
} else {
|
|
return this.set(primaryKey, value);
|
|
}
|
|
}
|
|
};
|
|
});
|
|
|
|
Model.prototype.isNew = function() {
|
|
return typeof this.get('id') === 'undefined';
|
|
};
|
|
|
|
Model.prototype.isDirty = function() {
|
|
return this.get('lifecycle.state') === 'dirty';
|
|
};
|
|
|
|
Model.prototype.updateAttributes = function(attrs) {
|
|
this.mixin(attrs);
|
|
return this;
|
|
};
|
|
|
|
Model.prototype.toString = function() {
|
|
return "" + (this.constructor.get('resourceName')) + ": " + (this.get('id'));
|
|
};
|
|
|
|
Model.prototype.toParam = function() {
|
|
return this.get('id');
|
|
};
|
|
|
|
Model.prototype.toJSON = function() {
|
|
var encoders, obj,
|
|
_this = this;
|
|
obj = {};
|
|
encoders = this._batman.get('encoders');
|
|
if (!(!encoders || encoders.isEmpty())) {
|
|
encoders.forEach(function(key, encoder) {
|
|
var encodedVal, val;
|
|
if (encoder.encode) {
|
|
val = _this.get(key);
|
|
if (typeof val !== 'undefined') {
|
|
encodedVal = encoder.encode(val, key, obj, _this);
|
|
if (typeof encodedVal !== 'undefined') {
|
|
return obj[encoder.as] = encodedVal;
|
|
}
|
|
}
|
|
}
|
|
});
|
|
}
|
|
return obj;
|
|
};
|
|
|
|
Model.prototype.fromJSON = function(data) {
|
|
var encoders, key, obj, value,
|
|
_this = this;
|
|
obj = {};
|
|
encoders = this._batman.get('encoders');
|
|
if (!encoders || encoders.isEmpty() || !encoders.some(function(key, encoder) {
|
|
return encoder.decode != null;
|
|
})) {
|
|
for (key in data) {
|
|
value = data[key];
|
|
obj[key] = value;
|
|
}
|
|
} else {
|
|
encoders.forEach(function(key, encoder) {
|
|
if (encoder.decode && typeof data[encoder.as] !== 'undefined') {
|
|
return obj[key] = encoder.decode(data[encoder.as], encoder.as, data, obj, _this);
|
|
}
|
|
});
|
|
}
|
|
if (this.constructor.primaryKey !== 'id') {
|
|
obj.id = data[this.constructor.primaryKey];
|
|
}
|
|
Batman.developer["do"](function() {
|
|
if ((!encoders) || encoders.length <= 1) {
|
|
return Batman.developer.warn("Warning: Model " + (Batman.functionName(_this.constructor)) + " has suspiciously few decoders!");
|
|
}
|
|
});
|
|
return this.mixin(obj);
|
|
};
|
|
|
|
Model.prototype.hasStorage = function() {
|
|
return this._batman.get('storage') != null;
|
|
};
|
|
|
|
Model.prototype.load = function(options, callback) {
|
|
var _ref1;
|
|
if (!callback) {
|
|
_ref1 = [{}, options], options = _ref1[0], callback = _ref1[1];
|
|
} else {
|
|
options = {
|
|
data: options
|
|
};
|
|
}
|
|
return this.loadWithOptions(options, callback);
|
|
};
|
|
|
|
Model.prototype.loadWithOptions = function(options, callback) {
|
|
var callbackQueue, hasOptions, _ref1,
|
|
_this = this;
|
|
hasOptions = Object.keys(options).length !== 0;
|
|
if ((_ref1 = this.get('lifecycle.state')) === 'destroying' || _ref1 === 'destroyed') {
|
|
if (typeof callback === "function") {
|
|
callback(new Error("Can't load a destroyed record!"));
|
|
}
|
|
return;
|
|
}
|
|
if (this.get('lifecycle').load()) {
|
|
callbackQueue = [];
|
|
if (callback != null) {
|
|
callbackQueue.push(callback);
|
|
}
|
|
if (!hasOptions) {
|
|
this._currentLoad = callbackQueue;
|
|
}
|
|
return this._doStorageOperation('read', options, function(err, record, env) {
|
|
var _j, _len1;
|
|
if (!err) {
|
|
_this.get('lifecycle').loaded();
|
|
record = _this.constructor._mapIdentity(record);
|
|
} else {
|
|
_this.get('lifecycle').error();
|
|
}
|
|
if (!hasOptions) {
|
|
_this._currentLoad = null;
|
|
}
|
|
for (_j = 0, _len1 = callbackQueue.length; _j < _len1; _j++) {
|
|
callback = callbackQueue[_j];
|
|
callback(err, record, env);
|
|
}
|
|
});
|
|
} else {
|
|
if (this.get('lifecycle.state') === 'loading' && !hasOptions) {
|
|
if (callback != null) {
|
|
return this._currentLoad.push(callback);
|
|
}
|
|
} else {
|
|
return typeof callback === "function" ? callback(new Batman.StateMachine.InvalidTransitionError("Can't load while in state " + (this.get('lifecycle.state')))) : void 0;
|
|
}
|
|
}
|
|
};
|
|
|
|
Model.prototype.save = function(options, callback) {
|
|
var endState, isNew, startState, storageOperation, _ref1, _ref2,
|
|
_this = this;
|
|
if (!callback) {
|
|
_ref1 = [{}, options], options = _ref1[0], callback = _ref1[1];
|
|
}
|
|
isNew = this.isNew();
|
|
_ref2 = isNew ? ['create', 'create', 'created'] : ['save', 'update', 'saved'], startState = _ref2[0], storageOperation = _ref2[1], endState = _ref2[2];
|
|
if (this.get('lifecycle').startTransition(startState)) {
|
|
return this.validate(function(error, errors) {
|
|
var associations;
|
|
if (error || errors.length) {
|
|
_this.get('lifecycle').failedValidation();
|
|
return typeof callback === "function" ? callback(error || errors, _this) : void 0;
|
|
}
|
|
associations = _this.constructor._batman.get('associations');
|
|
_this._withoutDirtyTracking(function() {
|
|
var _ref3,
|
|
_this = this;
|
|
return associations != null ? (_ref3 = associations.getByType('belongsTo')) != null ? _ref3.forEach(function(association, label) {
|
|
return association.apply(_this);
|
|
}) : void 0 : void 0;
|
|
});
|
|
return _this._doStorageOperation(storageOperation, {
|
|
data: options
|
|
}, function(err, record, env) {
|
|
if (!err) {
|
|
_this.get('dirtyKeys').clear();
|
|
_this.get('_dirtiedKeys').clear();
|
|
if (associations) {
|
|
record._withoutDirtyTracking(function() {
|
|
var _ref3, _ref4;
|
|
if ((_ref3 = associations.getByType('hasOne')) != null) {
|
|
_ref3.forEach(function(association, label) {
|
|
return association.apply(err, record);
|
|
});
|
|
}
|
|
return (_ref4 = associations.getByType('hasMany')) != null ? _ref4.forEach(function(association, label) {
|
|
return association.apply(err, record);
|
|
}) : void 0;
|
|
});
|
|
}
|
|
record = _this.constructor._mapIdentity(record);
|
|
_this.get('lifecycle').startTransition(endState);
|
|
} else {
|
|
if (err instanceof Batman.ErrorsSet) {
|
|
_this.get('lifecycle').failedValidation();
|
|
} else {
|
|
_this.get('lifecycle').error();
|
|
}
|
|
}
|
|
return typeof callback === "function" ? callback(err, record || _this, env) : void 0;
|
|
});
|
|
});
|
|
} else {
|
|
return typeof callback === "function" ? callback(new Batman.StateMachine.InvalidTransitionError("Can't save while in state " + (this.get('lifecycle.state')))) : void 0;
|
|
}
|
|
};
|
|
|
|
Model.prototype.destroy = function(options, callback) {
|
|
var _ref1,
|
|
_this = this;
|
|
if (!callback) {
|
|
_ref1 = [{}, options], options = _ref1[0], callback = _ref1[1];
|
|
}
|
|
if (this.get('lifecycle').destroy()) {
|
|
return this._doStorageOperation('destroy', {
|
|
data: options
|
|
}, function(err, record, env) {
|
|
if (!err) {
|
|
_this.constructor.get('loaded').remove(_this);
|
|
_this.get('lifecycle').destroyed();
|
|
} else {
|
|
_this.get('lifecycle').error();
|
|
}
|
|
return typeof callback === "function" ? callback(err, record, env) : void 0;
|
|
});
|
|
} else {
|
|
return typeof callback === "function" ? callback(new Batman.StateMachine.InvalidTransitionError("Can't destroy while in state " + (this.get('lifecycle.state')))) : void 0;
|
|
}
|
|
};
|
|
|
|
Model.prototype.validate = function(callback) {
|
|
var args, count, errors, finishedValidation, key, validator, validators, _j, _k, _len1, _len2, _ref1;
|
|
errors = this.get('errors');
|
|
errors.clear();
|
|
validators = this._batman.get('validators') || [];
|
|
if (!validators || validators.length === 0) {
|
|
if (typeof callback === "function") {
|
|
callback(void 0, errors);
|
|
}
|
|
return true;
|
|
}
|
|
count = validators.reduce((function(acc, validator) {
|
|
return acc + validator.keys.length;
|
|
}), 0);
|
|
finishedValidation = function() {
|
|
if (--count === 0) {
|
|
return typeof callback === "function" ? callback(void 0, errors) : void 0;
|
|
}
|
|
};
|
|
for (_j = 0, _len1 = validators.length; _j < _len1; _j++) {
|
|
validator = validators[_j];
|
|
_ref1 = validator.keys;
|
|
for (_k = 0, _len2 = _ref1.length; _k < _len2; _k++) {
|
|
key = _ref1[_k];
|
|
args = [errors, this, key, finishedValidation];
|
|
try {
|
|
if (validator.validator) {
|
|
validator.validator.validateEach.apply(validator.validator, args);
|
|
} else {
|
|
validator.callback.apply(validator, args);
|
|
}
|
|
} catch (e) {
|
|
if (typeof callback === "function") {
|
|
callback(e, errors);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
Model.prototype.associationProxy = function(association) {
|
|
var proxies, _base, _name;
|
|
Batman.initializeObject(this);
|
|
proxies = (_base = this._batman).associationProxies || (_base.associationProxies = {});
|
|
proxies[_name = association.label] || (proxies[_name] = new association.proxyClass(association, this));
|
|
return proxies[association.label];
|
|
};
|
|
|
|
Model.prototype._willSet = function(key) {
|
|
if (this._pauseDirtyTracking) {
|
|
return true;
|
|
}
|
|
if (this.get('lifecycle').startTransition('set')) {
|
|
if (!this.get('_dirtiedKeys').has(key)) {
|
|
this.set("dirtyKeys." + key, this.get(key));
|
|
this.get('_dirtiedKeys').add(key);
|
|
}
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
};
|
|
|
|
Model.prototype._doStorageOperation = function(operation, options, callback) {
|
|
var adapter,
|
|
_this = this;
|
|
Batman.developer.assert(this.hasStorage(), "Can't " + operation + " model " + (Batman.functionName(this.constructor)) + " without any storage adapters!");
|
|
adapter = this._batman.get('storage');
|
|
return adapter.perform(operation, this, options, function() {
|
|
return callback.apply(null, arguments);
|
|
});
|
|
};
|
|
|
|
Model.prototype._withoutDirtyTracking = function(block) {
|
|
var result;
|
|
this._pauseDirtyTracking = true;
|
|
result = block.call(this);
|
|
this._pauseDirtyTracking = false;
|
|
return result;
|
|
};
|
|
|
|
_ref1 = ['load', 'save', 'validate', 'destroy'];
|
|
for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
|
|
functionName = _ref1[_j];
|
|
Model.prototype[functionName] = Batman.Property.wrapTrackingPrevention(Model.prototype[functionName]);
|
|
}
|
|
|
|
return Model;
|
|
|
|
}).call(this, Batman.Object);
|
|
|
|
}).call(this);
|
|
|
|
(function() {
|
|
var k, _fn, _i, _len, _ref,
|
|
_this = this;
|
|
|
|
_ref = Batman.AssociationCurator.availableAssociations;
|
|
_fn = function(k) {
|
|
return Batman.Model[k] = function(label, scope) {
|
|
var collection, _base;
|
|
Batman.initializeObject(this);
|
|
collection = (_base = this._batman).associations || (_base.associations = new Batman.AssociationCurator(this));
|
|
return collection.add(new Batman["" + (Batman.helpers.capitalize(k)) + "Association"](this, label, scope));
|
|
};
|
|
};
|
|
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
|
k = _ref[_i];
|
|
_fn(k);
|
|
}
|
|
|
|
}).call(this);
|
|
|
|
(function() {
|
|
var __hasProp = {}.hasOwnProperty,
|
|
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
|
|
|
|
Batman.Proxy = (function(_super) {
|
|
|
|
__extends(Proxy, _super);
|
|
|
|
Proxy.prototype.isProxy = true;
|
|
|
|
function Proxy(target) {
|
|
Proxy.__super__.constructor.call(this);
|
|
if (target != null) {
|
|
this.set('target', target);
|
|
}
|
|
}
|
|
|
|
Proxy.accessor('target', Batman.Property.defaultAccessor);
|
|
|
|
Proxy.accessor({
|
|
get: function(key) {
|
|
var _ref;
|
|
return (_ref = this.get('target')) != null ? _ref.get(key) : void 0;
|
|
},
|
|
set: function(key, value) {
|
|
var _ref;
|
|
return (_ref = this.get('target')) != null ? _ref.set(key, value) : void 0;
|
|
},
|
|
unset: function(key) {
|
|
var _ref;
|
|
return (_ref = this.get('target')) != null ? _ref.unset(key) : void 0;
|
|
}
|
|
});
|
|
|
|
return Proxy;
|
|
|
|
})(Batman.Object);
|
|
|
|
}).call(this);
|
|
|
|
(function() {
|
|
var __hasProp = {}.hasOwnProperty,
|
|
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
|
|
|
|
Batman.AssociationProxy = (function(_super) {
|
|
|
|
__extends(AssociationProxy, _super);
|
|
|
|
AssociationProxy.prototype.loaded = false;
|
|
|
|
function AssociationProxy(association, model) {
|
|
this.association = association;
|
|
this.model = model;
|
|
AssociationProxy.__super__.constructor.call(this);
|
|
}
|
|
|
|
AssociationProxy.prototype.toJSON = function() {
|
|
var target;
|
|
target = this.get('target');
|
|
if (target != null) {
|
|
return this.get('target').toJSON();
|
|
}
|
|
};
|
|
|
|
AssociationProxy.prototype.load = function(callback) {
|
|
var _this = this;
|
|
this.fetch(function(err, proxiedRecord) {
|
|
if (!err) {
|
|
_this._setTarget(proxiedRecord);
|
|
}
|
|
return typeof callback === "function" ? callback(err, proxiedRecord) : void 0;
|
|
});
|
|
return this.get('target');
|
|
};
|
|
|
|
AssociationProxy.prototype.loadFromLocal = function() {
|
|
var target;
|
|
if (!this._canLoad()) {
|
|
return;
|
|
}
|
|
if (target = this.fetchFromLocal()) {
|
|
this._setTarget(target);
|
|
}
|
|
return target;
|
|
};
|
|
|
|
AssociationProxy.prototype.fetch = function(callback) {
|
|
var record;
|
|
if (!this._canLoad()) {
|
|
return callback(void 0, void 0);
|
|
}
|
|
record = this.fetchFromLocal();
|
|
if (record) {
|
|
return callback(void 0, record);
|
|
} else {
|
|
return this.fetchFromRemote(callback);
|
|
}
|
|
};
|
|
|
|
AssociationProxy.accessor('loaded', Batman.Property.defaultAccessor);
|
|
|
|
AssociationProxy.accessor('target', {
|
|
get: function() {
|
|
return this.fetchFromLocal();
|
|
},
|
|
set: function(_, v) {
|
|
return v;
|
|
}
|
|
});
|
|
|
|
AssociationProxy.prototype._canLoad = function() {
|
|
return (this.get('foreignValue') || this.get('primaryValue')) != null;
|
|
};
|
|
|
|
AssociationProxy.prototype._setTarget = function(target) {
|
|
this.set('target', target);
|
|
this.set('loaded', true);
|
|
return this.fire('loaded', target);
|
|
};
|
|
|
|
return AssociationProxy;
|
|
|
|
})(Batman.Proxy);
|
|
|
|
}).call(this);
|
|
|
|
(function() {
|
|
var __hasProp = {}.hasOwnProperty,
|
|
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
|
|
|
|
Batman.HasOneProxy = (function(_super) {
|
|
|
|
__extends(HasOneProxy, _super);
|
|
|
|
function HasOneProxy() {
|
|
return HasOneProxy.__super__.constructor.apply(this, arguments);
|
|
}
|
|
|
|
HasOneProxy.accessor('primaryValue', function() {
|
|
return this.model.get(this.association.primaryKey);
|
|
});
|
|
|
|
HasOneProxy.prototype.fetchFromLocal = function() {
|
|
return this.association.setIndex().get(this.get('primaryValue'));
|
|
};
|
|
|
|
HasOneProxy.prototype.fetchFromRemote = function(callback) {
|
|
var loadOptions,
|
|
_this = this;
|
|
loadOptions = {
|
|
data: {}
|
|
};
|
|
loadOptions.data[this.association.foreignKey] = this.get('primaryValue');
|
|
if (this.association.options.url) {
|
|
loadOptions.collectionUrl = this.association.options.url;
|
|
loadOptions.urlContext = this.model;
|
|
}
|
|
return this.association.getRelatedModel().loadWithOptions(loadOptions, function(error, loadedRecords) {
|
|
if (error) {
|
|
throw error;
|
|
}
|
|
if (!loadedRecords || loadedRecords.length <= 0) {
|
|
return callback(new Error("Couldn't find related record!"), void 0);
|
|
} else {
|
|
return callback(void 0, loadedRecords[0]);
|
|
}
|
|
});
|
|
};
|
|
|
|
return HasOneProxy;
|
|
|
|
})(Batman.AssociationProxy);
|
|
|
|
}).call(this);
|
|
|
|
(function() {
|
|
var __hasProp = {}.hasOwnProperty,
|
|
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
|
|
|
|
Batman.BelongsToProxy = (function(_super) {
|
|
|
|
__extends(BelongsToProxy, _super);
|
|
|
|
function BelongsToProxy() {
|
|
return BelongsToProxy.__super__.constructor.apply(this, arguments);
|
|
}
|
|
|
|
BelongsToProxy.accessor('foreignValue', function() {
|
|
return this.model.get(this.association.foreignKey);
|
|
});
|
|
|
|
BelongsToProxy.prototype.fetchFromLocal = function() {
|
|
return this.association.setIndex().get(this.get('foreignValue'));
|
|
};
|
|
|
|
BelongsToProxy.prototype.fetchFromRemote = function(callback) {
|
|
var loadOptions,
|
|
_this = this;
|
|
loadOptions = {};
|
|
if (this.association.options.url) {
|
|
loadOptions.recordUrl = this.association.options.url;
|
|
}
|
|
return this.association.getRelatedModel().findWithOptions(this.get('foreignValue'), loadOptions, function(error, loadedRecord) {
|
|
if (error) {
|
|
throw error;
|
|
}
|
|
return callback(void 0, loadedRecord);
|
|
});
|
|
};
|
|
|
|
return BelongsToProxy;
|
|
|
|
})(Batman.AssociationProxy);
|
|
|
|
}).call(this);
|
|
|
|
(function() {
|
|
var __hasProp = {}.hasOwnProperty,
|
|
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
|
|
|
|
Batman.PolymorphicBelongsToProxy = (function(_super) {
|
|
|
|
__extends(PolymorphicBelongsToProxy, _super);
|
|
|
|
function PolymorphicBelongsToProxy() {
|
|
return PolymorphicBelongsToProxy.__super__.constructor.apply(this, arguments);
|
|
}
|
|
|
|
PolymorphicBelongsToProxy.accessor('foreignTypeValue', function() {
|
|
return this.model.get(this.association.foreignTypeKey);
|
|
});
|
|
|
|
PolymorphicBelongsToProxy.prototype.fetchFromLocal = function() {
|
|
return this.association.setIndexForType(this.get('foreignTypeValue')).get(this.get('foreignValue'));
|
|
};
|
|
|
|
PolymorphicBelongsToProxy.prototype.fetchFromRemote = function(callback) {
|
|
var loadOptions,
|
|
_this = this;
|
|
loadOptions = {};
|
|
if (this.association.options.url) {
|
|
loadOptions.recordUrl = this.association.options.url;
|
|
}
|
|
return this.association.getRelatedModelForType(this.get('foreignTypeValue')).findWithOptions(this.get('foreignValue'), loadOptions, function(error, loadedRecord) {
|
|
if (error) {
|
|
throw error;
|
|
}
|
|
return callback(void 0, loadedRecord);
|
|
});
|
|
};
|
|
|
|
return PolymorphicBelongsToProxy;
|
|
|
|
})(Batman.BelongsToProxy);
|
|
|
|
}).call(this);
|
|
|
|
(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() {
|
|
|
|
Batman.mixins = new Batman.Object;
|
|
|
|
}).call(this);
|
|
|
|
(function() {
|
|
|
|
Batman.URI = (function() {
|
|
/*
|
|
# URI parsing
|
|
*/
|
|
|
|
var attributes, childKeyMatchers, decodeQueryComponent, encodeComponent, encodeQueryComponent, keyVal, nameParser, normalizeParams, plus, queryFromParams, r20, strictParser;
|
|
|
|
strictParser = /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/;
|
|
|
|
attributes = ["source", "protocol", "authority", "userInfo", "user", "password", "hostname", "port", "relative", "path", "directory", "file", "query", "hash"];
|
|
|
|
function URI(str) {
|
|
var i, matches;
|
|
matches = strictParser.exec(str);
|
|
i = 14;
|
|
while (i--) {
|
|
this[attributes[i]] = matches[i] || '';
|
|
}
|
|
this.queryParams = this.constructor.paramsFromQuery(this.query);
|
|
delete this.authority;
|
|
delete this.userInfo;
|
|
delete this.relative;
|
|
delete this.directory;
|
|
delete this.file;
|
|
delete this.query;
|
|
}
|
|
|
|
URI.prototype.queryString = function() {
|
|
return this.constructor.queryFromParams(this.queryParams);
|
|
};
|
|
|
|
URI.prototype.toString = function() {
|
|
return [this.protocol ? "" + this.protocol + ":" : void 0, this.authority() ? "//" : void 0, this.authority(), this.relative()].join("");
|
|
};
|
|
|
|
URI.prototype.userInfo = function() {
|
|
return [this.user, this.password ? ":" + this.password : void 0].join("");
|
|
};
|
|
|
|
URI.prototype.authority = function() {
|
|
return [this.userInfo(), this.user || this.password ? "@" : void 0, this.hostname, this.port ? ":" + this.port : void 0].join("");
|
|
};
|
|
|
|
URI.prototype.relative = function() {
|
|
var query;
|
|
query = this.queryString();
|
|
return [this.path, query ? "?" + query : void 0, this.hash ? "#" + this.hash : void 0].join("");
|
|
};
|
|
|
|
URI.prototype.directory = function() {
|
|
var splitPath;
|
|
splitPath = this.path.split('/');
|
|
if (splitPath.length > 1) {
|
|
return splitPath.slice(0, splitPath.length - 1).join('/') + "/";
|
|
} else {
|
|
return "";
|
|
}
|
|
};
|
|
|
|
URI.prototype.file = function() {
|
|
var splitPath;
|
|
splitPath = this.path.split("/");
|
|
return splitPath[splitPath.length - 1];
|
|
};
|
|
|
|
/*
|
|
# query parsing
|
|
*/
|
|
|
|
|
|
URI.paramsFromQuery = function(query) {
|
|
var matches, params, segment, _i, _len, _ref;
|
|
params = {};
|
|
_ref = query.split('&');
|
|
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
|
segment = _ref[_i];
|
|
if (matches = segment.match(keyVal)) {
|
|
normalizeParams(params, decodeQueryComponent(matches[1]), decodeQueryComponent(matches[2]));
|
|
} else {
|
|
normalizeParams(params, decodeQueryComponent(segment), null);
|
|
}
|
|
}
|
|
return params;
|
|
};
|
|
|
|
URI.decodeQueryComponent = decodeQueryComponent = function(str) {
|
|
return decodeURIComponent(str.replace(plus, '%20'));
|
|
};
|
|
|
|
nameParser = /^[\[\]]*([^\[\]]+)\]*(.*)/;
|
|
|
|
childKeyMatchers = [/^\[\]\[([^\[\]]+)\]$/, /^\[\](.+)$/];
|
|
|
|
plus = /\+/g;
|
|
|
|
r20 = /%20/g;
|
|
|
|
keyVal = /^([^=]*)=(.*)/;
|
|
|
|
normalizeParams = function(params, name, v) {
|
|
var after, childKey, k, last, matches, _ref, _ref1, _ref2;
|
|
if (matches = name.match(nameParser)) {
|
|
k = matches[1];
|
|
after = matches[2];
|
|
} else {
|
|
return;
|
|
}
|
|
if (after === '') {
|
|
params[k] = v;
|
|
} else if (after === '[]') {
|
|
if ((_ref = params[k]) == null) {
|
|
params[k] = [];
|
|
}
|
|
if (Batman.typeOf(params[k]) !== 'Array') {
|
|
throw new Error("expected Array (got " + (Batman.typeOf(params[k])) + ") for param \"" + k + "\"");
|
|
}
|
|
params[k].push(v);
|
|
} else if (matches = after.match(childKeyMatchers[0]) || after.match(childKeyMatchers[1])) {
|
|
childKey = matches[1];
|
|
if ((_ref1 = params[k]) == null) {
|
|
params[k] = [];
|
|
}
|
|
if (Batman.typeOf(params[k]) !== 'Array') {
|
|
throw new Error("expected Array (got " + (Batman.typeOf(params[k])) + ") for param \"" + k + "\"");
|
|
}
|
|
last = params[k][params[k].length - 1];
|
|
if (Batman.typeOf(last) === 'Object' && !(childKey in last)) {
|
|
normalizeParams(last, childKey, v);
|
|
} else {
|
|
params[k].push(normalizeParams({}, childKey, v));
|
|
}
|
|
} else {
|
|
if ((_ref2 = params[k]) == null) {
|
|
params[k] = {};
|
|
}
|
|
if (Batman.typeOf(params[k]) !== 'Object') {
|
|
throw new Error("expected Object (got " + (Batman.typeOf(params[k])) + ") for param \"" + k + "\"");
|
|
}
|
|
params[k] = normalizeParams(params[k], after, v);
|
|
}
|
|
return params;
|
|
};
|
|
|
|
/*
|
|
# query building
|
|
*/
|
|
|
|
|
|
URI.queryFromParams = queryFromParams = function(value, prefix) {
|
|
var arrayResults, k, v, valueType;
|
|
if (value == null) {
|
|
return prefix;
|
|
}
|
|
valueType = Batman.typeOf(value);
|
|
if (!((prefix != null) || valueType === 'Object')) {
|
|
throw new Error("value must be an Object");
|
|
}
|
|
switch (valueType) {
|
|
case 'Array':
|
|
return ((function() {
|
|
var _i, _len;
|
|
arrayResults = [];
|
|
if (value.length === 0) {
|
|
arrayResults.push(queryFromParams(null, "" + prefix + "[]"));
|
|
} else {
|
|
for (_i = 0, _len = value.length; _i < _len; _i++) {
|
|
v = value[_i];
|
|
arrayResults.push(queryFromParams(v, "" + prefix + "[]"));
|
|
}
|
|
}
|
|
return arrayResults;
|
|
})()).join("&");
|
|
case 'Object':
|
|
return ((function() {
|
|
var _results;
|
|
_results = [];
|
|
for (k in value) {
|
|
v = value[k];
|
|
_results.push(queryFromParams(v, prefix ? "" + prefix + "[" + (encodeQueryComponent(k)) + "]" : encodeQueryComponent(k)));
|
|
}
|
|
return _results;
|
|
})()).join("&");
|
|
default:
|
|
if (prefix != null) {
|
|
return "" + prefix + "=" + (encodeQueryComponent(value));
|
|
} else {
|
|
return encodeQueryComponent(value);
|
|
}
|
|
}
|
|
};
|
|
|
|
URI.encodeComponent = encodeComponent = function(str) {
|
|
if (str != null) {
|
|
return encodeURIComponent(str);
|
|
} else {
|
|
return '';
|
|
}
|
|
};
|
|
|
|
URI.encodeQueryComponent = encodeQueryComponent = function(str) {
|
|
return encodeComponent(str).replace(r20, '+');
|
|
};
|
|
|
|
return URI;
|
|
|
|
})();
|
|
|
|
}).call(this);
|
|
|
|
(function() {
|
|
var __hasProp = {}.hasOwnProperty,
|
|
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
|
|
|
|
Batman.Request = (function(_super) {
|
|
var dataHasFileUploads;
|
|
|
|
__extends(Request, _super);
|
|
|
|
Request.objectToFormData = function(data) {
|
|
var formData, key, pairForList, val, _i, _len, _ref, _ref1;
|
|
pairForList = function(key, object, first) {
|
|
var k, list, v;
|
|
if (first == null) {
|
|
first = false;
|
|
}
|
|
if (object instanceof Batman.container.File) {
|
|
return [[key, object]];
|
|
}
|
|
return list = (function() {
|
|
switch (Batman.typeOf(object)) {
|
|
case 'Object':
|
|
list = (function() {
|
|
var _results;
|
|
_results = [];
|
|
for (k in object) {
|
|
v = object[k];
|
|
_results.push(pairForList((first ? k : "" + key + "[" + k + "]"), v));
|
|
}
|
|
return _results;
|
|
})();
|
|
return list.reduce(function(acc, list) {
|
|
return acc.concat(list);
|
|
}, []);
|
|
case 'Array':
|
|
return object.reduce(function(acc, element) {
|
|
return acc.concat(pairForList("" + key + "[]", element));
|
|
}, []);
|
|
default:
|
|
return [[key, object != null ? object : ""]];
|
|
}
|
|
})();
|
|
};
|
|
formData = new Batman.container.FormData();
|
|
_ref = pairForList("", data, true);
|
|
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
|
_ref1 = _ref[_i], key = _ref1[0], val = _ref1[1];
|
|
formData.append(key, val);
|
|
}
|
|
return formData;
|
|
};
|
|
|
|
Request.dataHasFileUploads = dataHasFileUploads = function(data) {
|
|
var k, type, v, _i, _len;
|
|
if ((typeof File !== "undefined" && File !== null) && data instanceof File) {
|
|
return true;
|
|
}
|
|
type = Batman.typeOf(data);
|
|
switch (type) {
|
|
case 'Object':
|
|
for (k in data) {
|
|
v = data[k];
|
|
if (dataHasFileUploads(v)) {
|
|
return true;
|
|
}
|
|
}
|
|
break;
|
|
case 'Array':
|
|
for (_i = 0, _len = data.length; _i < _len; _i++) {
|
|
v = data[_i];
|
|
if (dataHasFileUploads(v)) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
};
|
|
|
|
Request.wrapAccessor('method', function(core) {
|
|
return {
|
|
set: function(k, val) {
|
|
return core.set.call(this, k, val != null ? typeof val.toUpperCase === "function" ? val.toUpperCase() : void 0 : void 0);
|
|
}
|
|
};
|
|
});
|
|
|
|
Request.prototype.method = 'GET';
|
|
|
|
Request.prototype.hasFileUploads = function() {
|
|
return dataHasFileUploads(this.data);
|
|
};
|
|
|
|
Request.prototype.contentType = 'application/x-www-form-urlencoded';
|
|
|
|
Request.prototype.autosend = true;
|
|
|
|
function Request(options) {
|
|
var handler, handlers, k, _ref;
|
|
handlers = {};
|
|
for (k in options) {
|
|
handler = options[k];
|
|
if (!(k === 'success' || k === 'error' || k === 'loading' || k === 'loaded')) {
|
|
continue;
|
|
}
|
|
handlers[k] = handler;
|
|
delete options[k];
|
|
}
|
|
Request.__super__.constructor.call(this, options);
|
|
for (k in handlers) {
|
|
handler = handlers[k];
|
|
this.on(k, handler);
|
|
}
|
|
if (((_ref = this.get('url')) != null ? _ref.length : void 0) > 0) {
|
|
if (this.autosend) {
|
|
this.send();
|
|
}
|
|
} else {
|
|
this.observe('url', function(url) {
|
|
if (url != null) {
|
|
return this.send();
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
Request.prototype.send = function() {
|
|
return Batman.developer.error("Please source a dependency file for a request implementation");
|
|
};
|
|
|
|
return Request;
|
|
|
|
})(Batman.Object);
|
|
|
|
}).call(this);
|
|
|
|
(function() {
|
|
var __hasProp = {}.hasOwnProperty,
|
|
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
|
|
__slice = [].slice;
|
|
|
|
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.find = function(block) {
|
|
var item, _i, _len, _ref;
|
|
this.base.registerAsMutableSource();
|
|
_ref = this.get('_storage');
|
|
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
|
item = _ref[_i];
|
|
if (block(item)) {
|
|
return item;
|
|
}
|
|
}
|
|
};
|
|
|
|
SetSort.prototype.merge = function(other) {
|
|
this.base.registerAsMutableSource();
|
|
return (function(func, args, ctor) {
|
|
ctor.prototype = func.prototype;
|
|
var child = new ctor, result = func.apply(child, args), t = typeof result;
|
|
return t == "object" || t == "function" ? result || child : child;
|
|
})(Batman.Set, this._storage, function(){}).merge(other).sortedBy(this.key, this.order);
|
|
};
|
|
|
|
SetSort.prototype.compare = function(a, b) {
|
|
if (a === b) {
|
|
return 0;
|
|
}
|
|
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().loadWithOptions(this._getLoadOptions(), function(err, records) {
|
|
if (!err) {
|
|
_this.markAsLoaded();
|
|
}
|
|
return callback(err, _this);
|
|
});
|
|
};
|
|
|
|
AssociationSet.prototype._getLoadOptions = function() {
|
|
var loadOptions;
|
|
loadOptions = {
|
|
data: {}
|
|
};
|
|
loadOptions.data[this.association.foreignKey] = this.foreignKeyValue;
|
|
if (this.association.options.url) {
|
|
loadOptions.collectionUrl = this.association.options.url;
|
|
loadOptions.urlContext = this.association.parentSetIndex().get(this.foreignKeyValue);
|
|
}
|
|
return loadOptions;
|
|
};
|
|
|
|
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 = {
|
|
data: {}
|
|
};
|
|
loadOptions.data[this.association.foreignKey] = this.foreignKeyValue;
|
|
loadOptions.data[this.association.foreignTypeKey] = this.foreignTypeKeyValue;
|
|
if (this.association.options.url) {
|
|
loadOptions.collectionUrl = this.association.options.url;
|
|
loadOptions.urlContext = this.association.parentSetIndex().get(this.foreignKeyValue);
|
|
}
|
|
return loadOptions;
|
|
};
|
|
|
|
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) {
|
|
return this.association.setForKey(key);
|
|
};
|
|
|
|
AssociationSetIndex.prototype.forEach = function(iterator, ctx) {
|
|
var _this = this;
|
|
return this.association.proxies.forEach(function(record, set) {
|
|
var key;
|
|
key = _this.association.indexValueForRecord(record);
|
|
if (set.get('length') > 0) {
|
|
return iterator.call(ctx, key, set, _this);
|
|
}
|
|
});
|
|
};
|
|
|
|
AssociationSetIndex.prototype.toArray = function() {
|
|
var results;
|
|
results = [];
|
|
this.forEach(function(key) {
|
|
return results.push(key);
|
|
});
|
|
return results;
|
|
};
|
|
|
|
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() {
|
|
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) {
|
|
this.cachedPath = this.app.get('dispatcher').dispatch(params);
|
|
if (this._lastRedirect) {
|
|
this.cachedPath = this._lastRedirect;
|
|
}
|
|
return this.cachedPath;
|
|
};
|
|
|
|
Navigator.prototype.push = function(params) {
|
|
var path, pathFromParams, _base;
|
|
pathFromParams = typeof (_base = this.app.get('dispatcher')).pathFromParams === "function" ? _base.pathFromParams(params) : void 0;
|
|
if (pathFromParams) {
|
|
this._lastRedirect = pathFromParams;
|
|
}
|
|
path = this.dispatch(params);
|
|
if (!this._lastRedirect || this._lastRedirect === path) {
|
|
this.pushState(null, '', path);
|
|
}
|
|
return path;
|
|
};
|
|
|
|
Navigator.prototype.replace = function(params) {
|
|
var path, pathFromParams, _base;
|
|
pathFromParams = typeof (_base = this.app.get('dispatcher')).pathFromParams === "function" ? _base.pathFromParams(params) : void 0;
|
|
if (pathFromParams) {
|
|
this._lastRedirect = pathFromParams;
|
|
}
|
|
path = this.dispatch(params);
|
|
if (!this._lastRedirect || this._lastRedirect === path) {
|
|
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.DOM.addEventListener(window, 'popstate', this.handleCurrentLocation);
|
|
};
|
|
|
|
PushStateNavigator.prototype.stopWatching = function() {
|
|
return Batman.DOM.removeEventListener(window, 'popstate', this.handleCurrentLocation);
|
|
};
|
|
|
|
PushStateNavigator.prototype.pushState = function(stateObject, title, path) {
|
|
if (path !== this.pathFromLocation(window.location)) {
|
|
return window.history.pushState(stateObject, title, this.linkTo(path));
|
|
}
|
|
};
|
|
|
|
PushStateNavigator.prototype.replaceState = function(stateObject, title, path) {
|
|
if (path !== this.pathFromLocation(window.location)) {
|
|
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.DOM.addEventListener(window, 'hashchange', this.handleCurrentLocation);
|
|
};
|
|
HashbangNavigator.prototype.stopWatching = function() {
|
|
return Batman.DOM.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 = Batman.helpers.underscore(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;
|
|
|
|
App.shouldAllowEvent = {};
|
|
|
|
_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);
|
|
|
|
PluralAssociation.prototype.proxyClass = Batman.AssociationSet;
|
|
|
|
PluralAssociation.prototype.isSingular = false;
|
|
|
|
function PluralAssociation() {
|
|
PluralAssociation.__super__.constructor.apply(this, arguments);
|
|
this._resetSetHashes();
|
|
}
|
|
|
|
PluralAssociation.prototype.setForRecord = function(record) {
|
|
var childModelSetIndex, indexValue,
|
|
_this = this;
|
|
indexValue = this.indexValueForRecord(record);
|
|
childModelSetIndex = this.setIndex();
|
|
Batman.Property.withoutTracking(function() {
|
|
return _this._setsByRecord.getOrSet(record, function() {
|
|
var existingValueSet, newSet;
|
|
if (indexValue != null) {
|
|
existingValueSet = _this._setsByValue.get(indexValue);
|
|
if (existingValueSet != null) {
|
|
return existingValueSet;
|
|
}
|
|
}
|
|
newSet = new _this.proxyClass(indexValue, _this);
|
|
if (indexValue != null) {
|
|
_this._setsByValue.set(indexValue, newSet);
|
|
}
|
|
return newSet;
|
|
});
|
|
});
|
|
if (indexValue != null) {
|
|
return childModelSetIndex.get(indexValue);
|
|
} else {
|
|
return this._setsByRecord.get(record);
|
|
}
|
|
};
|
|
|
|
PluralAssociation.prototype.setForKey = Batman.Property.wrapTrackingPrevention(function(indexValue) {
|
|
var foundSet,
|
|
_this = this;
|
|
foundSet = void 0;
|
|
this._setsByRecord.forEach(function(record, set) {
|
|
if (foundSet != null) {
|
|
return;
|
|
}
|
|
if (_this.indexValueForRecord(record) === indexValue) {
|
|
return foundSet = set;
|
|
}
|
|
});
|
|
if (foundSet != null) {
|
|
foundSet.foreignKeyValue = indexValue;
|
|
return foundSet;
|
|
}
|
|
return this._setsByValue.getOrSet(indexValue, function() {
|
|
return new _this.proxyClass(indexValue, _this);
|
|
});
|
|
});
|
|
|
|
PluralAssociation.prototype.getAccessor = function(self, model, label) {
|
|
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.parentSetIndex = function() {
|
|
this.parentIndex || (this.parentIndex = this.model.get('loaded').indexedByUnique(this.primaryKey));
|
|
return this.parentIndex;
|
|
};
|
|
|
|
PluralAssociation.prototype.setIndex = function() {
|
|
this.index || (this.index = new Batman.AssociationSetIndex(this, this[this.indexRelatedModelOn]));
|
|
return this.index;
|
|
};
|
|
|
|
PluralAssociation.prototype.indexValueForRecord = function(record) {
|
|
return record.get(this.primaryKey);
|
|
};
|
|
|
|
PluralAssociation.prototype.reset = function() {
|
|
PluralAssociation.__super__.reset.apply(this, arguments);
|
|
return this._resetSetHashes();
|
|
};
|
|
|
|
PluralAssociation.prototype._resetSetHashes = function() {
|
|
this._setsByRecord = new Batman.SimpleHash;
|
|
return this._setsByValue = new Batman.SimpleHash;
|
|
};
|
|
|
|
return PluralAssociation;
|
|
|
|
})(Batman.Association);
|
|
|
|
}).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 parent, proxy, record, recordInAttributes, _ref;
|
|
if (recordInAttributes = self.getFromAttributes(this)) {
|
|
return recordInAttributes;
|
|
}
|
|
if (self.getRelatedModel()) {
|
|
proxy = this.associationProxy(self);
|
|
record = false;
|
|
parent = this;
|
|
if ((_ref = proxy._loadSetter) == null) {
|
|
proxy._loadSetter = proxy.once('loaded', function(child) {
|
|
return parent._withoutDirtyTracking(function() {
|
|
return this.set(self.label, child);
|
|
});
|
|
});
|
|
}
|
|
if (!Batman.Property.withoutTracking(function() {
|
|
return proxy.get('loaded');
|
|
})) {
|
|
if (self.options.autoload) {
|
|
Batman.Property.withoutTracking(function() {
|
|
return proxy.load();
|
|
});
|
|
} else {
|
|
record = proxy.loadFromLocal();
|
|
}
|
|
}
|
|
return record || 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;
|
|
if (!data) {
|
|
return;
|
|
}
|
|
relatedModel = association.getRelatedModel();
|
|
record = relatedModel.createFromJSON(data);
|
|
if (association.options.inverseOf) {
|
|
record.set(association.options.inverseOf, parentRecord);
|
|
}
|
|
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 = relatedModel.createFromJSON(data);
|
|
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 = relatedModel.createFromJSON(data);
|
|
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);
|
|
|
|
Validator.triggers = function() {
|
|
var triggers;
|
|
triggers = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
|
|
if (this._triggers != null) {
|
|
return this._triggers.concat(triggers);
|
|
} else {
|
|
return this._triggers = triggers;
|
|
}
|
|
};
|
|
|
|
Validator.options = function() {
|
|
var options;
|
|
options = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
|
|
if (this._options != null) {
|
|
return this._options.concat(options);
|
|
} else {
|
|
return this._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._options) != null ? _ref.indexOf(key) : void 0)) {
|
|
results[key] = value;
|
|
}
|
|
if (~((_ref1 = this._triggers) != null ? _ref1.indexOf(key) : void 0)) {
|
|
results[key] = value;
|
|
shouldReturn = true;
|
|
}
|
|
}
|
|
if (shouldReturn) {
|
|
return results;
|
|
}
|
|
};
|
|
|
|
function Validator() {
|
|
var mixins, options;
|
|
options = arguments[0], mixins = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
|
|
this.options = options;
|
|
Validator.__super__.constructor.apply(this, mixins);
|
|
}
|
|
|
|
Validator.prototype.validate = function(record) {
|
|
return Batman.developer.error("You must override validate in Batman.Validator subclasses.");
|
|
};
|
|
|
|
Validator.prototype.format = function(key, messageKey, interpolations) {
|
|
return Batman.t("errors.messages." + messageKey, interpolations);
|
|
};
|
|
|
|
Validator.prototype.handleBlank = function(value) {
|
|
if (this.options.allowBlank && !Batman.PresenceValidator.prototype.isPresent(value)) {
|
|
return true;
|
|
}
|
|
};
|
|
|
|
return Validator;
|
|
|
|
})(Batman.Object);
|
|
|
|
}).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",
|
|
greater_than: "must be greater than %{count}",
|
|
greater_than_or_equal_to: "must be greater than or equal to %{count}",
|
|
equal_to: "must be equal to %{count}",
|
|
less_than: "must be less than %{count}",
|
|
less_than_or_equal_to: "must be less than or equal to %{count}",
|
|
not_matching: "is not valid",
|
|
invalid_association: "is not valid"
|
|
}
|
|
}
|
|
});
|
|
|
|
}).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.triggers('regexp', 'pattern');
|
|
|
|
RegExpValidator.options('allowBlank');
|
|
|
|
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 (this.handleBlank(value)) {
|
|
return callback();
|
|
}
|
|
if (!(value != null) || value === '' || !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.triggers('presence');
|
|
|
|
PresenceValidator.prototype.validateEach = function(errors, record, key, callback) {
|
|
var value;
|
|
value = record.get(key);
|
|
if (!this.isPresent(value)) {
|
|
errors.add(key, this.format(key, 'blank'));
|
|
}
|
|
return callback();
|
|
};
|
|
|
|
PresenceValidator.prototype.isPresent = function(value) {
|
|
return (value != null) && value !== '';
|
|
};
|
|
|
|
return PresenceValidator;
|
|
|
|
})(Batman.Validator);
|
|
|
|
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.triggers('numeric', 'greaterThan', 'greaterThanOrEqualTo', 'equalTo', 'lessThan', 'lessThanOrEqualTo');
|
|
|
|
NumericValidator.options('allowBlank');
|
|
|
|
NumericValidator.prototype.validateEach = function(errors, record, key, callback) {
|
|
var options, value;
|
|
options = this.options;
|
|
value = record.get(key);
|
|
if (this.handleBlank(value)) {
|
|
return callback();
|
|
}
|
|
if (!(value != null) || !(this.isNumeric(value) || this.canCoerceToNumeric(value))) {
|
|
errors.add(key, this.format(key, 'not_numeric'));
|
|
} else {
|
|
if (options.greaterThan && value <= options.greaterThan) {
|
|
errors.add(key, this.format(key, 'greater_than', {
|
|
count: options.greaterThan
|
|
}));
|
|
}
|
|
if (options.greaterThanOrEqualTo && value < options.greaterThanOrEqualTo) {
|
|
errors.add(key, this.format(key, 'greater_than_or_equal_to', {
|
|
count: options.greaterThanOrEqualTo
|
|
}));
|
|
}
|
|
if (options.equalTo && value !== options.equalTo) {
|
|
errors.add(key, this.format(key, 'equal_to', {
|
|
count: options.equalTo
|
|
}));
|
|
}
|
|
if (options.lessThan && value >= options.lessThan) {
|
|
errors.add(key, this.format(key, 'less_than', {
|
|
count: options.lessThan
|
|
}));
|
|
}
|
|
if (options.lessThanOrEqualTo && value > options.lessThanOrEqualTo) {
|
|
errors.add(key, this.format(key, 'less_than_or_equal_to', {
|
|
count: options.lessThanOrEqualTo
|
|
}));
|
|
}
|
|
}
|
|
return callback();
|
|
};
|
|
|
|
NumericValidator.prototype.isNumeric = function(value) {
|
|
return !isNaN(parseFloat(value)) && isFinite(value);
|
|
};
|
|
|
|
NumericValidator.prototype.canCoerceToNumeric = function(value) {
|
|
return (value - 0) == value && value.length > 0;
|
|
};
|
|
|
|
return NumericValidator;
|
|
|
|
})(Batman.Validator);
|
|
|
|
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.triggers('minLength', 'maxLength', 'length', 'lengthWithin', 'lengthIn');
|
|
|
|
LengthValidator.options('allowBlank');
|
|
|
|
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;
|
|
options = this.options;
|
|
value = record.get(key);
|
|
if (value !== '' && this.handleBlank(value)) {
|
|
return callback();
|
|
}
|
|
if (value == null) {
|
|
value = [];
|
|
}
|
|
if (options.minLength && value.length < options.minLength) {
|
|
errors.add(key, this.format(key, 'too_short', {
|
|
count: options.minLength
|
|
}));
|
|
}
|
|
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.AssociatedValidator = (function(_super) {
|
|
|
|
__extends(AssociatedValidator, _super);
|
|
|
|
function AssociatedValidator() {
|
|
return AssociatedValidator.__super__.constructor.apply(this, arguments);
|
|
}
|
|
|
|
AssociatedValidator.triggers('associated');
|
|
|
|
AssociatedValidator.prototype.validateEach = function(errors, record, key, callback) {
|
|
var childFinished, count, value,
|
|
_this = this;
|
|
value = record.get(key);
|
|
if (value != null) {
|
|
if (value instanceof Batman.AssociationProxy) {
|
|
value = typeof value.get === "function" ? value.get('target') : void 0;
|
|
}
|
|
count = 1;
|
|
childFinished = function(err, childErrors) {
|
|
if (childErrors.length > 0) {
|
|
errors.add(key, _this.format(key, 'invalid_association'));
|
|
}
|
|
if (--count === 0) {
|
|
return callback();
|
|
}
|
|
};
|
|
if ((value != null ? value.forEach : void 0) != null) {
|
|
value.forEach(function(record) {
|
|
count += 1;
|
|
return record.validate(childFinished);
|
|
});
|
|
} else if ((value != null ? value.validate : void 0) != null) {
|
|
count += 1;
|
|
value.validate(childFinished);
|
|
}
|
|
return childFinished(null, []);
|
|
} else {
|
|
return callback();
|
|
}
|
|
};
|
|
|
|
return AssociatedValidator;
|
|
|
|
})(Batman.Validator);
|
|
|
|
Batman.Validators.push(Batman.AssociatedValidator);
|
|
|
|
}).call(this);
|
|
|
|
(function() {
|
|
var __hasProp = {}.hasOwnProperty,
|
|
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
|
|
|
|
Batman.ControllerActionFrame = (function(_super) {
|
|
|
|
__extends(ControllerActionFrame, _super);
|
|
|
|
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 {
|
|
if (this.node.parentNode != null) {
|
|
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 (value == null) {
|
|
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;
|
|
},
|
|
trim: buntUndefined(function(value, binding) {
|
|
return value.trim();
|
|
}),
|
|
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 != null ? string : '') + (value != null ? value : '');
|
|
},
|
|
append: function(value, string, binding) {
|
|
return (value != null ? value : '') + (string != null ? 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 != null) {
|
|
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);
|
|
|
|
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(Batman.config.viewPrefix, "" + 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 (Batman.config.fetchRemoteViews) {
|
|
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;
|
|
keys = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
|
|
return this.accessor.apply(this, __slice.call(keys).concat([{
|
|
get: function(key) {
|
|
var _ref;
|
|
return (_ref = this.get("argumentBindings." + key)) != null ? _ref.get('filteredValue') : void 0;
|
|
},
|
|
set: function(key, value) {
|
|
var _ref;
|
|
return (_ref = this.get("argumentBindings." + key)) != null ? _ref.set('filteredValue', value) : void 0;
|
|
},
|
|
unset: function(key) {
|
|
var _ref;
|
|
return (_ref = this.get("argumentBindings." + key)) != null ? _ref.unset('filteredValue') : void 0;
|
|
}
|
|
}]));
|
|
};
|
|
|
|
View.prototype.isView = true;
|
|
|
|
View.prototype.cache = true;
|
|
|
|
View.prototype._rendered = false;
|
|
|
|
View.prototype.node = null;
|
|
|
|
View.prototype.event('ready').oneShot = true;
|
|
|
|
View.accessor('argumentBindings', function() {
|
|
var _this = this;
|
|
return new Batman.TerminalAccessible(function(key) {
|
|
var bindingKey, context, keyPath, node, _ref;
|
|
if (!((node = _this.get('node')) && (context = _this.get('context')))) {
|
|
return;
|
|
}
|
|
keyPath = node.getAttribute(("data-view-" + key).toLowerCase());
|
|
if (keyPath == null) {
|
|
return;
|
|
}
|
|
bindingKey = "_argumentBinding" + key;
|
|
if ((_ref = _this[bindingKey]) != null) {
|
|
_ref.die();
|
|
}
|
|
return _this[bindingKey] = new Batman.DOM.ViewArgumentBinding(node, keyPath, context);
|
|
});
|
|
});
|
|
|
|
View.accessor('html', {
|
|
get: function() {
|
|
var source;
|
|
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.DOM.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.DOM.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._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.DOM.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.DOM.removeOrDestroyNode(child));
|
|
}
|
|
}
|
|
return _results;
|
|
});
|
|
|
|
Yield.prototype.append = Yield.queued(function(node) {
|
|
this.currentVersionNodes.push(node);
|
|
return Batman.DOM.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); |