Guest User

Untitled

a guest
Jan 23rd, 2018
83
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 134.45 KB | None | 0 0
  1. + (function() {
  2. + var $block, $event, $eventOneShot, $findName, $get, $mixin, $redirect, $typeOf, $unmixin, Batman, BatmanObject, Binding, RenderContext, Validators, buntUndefined, camelize_rx, capitalize_rx, container, filters, helpers, k, mixins, underscore_rx1, underscore_rx2, _Batman, _fn, _i, _j, _len, _len2, _objectToString, _ref, _ref2, _stateMachine_setState;
  3. + var __slice = Array.prototype.slice, __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) {
  4. + for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
  5. + function ctor() { this.constructor = child; }
  6. + ctor.prototype = parent.prototype;
  7. + child.prototype = new ctor;
  8. + child.__super__ = parent.prototype;
  9. + return child;
  10. + }, __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
  11. + Batman = function() {
  12. + var mixins;
  13. + mixins = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
  14. + return (function(func, args, ctor) {
  15. + ctor.prototype = func.prototype;
  16. + var child = new ctor, result = func.apply(child, args);
  17. + return typeof result === "object" ? result : child;
  18. })(Batman.Object, mixins, function() {});
  19. };
  20. + Batman.typeOf = $typeOf = function(object) {
  21. + return _objectToString.call(object).slice(8, -1);
  22. };
  23. + _objectToString = Object.prototype.toString;
  24. + Batman.mixin = $mixin = function() {
  25. + var hasSet, key, mixin, mixins, to, value, _i, _len;
  26. + to = arguments[0], mixins = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
  27. + hasSet = typeof to.set === 'function';
  28. + for (_i = 0, _len = mixins.length; _i < _len; _i++) {
  29. + mixin = mixins[_i];
  30. + if ($typeOf(mixin) !== 'Object') {
  31. + continue;
  32. }
  33. + for (key in mixin) {
  34. + if (!__hasProp.call(mixin, key)) continue;
  35. + value = mixin[key];
  36. + if (key === 'initialize' || key === 'uninitialize' || key === 'prototype') {
  37. + continue;
  38. }
  39. + if (hasSet) {
  40. + to.set(key, value);
  41. } else {
  42. + to[key] = value;
  43. }
  44. }
  45. + if (typeof mixin.initialize === 'function') {
  46. + mixin.initialize.call(to);
  47. }
  48. }
  49. + return to;
  50. };
  51. + Batman.unmixin = $unmixin = function() {
  52. + var from, key, mixin, mixins, _i, _len;
  53. + from = arguments[0], mixins = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
  54. + for (_i = 0, _len = mixins.length; _i < _len; _i++) {
  55. + mixin = mixins[_i];
  56. + for (key in mixin) {
  57. + if (key === 'initialize' || key === 'uninitialize') {
  58. - continue;
  59. }
  60. + delete from[key];
  61. }
  62. + if (typeof mixin.uninitialize === 'function') {
  63. - mixin.uninitialize.call(from);
  64. }
  65. }
  66. + return from;
  67. };
  68. + Batman._block = $block = function(lengthOrFunction, fn) {
  69. + var argsLength, callbackEater;
  70. + if (fn != null) {
  71. + argsLength = lengthOrFunction;
  72. } else {
  73. + fn = lengthOrFunction;
  74. }
  75. + return callbackEater = function() {
  76. + var args, ctx, f;
  77. + args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
  78. + ctx = this;
  79. + f = function(callback) {
  80. + args.push(callback);
  81. + return fn.apply(ctx, args);
  82. };
  83. + if ((typeof args[args.length - 1] === 'function') || (argsLength && (args.length >= argsLength))) {
  84. + return f(args.pop());
  85. } else {
  86. + return f;
  87. }
  88. };
  89. };
  90. + Batman._findName = $findName = function(f, context) {
  91. + var key, value;
  92. + if (!f.displayName) {
  93. + for (key in context) {
  94. + value = context[key];
  95. + if (value === f) {
  96. + f.displayName = key;
  97. + break;
  98. }
  99. }
  100. }
  101. + return f.displayName;
  102. };
  103. + Batman.Property = (function() {
  104. + Property.defaultAccessor = {
  105. get: function(key) {
  106. + return this[key];
  107. },
  108. set: function(key, val) {
  109. + return this[key] = val;
  110. },
  111. unset: function(key) {
  112. + var x;
  113. + x = this[key];
  114. + delete this[key];
  115. + return x;
  116. }
  117. };
  118. + Property.triggerTracker = null;
  119. + Property.forBaseAndKey = function(base, key) {
  120. + var properties, _base;
  121. + if (base._batman) {
  122. + Batman.initializeObject(base);
  123. + properties = (_base = base._batman).properties || (_base.properties = new Batman.SimpleHash);
  124. + return properties.get(key) || properties.set(key, new this(base, key));
  125. } else {
  126. + return new this(base, key);
  127. }
  128. };
  129. + function Property(base, key) {
  130. + this.base = base;
  131. + this.key = key;
  132. }
  133. + Property.prototype.isProperty = true;
  134. + Property.prototype.accessor = function() {
  135. + var accessors, val, _ref, _ref2;
  136. + accessors = (_ref = this.base._batman) != null ? _ref.get('keyAccessors') : void 0;
  137. + if (accessors && (val = accessors.get(this.key))) {
  138. + return val;
  139. } else {
  140. + return ((_ref2 = this.base._batman) != null ? _ref2.getFirst('defaultAccessor') : void 0) || Batman.Property.defaultAccessor;
  141. }
  142. };
  143. + Property.prototype.registerAsTrigger = function() {
  144. + var tracker;
  145. + if (tracker = Batman.Property.triggerTracker) {
  146. + return tracker.add(this);
  147. }
  148. };
  149. + Property.prototype.getValue = function() {
  150. + var _ref;
  151. + this.registerAsTrigger();
  152. + return (_ref = this.accessor()) != null ? _ref.get.call(this.base, this.key) : void 0;
  153. };
  154. + Property.prototype.setValue = function(val) {
  155. + var _ref;
  156. + return (_ref = this.accessor()) != null ? _ref.set.call(this.base, this.key, val) : void 0;
  157. };
  158. + Property.prototype.unsetValue = function() {
  159. + var _ref;
  160. + return (_ref = this.accessor()) != null ? _ref.unset.call(this.base, this.key) : void 0;
  161. };
  162. + Property.prototype.isEqual = function(other) {
  163. + return this.constructor === other.constructor && this.base === other.base && this.key === other.key;
  164. };
  165. + return Property;
  166. })();
  167. + Batman.ObservableProperty = (function() {
  168. + __extends(ObservableProperty, Batman.Property);
  169. + function ObservableProperty(base, key) {
  170. + ObservableProperty.__super__.constructor.apply(this, arguments);
  171. + this.observers = new Batman.SimpleSet;
  172. + if (this.hasObserversToFire()) {
  173. + this.refreshTriggers();
  174. }
  175. + this._preventCount = 0;
  176. }
  177. + ObservableProperty.prototype.setValue = function(val) {
  178. + this.cacheDependentValues();
  179. + ObservableProperty.__super__.setValue.apply(this, arguments);
  180. + this.fireDependents();
  181. + return val;
  182. };
  183. + ObservableProperty.prototype.unsetValue = function() {
  184. + this.cacheDependentValues();
  185. + ObservableProperty.__super__.unsetValue.apply(this, arguments);
  186. + this.fireDependents();
  187. };
  188. + ObservableProperty.prototype.cacheDependentValues = function() {
  189. + if (this.dependents) {
  190. + return this.dependents.forEach(function(prop) {
  191. + return prop.cachedValue = prop.getValue();
  192. });
  193. }
  194. };
  195. + ObservableProperty.prototype.fireDependents = function() {
  196. + if (this.dependents) {
  197. + return this.dependents.forEach(function(prop) {
  198. + if (typeof prop.hasObserversToFire === "function" ? prop.hasObserversToFire() : void 0) {
  199. + return prop.fire(prop.getValue(), prop.cachedValue);
  200. }
  201. });
  202. }
  203. };
  204. + ObservableProperty.prototype.observe = function() {
  205. + var callback, currentValue, fireImmediately, _i;
  206. + fireImmediately = 2 <= arguments.length ? __slice.call(arguments, 0, _i = arguments.length - 1) : (_i = 0, []), callback = arguments[_i++];
  207. + fireImmediately = fireImmediately[0] === true;
  208. + currentValue = this.getValue();
  209. + this.observers.add(callback);
  210. + this.refreshTriggers();
  211. + if (fireImmediately) {
  212. + callback.call(this.base, currentValue, currentValue);
  213. }
  214. + return this;
  215. };
  216. + ObservableProperty.prototype.hasObserversToFire = function() {
  217. + if (this.observers.length > 0) {
  218. + return true;
  219. }
  220. + if (this.base._batman) {
  221. + return this.base._batman.ancestors().some(__bind(function(ancestor) {
  222. + var _ref, _ref2;
  223. + return (typeof ancestor.property === "function" ? (_ref = ancestor.property(this.key)) != null ? (_ref2 = _ref.observers) != null ? _ref2.length : void 0 : void 0 : void 0) > 0;
  224. }, this));
  225. } else {
  226. + return false;
  227. }
  228. };
  229. + ObservableProperty.prototype.prevent = function() {
  230. + return this._preventCount++;
  231. };
  232. + ObservableProperty.prototype.allow = function() {
  233. + if (this._preventCount > 0) {
  234. + return this._preventCount--;
  235. }
  236. };
  237. + ObservableProperty.prototype.isAllowedToFire = function() {
  238. + return this._preventCount <= 0;
  239. };
  240. + ObservableProperty.prototype.fire = function() {
  241. + var args, base, key, observerSets;
  242. + args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
  243. + if (!(this.isAllowedToFire() && this.hasObserversToFire())) {
  244. + return;
  245. }
  246. + key = this.key;
  247. + base = this.base;
  248. + observerSets = [this.observers];
  249. + this.observers.forEach(function(callback) {
  250. + return callback != null ? callback.apply(base, args) : void 0;
  251. });
  252. + if (this.base._batman) {
  253. + this.base._batman.ancestors(function(ancestor) {
  254. + return typeof ancestor.property === "function" ? ancestor.property(key).observers.forEach(function(callback) {
  255. + return callback != null ? callback.apply(base, args) : void 0;
  256. }) : void 0;
  257. });
  258. }
  259. + return this.refreshTriggers();
  260. };
  261. + ObservableProperty.prototype.forget = function(observer) {
  262. + if (observer) {
  263. + this.observers.remove(observer);
  264. } else {
  265. + this.observers = new Batman.SimpleSet;
  266. }
  267. + if (!this.hasObserversToFire()) {
  268. + return this.clearTriggers();
  269. }
  270. };
  271. + ObservableProperty.prototype.refreshTriggers = function() {
  272. + Batman.Property.triggerTracker = new Batman.SimpleSet;
  273. + this.getValue();
  274. + if (this.triggers) {
  275. + this.triggers.forEach(__bind(function(property) {
  276. + var _ref;
  277. + if (!Batman.Property.triggerTracker.has(property)) {
  278. + return (_ref = property.dependents) != null ? _ref.remove(this) : void 0;
  279. }
  280. }, this));
  281. }
  282. + this.triggers = Batman.Property.triggerTracker;
  283. + this.triggers.forEach(__bind(function(property) {
  284. + property.dependents || (property.dependents = new Batman.SimpleSet);
  285. + return property.dependents.add(this);
  286. }, this));
  287. + return delete Batman.Property.triggerTracker;
  288. };
  289. + ObservableProperty.prototype.clearTriggers = function() {
  290. + this.triggers.forEach(__bind(function(property) {
  291. + return property.dependents.remove(this);
  292. }, this));
  293. + return this.triggers = new Batman.SimpleSet;
  294. };
  295. + return ObservableProperty;
  296. })();
  297. + Batman.Keypath = (function() {
  298. + __extends(Keypath, Batman.ObservableProperty);
  299. + function Keypath(base, key) {
  300. + if ($typeOf(key) === 'String') {
  301. + this.segments = key.split('.');
  302. + this.depth = this.segments.length;
  303. } else {
  304. + this.segments = [key];
  305. + this.depth = 1;
  306. }
  307. + Keypath.__super__.constructor.apply(this, arguments);
  308. }
  309. + Keypath.prototype.slice = function(begin, end) {
  310. + var base, segment, _i, _len, _ref;
  311. + if (end == null) {
  312. + end = this.depth;
  313. }
  314. + base = this.base;
  315. + _ref = this.segments.slice(0, begin);
  316. + for (_i = 0, _len = _ref.length; _i < _len; _i++) {
  317. + segment = _ref[_i];
  318. + if (!((base != null) && (base = Batman.Keypath.forBaseAndKey(base, segment).getValue()))) {
  319. + return;
  320. }
  321. }
  322. + return Batman.Keypath.forBaseAndKey(base, this.segments.slice(begin, end).join('.'));
  323. };
  324. + Keypath.prototype.terminalProperty = function() {
  325. + return this.slice(-1);
  326. };
  327. + Keypath.prototype.getValue = function() {
  328. + var _ref;
  329. + this.registerAsTrigger();
  330. + if (this.depth === 1) {
  331. + return Keypath.__super__.getValue.apply(this, arguments);
  332. } else {
  333. + return (_ref = this.terminalProperty()) != null ? _ref.getValue() : void 0;
  334. }
  335. };
  336. + Keypath.prototype.setValue = function(val) {
  337. + var _ref;
  338. + if (this.depth === 1) {
  339. + return Keypath.__super__.setValue.apply(this, arguments);
  340. } else {
  341. + return (_ref = this.terminalProperty()) != null ? _ref.setValue(val) : void 0;
  342. }
  343. };
  344. + Keypath.prototype.unsetValue = function() {
  345. + var _ref;
  346. + if (this.depth === 1) {
  347. + return Keypath.__super__.unsetValue.apply(this, arguments);
  348. } else {
  349. + return (_ref = this.terminalProperty()) != null ? _ref.unsetValue() : void 0;
  350. }
  351. };
  352. + return Keypath;
  353. })();
  354. + Batman.Observable = {
  355. isObservable: true,
  356. property: function(key) {
  357. + Batman.initializeObject(this);
  358. + return Batman.Keypath.forBaseAndKey(this, key);
  359. },
  360. get: function(key) {
  361. + return this.property(key).getValue();
  362. },
  363. set: function(key, val) {
  364. + return this.property(key).setValue(val);
  365. },
  366. unset: function(key) {
  367. + return this.property(key).unsetValue();
  368. },
  369. getOrSet: function(key, valueFunction) {
  370. + var currentValue;
  371. + currentValue = this.get(key);
  372. + if (!currentValue) {
  373. + currentValue = valueFunction();
  374. + this.set(key, currentValue);
  375. }
  376. + return currentValue;
  377. },
  378. forget: function(key, observer) {
  379. + if (key) {
  380. + this.property(key).forget(observer);
  381. } else {
  382. + this._batman.properties.forEach(function(key, property) {
  383. + return property.forget();
  384. });
  385. }
  386. + return this;
  387. },
  388. allowed: function(key) {
  389. + return this.property(key).isAllowedToFire();
  390. }
  391. };
  392. + _ref = ['observe', 'prevent', 'allow', 'fire'];
  393. + _fn = function(k) {
  394. + return Batman.Observable[k] = function() {
  395. + var args, key, _ref2;
  396. + key = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
  397. + (_ref2 = this.property(key))[k].apply(_ref2, args);
  398. + return this;
  399. };
  400. };
  401. + for (_i = 0, _len = _ref.length; _i < _len; _i++) {
  402. + k = _ref[_i];
  403. + _fn(k);
  404. }
  405. + $get = Batman.get = function(object, key) {
  406. + if (object.get) {
  407. + return object.get(key);
  408. } else {
  409. - return Batman.Observable.get.call(object, key);
  410. }
  411. };
  412. + Batman.EventEmitter = {
  413. event: $block(function(key, context, callback) {
  414. + var f;
  415. + if (!callback && typeof context !== 'undefined') {
  416. + callback = context;
  417. + context = null;
  418. }
  419. + if (!callback && $typeOf(key) !== 'String') {
  420. + callback = key;
  421. + key = null;
  422. }
  423. + f = function(observer) {
  424. + var args, fired, firings, value, _base, _ref2, _ref3;
  425. + if (!this.observe) {
  426. - throw "EventEmitter requires Observable";
  427. }
  428. + Batman.initializeObject(this);
  429. + key || (key = $findName(f, this));
  430. + fired = (_ref2 = this._batman.oneShotFired) != null ? _ref2[key] : void 0;
  431. + if (typeof observer === 'function') {
  432. + this.observe(key, observer);
  433. + if (f.isOneShot && fired) {
  434. - return observer.apply(this, f._firedArgs);
  435. }
  436. + } else if (this.allowed(key)) {
  437. + if (f.isOneShot && fired) {
  438. + return false;
  439. }
  440. + value = callback != null ? callback.apply(this, arguments) : void 0;
  441. + if (value !== false) {
  442. + f._firedArgs = typeof value !== 'undefined' ? (_ref3 = [value]).concat.apply(_ref3, arguments) : arguments.length === 0 ? [] : Array.prototype.slice.call(arguments);
  443. + args = Array.prototype.slice.call(f._firedArgs);
  444. + args.unshift(key);
  445. + this.fire.apply(this, args);
  446. + if (f.isOneShot) {
  447. + firings = (_base = this._batman).oneShotFired || (_base.oneShotFired = {});
  448. + firings[key] = true;
  449. }
  450. }
  451. + return value;
  452. } else {
  453. - return false;
  454. }
  455. };
  456. + if (context) {
  457. + f = f.bind(context);
  458. }
  459. + if (key != null) {
  460. + this[key] = f;
  461. }
  462. + return $mixin(f, {
  463. isEvent: true,
  464. action: callback
  465. });
  466. }),
  467. eventOneShot: function(callback) {
  468. + return $mixin(Batman.EventEmitter.event.apply(this, arguments), {
  469. isOneShot: true,
  470. oneShotFired: this.oneShotFired.bind(this)
  471. });
  472. },
  473. oneShotFired: function(key) {
  474. + var firings, _base;
  475. + Batman.initializeObject(this);
  476. + firings = (_base = this._batman).oneShotFired || (_base.oneShotFired = {});
  477. + return !!firings[key];
  478. }
  479. };
  480. + Batman.event = $event = function(callback) {
  481. + var context;
  482. + context = new Batman.Object;
  483. + return context.event('_event', context, callback);
  484. };
  485. + Batman.eventOneShot = $eventOneShot = function(callback) {
  486. - var context, oneShot;
  487. - context = new Batman.Object;
  488. - oneShot = context.eventOneShot('_event', context, callback);
  489. - oneShot.oneShotFired = function() {
  490. - return context.oneShotFired('_event');
  491. };
  492. - return oneShot;
  493. };
  494. + Batman.initializeObject = function(object) {
  495. + if (object._batman != null) {
  496. + return object._batman.check(object);
  497. } else {
  498. + return object._batman = new _Batman(object);
  499. }
  500. };
  501. + Batman._Batman = _Batman = (function() {
  502. + function _Batman() {
  503. + var mixins, object;
  504. + object = arguments[0], mixins = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
  505. + this.object = object;
  506. + if (mixins.length > 0) {
  507. - $mixin.apply(null, [this].concat(__slice.call(mixins)));
  508. }
  509. }
  510. + _Batman.prototype.check = function(object) {
  511. + if (object !== this.object) {
  512. + object._batman = new _Batman(object);
  513. + return false;
  514. }
  515. + return true;
  516. };
  517. + _Batman.prototype.get = function(key) {
  518. + var results;
  519. + results = this.getAll(key);
  520. + switch (results.length) {
  521. case 0:
  522. + return;
  523. case 1:
  524. + return results[0];
  525. default:
  526. + if (results[0].concat != null) {
  527. + results = results.reduceRight(function(a, b) {
  528. + return a.concat(b);
  529. });
  530. + } else if (results[0].merge != null) {
  531. + results = results.reduceRight(function(a, b) {
  532. + return a.merge(b);
  533. });
  534. }
  535. + return results;
  536. }
  537. };
  538. + _Batman.prototype.getFirst = function(key) {
  539. + var results;
  540. + results = this.getAll(key);
  541. + return results[0];
  542. };
  543. + _Batman.prototype.getAll = function(keyOrGetter) {
  544. + var getter, results, val;
  545. + if (typeof keyOrGetter === 'function') {
  546. + getter = keyOrGetter;
  547. } else {
  548. + getter = function(ancestor) {
  549. + var _ref2;
  550. + return (_ref2 = ancestor._batman) != null ? _ref2[keyOrGetter] : void 0;
  551. };
  552. }
  553. + results = this.ancestors(getter);
  554. + if (val = getter(this.object)) {
  555. + results.unshift(val);
  556. }
  557. + return results;
  558. };
  559. + _Batman.prototype.ancestors = function(getter) {
  560. + var isClass, parent, proto, results, val, _ref2;
  561. + if (getter == null) {
  562. + getter = function(x) {
  563. + return x;
  564. };
  565. }
  566. + results = [];
  567. + isClass = !!this.object.prototype;
  568. + parent = isClass ? (_ref2 = this.object.__super__) != null ? _ref2.constructor : void 0 : (proto = Object.getPrototypeOf(this.object)) === this.object ? this.object.constructor.__super__ : proto;
  569. + if (parent != null) {
  570. + val = getter(parent);
  571. + if (val != null) {
  572. + results.push(val);
  573. }
  574. + if (parent._batman != null) {
  575. + results = results.concat(parent._batman.ancestors(getter));
  576. }
  577. }
  578. + return results;
  579. };
  580. + _Batman.prototype.set = function(key, value) {
  581. + return this[key] = value;
  582. };
  583. + return _Batman;
  584. })();
  585. + BatmanObject = (function() {
  586. + var getAccessorObject;
  587. + BatmanObject.global = function(isGlobal) {
  588. - if (isGlobal === false) {
  589. - return;
  590. }
  591. - return container[this.name] = this;
  592. };
  593. + BatmanObject.classMixin = function() {
  594. + return $mixin.apply(null, [this].concat(__slice.call(arguments)));
  595. };
  596. + BatmanObject.mixin = function() {
  597. + return this.classMixin.apply(this.prototype, arguments);
  598. };
  599. + BatmanObject.prototype.mixin = BatmanObject.classMixin;
  600. + getAccessorObject = function(accessor) {
  601. + if (!accessor.get && !accessor.set && !accessor.unset) {
  602. + accessor = {
  603. get: accessor
  604. };
  605. }
  606. + return accessor;
  607. };
  608. + BatmanObject.classAccessor = function() {
  609. + var accessor, key, keys, _base, _j, _k, _len2, _results;
  610. + keys = 2 <= arguments.length ? __slice.call(arguments, 0, _j = arguments.length - 1) : (_j = 0, []), accessor = arguments[_j++];
  611. + Batman.initializeObject(this);
  612. + if (keys.length === 0) {
  613. + return this._batman.defaultAccessor = getAccessorObject(accessor);
  614. } else {
  615. + (_base = this._batman).keyAccessors || (_base.keyAccessors = new Batman.SimpleHash);
  616. + _results = [];
  617. + for (_k = 0, _len2 = keys.length; _k < _len2; _k++) {
  618. + key = keys[_k];
  619. + _results.push(this._batman.keyAccessors.set(key, getAccessorObject(accessor)));
  620. }
  621. + return _results;
  622. }
  623. };
  624. + BatmanObject.accessor = function() {
  625. + return this.classAccessor.apply(this.prototype, arguments);
  626. };
  627. + BatmanObject.prototype.accessor = BatmanObject.classAccessor;
  628. + function BatmanObject() {
  629. + var mixins;
  630. + mixins = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
  631. + this._batman = new _Batman(this);
  632. + this.mixin.apply(this, mixins);
  633. }
  634. + BatmanObject.classMixin(Batman.Observable, Batman.EventEmitter);
  635. + BatmanObject.mixin(Batman.Observable, Batman.EventEmitter);
  636. + BatmanObject.observeAll = function() {
  637. + return this.prototype.observe.apply(this.prototype, arguments);
  638. };
  639. + BatmanObject.singleton = function(singletonMethodName) {
  640. + if (singletonMethodName == null) {
  641. - singletonMethodName = "sharedInstance";
  642. }
  643. + return this.classAccessor(singletonMethodName, {
  644. get: function() {
  645. + var _name;
  646. + return this[_name = "_" + singletonMethodName] || (this[_name] = new this);
  647. }
  648. });
  649. };
  650. + return BatmanObject;
  651. })();
  652. + Batman.Object = BatmanObject;
  653. + Batman.Accessible = (function() {
  654. + __extends(Accessible, Batman.Object);
  655. + function Accessible() {
  656. + this.accessor.apply(this, arguments);
  657. }
  658. + return Accessible;
  659. })();
  660. + Batman.SimpleHash = (function() {
  661. + function SimpleHash() {
  662. + this._storage = {};
  663. + this.length = 0;
  664. }
  665. + SimpleHash.prototype.hasKey = function(key) {
  666. + var match, matches, pair, _base, _j, _len2;
  667. + matches = (_base = this._storage)[key] || (_base[key] = []);
  668. + for (_j = 0, _len2 = matches.length; _j < _len2; _j++) {
  669. + match = matches[_j];
  670. + if (this.equality(match[0], key)) {
  671. + pair = match;
  672. + return true;
  673. }
  674. }
  675. + return false;
  676. };
  677. + SimpleHash.prototype.get = function(key) {
  678. + var matches, obj, v, _j, _len2, _ref2;
  679. + if (matches = this._storage[key]) {
  680. + for (_j = 0, _len2 = matches.length; _j < _len2; _j++) {
  681. + _ref2 = matches[_j], obj = _ref2[0], v = _ref2[1];
  682. + if (this.equality(obj, key)) {
  683. + return v;
  684. }
  685. }
  686. }
  687. };
  688. + SimpleHash.prototype.set = function(key, val) {
  689. + var match, matches, pair, _base, _j, _len2;
  690. + matches = (_base = this._storage)[key] || (_base[key] = []);
  691. + for (_j = 0, _len2 = matches.length; _j < _len2; _j++) {
  692. + match = matches[_j];
  693. + if (this.equality(match[0], key)) {
  694. + pair = match;
  695. + break;
  696. }
  697. }
  698. + if (!pair) {
  699. + pair = [key];
  700. + matches.push(pair);
  701. + this.length++;
  702. }
  703. + return pair[1] = val;
  704. };
  705. + SimpleHash.prototype.unset = function(key) {
  706. + var index, matches, obj, v, _len2, _ref2;
  707. + if (matches = this._storage[key]) {
  708. + for (index = 0, _len2 = matches.length; index < _len2; index++) {
  709. + _ref2 = matches[index], obj = _ref2[0], v = _ref2[1];
  710. + if (this.equality(obj, key)) {
  711. + matches.splice(index, 1);
  712. + this.length--;
  713. + return;
  714. }
  715. }
  716. }
  717. };
  718. + SimpleHash.prototype.getOrSet = Batman.Observable.getOrSet;
  719. + SimpleHash.prototype.equality = function(lhs, rhs) {
  720. + if (lhs === rhs) {
  721. + return true;
  722. }
  723. + if (lhs !== lhs && rhs !== rhs) {
  724. + return true;
  725. }
  726. + 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)) {
  727. + return true;
  728. }
  729. + return false;
  730. };
  731. + SimpleHash.prototype.forEach = function(iterator) {
  732. + var key, obj, value, values, _ref2, _results;
  733. + _ref2 = this._storage;
  734. + _results = [];
  735. + for (key in _ref2) {
  736. + values = _ref2[key];
  737. + _results.push((function() {
  738. + var _j, _len2, _ref3, _results2;
  739. + _results2 = [];
  740. + for (_j = 0, _len2 = values.length; _j < _len2; _j++) {
  741. + _ref3 = values[_j], obj = _ref3[0], value = _ref3[1];
  742. + _results2.push(iterator(obj, value));
  743. }
  744. + return _results2;
  745. })());
  746. }
  747. + return _results;
  748. };
  749. + SimpleHash.prototype.keys = function() {
  750. + var result;
  751. + result = [];
  752. + this.forEach(function(obj) {
  753. + return result.push(obj);
  754. });
  755. + return result;
  756. };
  757. + SimpleHash.prototype.clear = function() {
  758. + this._storage = {};
  759. + return this.length = 0;
  760. };
  761. + SimpleHash.prototype.isEmpty = function() {
  762. + return this.length === 0;
  763. };
  764. + SimpleHash.prototype.merge = function() {
  765. + var hash, merged, others, _j, _len2;
  766. + others = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
  767. + merged = new this.constructor;
  768. + others.unshift(this);
  769. + for (_j = 0, _len2 = others.length; _j < _len2; _j++) {
  770. + hash = others[_j];
  771. + hash.forEach(function(obj, value) {
  772. + return merged.set(obj, value);
  773. });
  774. }
  775. + return merged;
  776. };
  777. + return SimpleHash;
  778. })();
  779. + Batman.Hash = (function() {
  780. + var k, _j, _len2, _ref2;
  781. + __extends(Hash, Batman.Object);
  782. + function Hash() {
  783. + Batman.SimpleHash.apply(this, arguments);
  784. + Hash.__super__.constructor.apply(this, arguments);
  785. }
  786. + Hash.accessor({
  787. get: Batman.SimpleHash.prototype.get,
  788. set: Batman.SimpleHash.prototype.set,
  789. unset: Batman.SimpleHash.prototype.unset
  790. });
  791. + Hash.accessor('isEmpty', function() {
  792. + return this.isEmpty();
  793. });
  794. + _ref2 = ['hasKey', 'equality', 'forEach', 'keys', 'isEmpty', 'merge', 'clear'];
  795. + for (_j = 0, _len2 = _ref2.length; _j < _len2; _j++) {
  796. + k = _ref2[_j];
  797. + Hash.prototype[k] = Batman.SimpleHash.prototype[k];
  798. }
  799. + return Hash;
  800. })();
  801. + Batman.SimpleSet = (function() {
  802. + function SimpleSet() {
  803. + this._storage = new Batman.SimpleHash;
  804. + this._indexes = new Batman.SimpleHash;
  805. + this._sorts = new Batman.SimpleHash;
  806. + this.length = 0;
  807. + if (arguments.length > 0) {
  808. + this.add.apply(this, arguments);
  809. }
  810. }
  811. + SimpleSet.prototype.has = function(item) {
  812. + return this._storage.hasKey(item);
  813. };
  814. + SimpleSet.prototype.add = function() {
  815. + var addedItems, item, items, _j, _len2;
  816. + items = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
  817. + addedItems = [];
  818. + for (_j = 0, _len2 = items.length; _j < _len2; _j++) {
  819. + item = items[_j];
  820. + if (!this._storage.hasKey(item)) {
  821. + this._storage.set(item, true);
  822. + addedItems.push(item);
  823. + this.length++;
  824. }
  825. }
  826. + if (addedItems.length !== 0) {
  827. + this.itemsWereAdded.apply(this, addedItems);
  828. }
  829. + return addedItems;
  830. };
  831. + SimpleSet.prototype.remove = function() {
  832. + var item, items, removedItems, _j, _len2;
  833. + items = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
  834. + removedItems = [];
  835. + for (_j = 0, _len2 = items.length; _j < _len2; _j++) {
  836. + item = items[_j];
  837. + if (this._storage.hasKey(item)) {
  838. + this._storage.unset(item);
  839. + removedItems.push(item);
  840. + this.length--;
  841. }
  842. }
  843. + if (removedItems.length !== 0) {
  844. + this.itemsWereRemoved.apply(this, removedItems);
  845. }
  846. + return removedItems;
  847. };
  848. + SimpleSet.prototype.forEach = function(iterator) {
  849. + return this._storage.forEach(function(key, value) {
  850. + return iterator(key);
  851. });
  852. };
  853. + SimpleSet.prototype.isEmpty = function() {
  854. + return this.length === 0;
  855. };
  856. + SimpleSet.prototype.clear = function() {
  857. + var items;
  858. + items = this.toArray();
  859. + this._storage = new Batman.SimpleHash;
  860. + this.length = 0;
  861. + this.itemsWereRemoved.apply(this, items);
  862. + return items;
  863. };
  864. + SimpleSet.prototype.toArray = function() {
  865. + return this._storage.keys();
  866. };
  867. + SimpleSet.prototype.merge = function() {
  868. + var merged, others, set, _j, _len2;
  869. + others = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
  870. + merged = new this.constructor;
  871. + others.unshift(this);
  872. + for (_j = 0, _len2 = others.length; _j < _len2; _j++) {
  873. + set = others[_j];
  874. + set.forEach(function(v) {
  875. + return merged.add(v);
  876. });
  877. }
  878. + return merged;
  879. };
  880. + SimpleSet.prototype.indexedBy = function(key) {
  881. + return this._indexes.get(key) || this._indexes.set(key, new Batman.SetIndex(this, key));
  882. };
  883. + SimpleSet.prototype.sortedBy = function(key) {
  884. - return this._sorts.get(key) || this._sorts.set(key, new Batman.SetSort(this, key));
  885. };
  886. + SimpleSet.prototype.itemsWereAdded = function() {};
  887. + SimpleSet.prototype.itemsWereRemoved = function() {};
  888. + return SimpleSet;
  889. })();
  890. + Batman.Set = (function() {
  891. + var k, _fn2, _j, _k, _len2, _len3, _ref2, _ref3;
  892. + __extends(Set, Batman.Object);
  893. + function Set() {
  894. + Batman.SimpleSet.apply(this, arguments);
  895. }
  896. + Set.prototype.itemsWereAdded = Set.event(function() {});
  897. + Set.prototype.itemsWereRemoved = Set.event(function() {});
  898. + _ref2 = ['has', 'forEach', 'isEmpty', 'toArray', 'indexedBy', 'sortedBy'];
  899. + for (_j = 0, _len2 = _ref2.length; _j < _len2; _j++) {
  900. + k = _ref2[_j];
  901. + Set.prototype[k] = Batman.SimpleSet.prototype[k];
  902. }
  903. + _ref3 = ['add', 'remove', 'clear', 'merge'];
  904. + _fn2 = __bind(function(k) {
  905. + return this.prototype[k] = function() {
  906. + var oldLength, results;
  907. + oldLength = this.length;
  908. + results = Batman.SimpleSet.prototype[k].apply(this, arguments);
  909. + this.property('length').fireDependents();
  910. + return results;
  911. };
  912. }, Set);
  913. + for (_k = 0, _len3 = _ref3.length; _k < _len3; _k++) {
  914. + k = _ref3[_k];
  915. + _fn2(k);
  916. }
  917. + Set.accessor('indexedBy', function() {
  918. + return new Batman.Accessible(__bind(function(key) {
  919. + return this.indexedBy(key);
  920. }, this));
  921. });
  922. + Set.accessor('sortedBy', function() {
  923. - return new Batman.Accessible(__bind(function(key) {
  924. - return this.sortedBy(key);
  925. }, this));
  926. });
  927. + Set.accessor('isEmpty', function() {
  928. + return this.isEmpty();
  929. });
  930. + Set.accessor('length', function() {
  931. + return this.length;
  932. });
  933. + return Set;
  934. }).call(this);
  935. + Batman.SetObserver = (function() {
  936. + __extends(SetObserver, Batman.Object);
  937. + function SetObserver(base) {
  938. + this.base = base;
  939. + this._itemObservers = new Batman.Hash;
  940. + this._setObservers = new Batman.Hash;
  941. + this._setObservers.set("itemsWereAdded", this.itemsWereAdded.bind(this));
  942. + this._setObservers.set("itemsWereRemoved", this.itemsWereRemoved.bind(this));
  943. + this.observe('itemsWereAdded', this.startObservingItems.bind(this));
  944. + this.observe('itemsWereRemoved', this.stopObservingItems.bind(this));
  945. }
  946. + SetObserver.prototype.itemsWereAdded = SetObserver.event(function() {});
  947. + SetObserver.prototype.itemsWereRemoved = SetObserver.event(function() {});
  948. + SetObserver.prototype.observedItemKeys = [];
  949. + SetObserver.prototype.observerForItemAndKey = function(item, key) {};
  950. + SetObserver.prototype._getOrSetObserverForItemAndKey = function(item, key) {
  951. + return this._itemObservers.getOrSet(item, __bind(function() {
  952. + var observersByKey;
  953. + observersByKey = new Batman.Hash;
  954. + return observersByKey.getOrSet(key, __bind(function() {
  955. + return this.observerForItemAndKey(item, key);
  956. }, this));
  957. }, this));
  958. };
  959. + SetObserver.prototype.startObserving = function() {
  960. + this._manageItemObservers("observe");
  961. + return this._manageSetObservers("observe");
  962. };
  963. + SetObserver.prototype.stopObserving = function() {
  964. + this._manageItemObservers("forget");
  965. + return this._manageSetObservers("forget");
  966. };
  967. + SetObserver.prototype.startObservingItems = function() {
  968. + var item, items, _j, _len2, _results;
  969. + items = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
  970. + _results = [];
  971. + for (_j = 0, _len2 = items.length; _j < _len2; _j++) {
  972. + item = items[_j];
  973. + _results.push(this._manageObserversForItem(item, "observe"));
  974. }
  975. + return _results;
  976. };
  977. + SetObserver.prototype.stopObservingItems = function() {
  978. + var item, items, _j, _len2, _results;
  979. + items = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
  980. + _results = [];
  981. + for (_j = 0, _len2 = items.length; _j < _len2; _j++) {
  982. + item = items[_j];
  983. + _results.push(this._manageObserversForItem(item, "forget"));
  984. }
  985. + return _results;
  986. };
  987. + SetObserver.prototype._manageObserversForItem = function(item, method) {
  988. + var key, _j, _len2, _ref2;
  989. + if (!item.isObservable) {
  990. + return;
  991. }
  992. + _ref2 = this.observedItemKeys;
  993. + for (_j = 0, _len2 = _ref2.length; _j < _len2; _j++) {
  994. + key = _ref2[_j];
  995. + item[method](key, this._getOrSetObserverForItemAndKey(item, key));
  996. }
  997. + if (method === "forget") {
  998. + return this._itemObservers.unset(item);
  999. }
  1000. };
  1001. + SetObserver.prototype._manageItemObservers = function(method) {
  1002. + return this.base.forEach(__bind(function(item) {
  1003. + return this._manageObserversForItem(item, method);
  1004. }, this));
  1005. };
  1006. + SetObserver.prototype._manageSetObservers = function(method) {
  1007. + if (!this.base.isObservable) {
  1008. - return;
  1009. }
  1010. + return this._setObservers.forEach(__bind(function(key, observer) {
  1011. + return this.base[method](key, observer);
  1012. }, this));
  1013. };
  1014. + return SetObserver;
  1015. })();
  1016. + Batman.SetSort = (function() {
  1017. + __extends(SetSort, Batman.Object);
  1018. + function SetSort(base, key) {
  1019. + var boundReIndex;
  1020. + this.base = base;
  1021. + this.key = key;
  1022. + if (this.base.isObservable) {
  1023. + this._setObserver = new Batman.SetObserver(this.base);
  1024. + this._setObserver.observedItemKeys = [this.key];
  1025. + boundReIndex = this._reIndex.bind(this);
  1026. + this._setObserver.observerForItemAndKey = function() {
  1027. + return boundReIndex;
  1028. };
  1029. + this._setObserver.observe('itemsWereAdded', boundReIndex);
  1030. + this._setObserver.observe('itemsWereRemoved', boundReIndex);
  1031. + this.startObserving();
  1032. }
  1033. + this._reIndex();
  1034. }
  1035. + SetSort.prototype.startObserving = function() {
  1036. + var _ref2;
  1037. + return (_ref2 = this._setObserver) != null ? _ref2.startObserving() : void 0;
  1038. };
  1039. + SetSort.prototype.stopObserving = function() {
  1040. + var _ref2;
  1041. + return (_ref2 = this._setObserver) != null ? _ref2.stopObserving() : void 0;
  1042. };
  1043. + SetSort.prototype.toArray = function() {
  1044. + return this.get('_storage');
  1045. };
  1046. + SetSort.accessor('toArray', SetSort.prototype.toArray);
  1047. + SetSort.prototype.forEach = function(iterator) {
  1048. + var e, i, _len2, _ref2, _results;
  1049. + _ref2 = this.get('_storage');
  1050. + _results = [];
  1051. + for (i = 0, _len2 = _ref2.length; i < _len2; i++) {
  1052. + e = _ref2[i];
  1053. + _results.push(iterator(e, i));
  1054. }
  1055. + return _results;
  1056. };
  1057. + SetSort.prototype.compare = function(a, b) {
  1058. + var typeComparison;
  1059. + if (a === b) {
  1060. + return 0;
  1061. }
  1062. + if (a === void 0) {
  1063. + return 1;
  1064. }
  1065. + if (b === void 0) {
  1066. + return -1;
  1067. }
  1068. + if (a === null) {
  1069. + return 1;
  1070. }
  1071. + if (b === null) {
  1072. + return -1;
  1073. }
  1074. + if ((typeof a.isEqual === "function" ? a.isEqual(b) : void 0) && (typeof b.isEqual === "function" ? b.isEqual(a) : void 0)) {
  1075. - return 0;
  1076. }
  1077. + typeComparison = Batman.SetSort.prototype.compare($typeOf(a), $typeOf(b));
  1078. + if (typeComparison !== 0) {
  1079. + return typeComparison;
  1080. }
  1081. + if (a !== a) {
  1082. + return 1;
  1083. }
  1084. + if (b !== b) {
  1085. + return -1;
  1086. }
  1087. + if (a > b) {
  1088. + return 1;
  1089. }
  1090. + if (a < b) {
  1091. + return -1;
  1092. }
  1093. - return 0;
  1094. };
  1095. + SetSort.prototype._reIndex = function() {
  1096. + var newOrder, _ref2;
  1097. + newOrder = this.base.toArray().sort(__bind(function(a, b) {
  1098. + var valueA, valueB;
  1099. + valueA = Batman.Observable.property.call(a, this.key).getValue();
  1100. + if (valueA != null) {
  1101. + valueA = valueA.valueOf();
  1102. }
  1103. + valueB = Batman.Observable.property.call(b, this.key).getValue();
  1104. + if (valueB != null) {
  1105. + valueB = valueB.valueOf();
  1106. }
  1107. + return this.compare.call(this, valueA, valueB);
  1108. }, this));
  1109. + if ((_ref2 = this._setObserver) != null) {
  1110. + _ref2.startObservingItems.apply(_ref2, newOrder);
  1111. }
  1112. + return this.set('_storage', newOrder);
  1113. };
  1114. + return SetSort;
  1115. })();
  1116. + Batman.SetIndex = (function() {
  1117. + __extends(SetIndex, Batman.Object);
  1118. + function SetIndex(base, key) {
  1119. + this.base = base;
  1120. + this.key = key;
  1121. + this._storage = new Batman.Hash;
  1122. + if (this.base.isObservable) {
  1123. + this._setObserver = new Batman.SetObserver(this.base);
  1124. + this._setObserver.observedItemKeys = [this.key];
  1125. + this._setObserver.observerForItemAndKey = this.observerForItemAndKey.bind(this);
  1126. + this._setObserver.observe('itemsWereAdded', __bind(function() {
  1127. + var item, items, _j, _len2, _results;
  1128. + items = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
  1129. + _results = [];
  1130. + for (_j = 0, _len2 = items.length; _j < _len2; _j++) {
  1131. + item = items[_j];
  1132. + _results.push(this._addItem(item));
  1133. }
  1134. + return _results;
  1135. }, this));
  1136. + this._setObserver.observe('itemsWereRemoved', __bind(function() {
  1137. + var item, items, _j, _len2, _results;
  1138. + items = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
  1139. + _results = [];
  1140. + for (_j = 0, _len2 = items.length; _j < _len2; _j++) {
  1141. + item = items[_j];
  1142. + _results.push(this._removeItem(item));
  1143. }
  1144. + return _results;
  1145. }, this));
  1146. }
  1147. + this.base.forEach(this._addItem.bind(this));
  1148. + this.startObserving();
  1149. }
  1150. + SetIndex.accessor(function(key) {
  1151. + return this._resultSetForKey(key);
  1152. });
  1153. + SetIndex.prototype.startObserving = function() {
  1154. + var _ref2;
  1155. + return (_ref2 = this._setObserver) != null ? _ref2.startObserving() : void 0;
  1156. };
  1157. + SetIndex.prototype.stopObserving = function() {
  1158. + var _ref2;
  1159. + return (_ref2 = this._setObserver) != null ? _ref2.stopObserving() : void 0;
  1160. };
  1161. + SetIndex.prototype.observerForItemAndKey = function(item, key) {
  1162. + return __bind(function(newValue, oldValue) {
  1163. + this._removeItemFromKey(item, oldValue);
  1164. + return this._addItemToKey(item, newValue);
  1165. }, this);
  1166. };
  1167. + SetIndex.prototype._addItem = function(item) {
  1168. + return this._addItemToKey(item, this._keyForItem(item));
  1169. };
  1170. + SetIndex.prototype._addItemToKey = function(item, key) {
  1171. + return this._resultSetForKey(key).add(item);
  1172. };
  1173. + SetIndex.prototype._removeItem = function(item) {
  1174. + return this._removeItemFromKey(item, this._keyForItem(item));
  1175. };
  1176. + SetIndex.prototype._removeItemFromKey = function(item, key) {
  1177. + return this._resultSetForKey(key).remove(item);
  1178. };
  1179. + SetIndex.prototype._resultSetForKey = function(key) {
  1180. + return this._storage.getOrSet(key, function() {
  1181. + return new Batman.Set;
  1182. });
  1183. };
  1184. + SetIndex.prototype._keyForItem = function(item) {
  1185. + return Batman.Keypath.forBaseAndKey(item, this.key).getValue();
  1186. };
  1187. + return SetIndex;
  1188. })();
  1189. + Batman.UniqueSetIndex = (function() {
  1190. + __extends(UniqueSetIndex, Batman.SetIndex);
  1191. + function UniqueSetIndex() {
  1192. + this._uniqueIndex = new Batman.Hash;
  1193. + UniqueSetIndex.__super__.constructor.apply(this, arguments);
  1194. }
  1195. + UniqueSetIndex.accessor(function(key) {
  1196. + return this._uniqueIndex.get(key);
  1197. });
  1198. + UniqueSetIndex.prototype._addItemToKey = function(item, key) {
  1199. + this._resultSetForKey(key).add(item);
  1200. + if (!this._uniqueIndex.hasKey(key)) {
  1201. + return this._uniqueIndex.set(key, item);
  1202. }
  1203. };
  1204. + UniqueSetIndex.prototype._removeItemFromKey = function(item, key) {
  1205. + var resultSet;
  1206. + resultSet = this._resultSetForKey(key);
  1207. + resultSet.remove(item);
  1208. + if (resultSet.length === 0) {
  1209. + return this._uniqueIndex.unset(key);
  1210. } else {
  1211. + return this._uniqueIndex.set(key, resultSet.toArray()[0]);
  1212. }
  1213. };
  1214. + return UniqueSetIndex;
  1215. })();
  1216. + Batman.SortableSet = (function() {
  1217. + __extends(SortableSet, Batman.Set);
  1218. + function SortableSet() {
  1219. + SortableSet.__super__.constructor.apply(this, arguments);
  1220. + this._sortIndexes = {};
  1221. + this.observe('activeIndex', __bind(function() {
  1222. + return this.setWasSorted(this);
  1223. }, this));
  1224. }
  1225. + SortableSet.prototype.setWasSorted = SortableSet.event(function() {
  1226. + if (this.length === 0) {
  1227. + return false;
  1228. }
  1229. });
  1230. + SortableSet.prototype.add = function() {
  1231. + var results;
  1232. + results = SortableSet.__super__.add.apply(this, arguments);
  1233. + this._reIndex();
  1234. + return results;
  1235. };
  1236. + SortableSet.prototype.remove = function() {
  1237. + var results;
  1238. + results = SortableSet.__super__.remove.apply(this, arguments);
  1239. + this._reIndex();
  1240. + return results;
  1241. };
  1242. + SortableSet.prototype.addIndex = function(index) {
  1243. + return this._reIndex(index);
  1244. };
  1245. + SortableSet.prototype.removeIndex = function(index) {
  1246. - this._sortIndexes[index] = null;
  1247. - delete this._sortIndexes[index];
  1248. - if (this.activeIndex === index) {
  1249. - this.unset('activeIndex');
  1250. }
  1251. - return index;
  1252. };
  1253. + SortableSet.prototype.forEach = function(iterator) {
  1254. + var el, _j, _len2, _ref2, _results;
  1255. + _ref2 = this.toArray();
  1256. + _results = [];
  1257. + for (_j = 0, _len2 = _ref2.length; _j < _len2; _j++) {
  1258. + el = _ref2[_j];
  1259. + _results.push(iterator(el));
  1260. }
  1261. + return _results;
  1262. };
  1263. + SortableSet.prototype.sortBy = function(index) {
  1264. + if (!this._sortIndexes[index]) {
  1265. + this.addIndex(index);
  1266. }
  1267. + if (this.activeIndex !== index) {
  1268. + this.set('activeIndex', index);
  1269. }
  1270. + return this;
  1271. };
  1272. + SortableSet.prototype.isSorted = function() {
  1273. + return this._sortIndexes[this.get('activeIndex')] != null;
  1274. };
  1275. + SortableSet.prototype.toArray = function() {
  1276. + return this._sortIndexes[this.get('activeIndex')] || SortableSet.__super__.toArray.apply(this, arguments);
  1277. };
  1278. + SortableSet.prototype._reIndex = function(index) {
  1279. + var ary, keypath, ordering, _ref2;
  1280. + if (index) {
  1281. + _ref2 = index.split(' '), keypath = _ref2[0], ordering = _ref2[1];
  1282. + ary = Batman.Set.prototype.toArray.call(this);
  1283. + this._sortIndexes[index] = ary.sort(function(a, b) {
  1284. + var valueA, valueB, _ref3, _ref4, _ref5;
  1285. + valueA = (_ref3 = (Batman.Observable.property.call(a, keypath)).getValue()) != null ? _ref3.valueOf() : void 0;
  1286. + valueB = (_ref4 = (Batman.Observable.property.call(b, keypath)).getValue()) != null ? _ref4.valueOf() : void 0;
  1287. + if ((ordering != null ? ordering.toLowerCase() : void 0) === 'desc') {
  1288. + _ref5 = [valueB, valueA], valueA = _ref5[0], valueB = _ref5[1];
  1289. }
  1290. + if (valueA < valueB) {
  1291. + return -1;
  1292. + } else if (valueA > valueB) {
  1293. + return 1;
  1294. } else {
  1295. + return 0;
  1296. }
  1297. });
  1298. + if (this.activeIndex === index) {
  1299. + this.setWasSorted(this);
  1300. }
  1301. } else {
  1302. + for (index in this._sortIndexes) {
  1303. + this._reIndex(index);
  1304. }
  1305. + this.setWasSorted(this);
  1306. }
  1307. + return this;
  1308. };
  1309. + return SortableSet;
  1310. })();
  1311. + Batman.StateMachine = {
  1312. initialize: function() {
  1313. + Batman.initializeObject(this);
  1314. + if (!this._batman.states) {
  1315. + this._batman.states = new Batman.SimpleHash;
  1316. + return this.accessor('state', {
  1317. get: function() {
  1318. + return this.state();
  1319. },
  1320. set: function(key, value) {
  1321. + return _stateMachine_setState.call(this, value);
  1322. }
  1323. });
  1324. }
  1325. },
  1326. state: function(name, callback) {
  1327. + var event;
  1328. + Batman.StateMachine.initialize.call(this);
  1329. + if (!name) {
  1330. + return this._batman.getFirst('state');
  1331. }
  1332. + if (!this.event) {
  1333. - throw "StateMachine requires EventEmitter";
  1334. }
  1335. + event = this[name] || this.event(name, function() {
  1336. + _stateMachine_setState.call(this, name);
  1337. + return false;
  1338. });
  1339. + if (typeof callback === 'function') {
  1340. + event.call(this, callback);
  1341. }
  1342. + return event;
  1343. },
  1344. transition: function(from, to, callback) {
  1345. + var event, name, transitions;
  1346. + Batman.StateMachine.initialize.call(this);
  1347. + this.state(from);
  1348. + this.state(to);
  1349. + name = "" + from + "->" + to;
  1350. + transitions = this._batman.states;
  1351. + event = transitions.get(name) || transitions.set(name, $event(function() {}));
  1352. + if (callback) {
  1353. + event(callback);
  1354. }
  1355. + return event;
  1356. }
  1357. };
  1358. + Batman.Object.actsAsStateMachine = function(includeInstanceMethods) {
  1359. + if (includeInstanceMethods == null) {
  1360. - includeInstanceMethods = true;
  1361. }
  1362. + Batman.StateMachine.initialize.call(this);
  1363. + Batman.StateMachine.initialize.call(this.prototype);
  1364. + this.classState = function() {
  1365. + return Batman.StateMachine.state.apply(this, arguments);
  1366. };
  1367. + this.state = function() {
  1368. + return this.classState.apply(this.prototype, arguments);
  1369. };
  1370. + if (includeInstanceMethods) {
  1371. + this.prototype.state = this.classState;
  1372. }
  1373. + this.classTransition = function() {
  1374. + return Batman.StateMachine.transition.apply(this, arguments);
  1375. };
  1376. + this.transition = function() {
  1377. - return this.classTransition.apply(this.prototype, arguments);
  1378. };
  1379. + if (includeInstanceMethods) {
  1380. + return this.prototype.transition = this.classTransition;
  1381. }
  1382. };
  1383. + _stateMachine_setState = function(newState) {
  1384. + var event, name, oldState, _base, _j, _len2, _ref2, _ref3;
  1385. + Batman.StateMachine.initialize.call(this);
  1386. + if (this._batman.isTransitioning) {
  1387. + ((_base = this._batman).nextState || (_base.nextState = [])).push(newState);
  1388. + return false;
  1389. }
  1390. + this._batman.isTransitioning = true;
  1391. + oldState = this.state();
  1392. + this._batman.state = newState;
  1393. + if (newState && oldState) {
  1394. + name = "" + oldState + "->" + newState;
  1395. + _ref2 = this._batman.getAll(function(ancestor) {
  1396. + var _ref2, _ref3;
  1397. + return (_ref2 = ancestor._batman) != null ? (_ref3 = _ref2.get('states')) != null ? _ref3.get(name) : void 0 : void 0;
  1398. });
  1399. + for (_j = 0, _len2 = _ref2.length; _j < _len2; _j++) {
  1400. + event = _ref2[_j];
  1401. + if (event) {
  1402. + event(newState, oldState);
  1403. }
  1404. }
  1405. }
  1406. + if (newState) {
  1407. + this.fire(newState, newState, oldState);
  1408. }
  1409. + this._batman.isTransitioning = false;
  1410. + if ((_ref3 = this._batman.nextState) != null ? _ref3.length : void 0) {
  1411. + this[this._batman.nextState.shift()]();
  1412. }
  1413. + return newState;
  1414. };
  1415. + Batman.Request = (function() {
  1416. + __extends(Request, Batman.Object);
  1417. + function Request() {
  1418. + Request.__super__.constructor.apply(this, arguments);
  1419. }
  1420. + Request.prototype.url = '';
  1421. + Request.prototype.data = '';
  1422. + Request.prototype.method = 'get';
  1423. + Request.prototype.response = null;
  1424. + Request.prototype.contentType = 'application/json';
  1425. + Request.observeAll('url', function() {
  1426. + return this._autosendTimeout = setTimeout((__bind(function() {
  1427. + return this.send();
  1428. }, this)), 0);
  1429. });
  1430. + Request.prototype.loading = Request.event(function() {});
  1431. + Request.prototype.loaded = Request.event(function() {});
  1432. + Request.prototype.success = Request.event(function() {});
  1433. + Request.prototype.error = Request.event(function() {});
  1434. + Request.prototype.send = function() {
  1435. - throw "Please source a dependency file for a request implementation";
  1436. };
  1437. + Request.prototype.cancel = function() {
  1438. - if (this._autosendTimeout) {
  1439. - return clearTimeout(this._autosendTimeout);
  1440. }
  1441. };
  1442. + return Request;
  1443. })();
  1444. + Batman.App = (function() {
  1445. + __extends(App, Batman.Object);
  1446. + function App() {
  1447. - App.__super__.constructor.apply(this, arguments);
  1448. }
  1449. + App.requirePath = '';
  1450. + App.require = function() {
  1451. - var base, name, names, path, _j, _len2;
  1452. - path = arguments[0], names = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
  1453. - base = this.requirePath + path;
  1454. - for (_j = 0, _len2 = names.length; _j < _len2; _j++) {
  1455. - name = names[_j];
  1456. - this.prevent('run');
  1457. - path = base + '/' + name + '.coffee';
  1458. - new Batman.Request({
  1459. url: path,
  1460. type: 'html',
  1461. success: __bind(function(response) {
  1462. - CoffeeScript.eval(response);
  1463. - this.allow('run');
  1464. - return this.run();
  1465. }, this)
  1466. });
  1467. }
  1468. - return this;
  1469. };
  1470. + App.controller = function() {
  1471. - var names;
  1472. - names = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
  1473. - names = names.map(function(n) {
  1474. - return n + '_controller';
  1475. });
  1476. - return this.require.apply(this, ['controllers'].concat(__slice.call(names)));
  1477. };
  1478. + App.model = function() {
  1479. - return this.require.apply(this, ['models'].concat(__slice.call(arguments)));
  1480. };
  1481. + App.view = function() {
  1482. - return this.require.apply(this, ['views'].concat(__slice.call(arguments)));
  1483. };
  1484. + App.layout = void 0;
  1485. + App.run = App.eventOneShot(function() {
  1486. - if (Batman.currentApp) {
  1487. - if (Batman.currentApp === this) {
  1488. - return;
  1489. }
  1490. - Batman.currentApp.stop();
  1491. }
  1492. - if (this.hasRun) {
  1493. - return false;
  1494. }
  1495. - Batman.currentApp = this;
  1496. - if (typeof this.dispatcher === 'undefined') {
  1497. - this.dispatcher || (this.dispatcher = new Batman.Dispatcher(this));
  1498. }
  1499. - if (typeof this.layout === 'undefined') {
  1500. - this.set('layout', new Batman.View({
  1501. contexts: [this],
  1502. node: document
  1503. }));
  1504. }
  1505. - if (typeof this.historyManager === 'undefined' && this.dispatcher.routeMap) {
  1506. - this.historyManager = Batman.historyManager = new Batman.HashHistory(this);
  1507. - this.historyManager.start();
  1508. }
  1509. - this.hasRun = true;
  1510. - return this;
  1511. });
  1512. + App.stop = App.eventOneShot(function() {
  1513. - var _ref2;
  1514. - if ((_ref2 = this.historyManager) != null) {
  1515. - _ref2.stop();
  1516. }
  1517. - Batman.historyManager = null;
  1518. - this.hasRun = false;
  1519. - return this;
  1520. });
  1521. + return App;
  1522. })();
  1523. + Batman.Route = (function() {
  1524. + var escapeRegExp, namedOrSplat, namedParam, queryParam, splatParam;
  1525. + __extends(Route, Batman.Object);
  1526. + namedParam = /:([\w\d]+)/g;
  1527. + splatParam = /\*([\w\d]+)/g;
  1528. + queryParam = '(?:\\?.+)?';
  1529. + namedOrSplat = /[:|\*]([\w\d]+)/g;
  1530. + escapeRegExp = /[-[\]{}()+?.,\\^$|#\s]/g;
  1531. + function Route() {
  1532. - var array;
  1533. - Route.__super__.constructor.apply(this, arguments);
  1534. - this.pattern = this.url.replace(escapeRegExp, '\\$&');
  1535. - this.regexp = new RegExp('^' + this.pattern.replace(namedParam, '([^\/]*)').replace(splatParam, '(.*?)') + queryParam + '$');
  1536. - this.namedArguments = [];
  1537. - while ((array = namedOrSplat.exec(this.pattern)) != null) {
  1538. - if (array[1]) {
  1539. - this.namedArguments.push(array[1]);
  1540. }
  1541. }
  1542. }
  1543. + Route.accessor('action', {
  1544. get: function() {
  1545. - var components, result, signature;
  1546. - if (this.action) {
  1547. - return this.action;
  1548. }
  1549. - if (this.options) {
  1550. - result = $mixin({}, this.options);
  1551. - if (signature = result.signature) {
  1552. - components = signature.split('#');
  1553. - result.controller = components[0];
  1554. - result.action = components[1] || 'index';
  1555. }
  1556. - result.target = this.dispatcher.get(result.controller);
  1557. - return this.set('action', result);
  1558. }
  1559. },
  1560. set: function(key, action) {
  1561. - return this.action = action;
  1562. }
  1563. });
  1564. + Route.prototype.parameterize = function(url) {
  1565. - var action, array, index, key, param, params, query, s, value, _j, _len2, _len3, _ref2, _ref3, _ref4, _ref5;
  1566. - _ref2 = url.split('?'), url = _ref2[0], query = _ref2[1];
  1567. - array = (_ref3 = this.regexp.exec(url)) != null ? _ref3.slice(1) : void 0;
  1568. - params = {
  1569. url: url
  1570. };
  1571. - action = this.get('action');
  1572. - if (typeof action === 'function') {
  1573. - params.action = action;
  1574. } else {
  1575. - $mixin(params, action);
  1576. }
  1577. - if (array) {
  1578. - for (index = 0, _len2 = array.length; index < _len2; index++) {
  1579. - param = array[index];
  1580. - params[this.namedArguments[index]] = param;
  1581. }
  1582. }
  1583. - if (query) {
  1584. - _ref4 = query.split('&');
  1585. - for (_j = 0, _len3 = _ref4.length; _j < _len3; _j++) {
  1586. - s = _ref4[_j];
  1587. - _ref5 = s.split('='), key = _ref5[0], value = _ref5[1];
  1588. - params[key] = value;
  1589. }
  1590. }
  1591. - return params;
  1592. };
  1593. + Route.prototype.dispatch = function(url) {
  1594. - var action, params, _ref2, _ref3;
  1595. - if ($typeOf(url) === 'String') {
  1596. - params = this.parameterize(url);
  1597. }
  1598. - if (!(action = params.action) && url !== '/404') {
  1599. - $redirect('/404');
  1600. }
  1601. - if (typeof action === 'function') {
  1602. - return action(params);
  1603. }
  1604. - if ((_ref2 = params.target) != null ? _ref2.dispatch : void 0) {
  1605. - return params.target.dispatch(action, params);
  1606. }
  1607. - return (_ref3 = params.target) != null ? _ref3[action](params) : void 0;
  1608. };
  1609. + return Route;
  1610. })();
  1611. + Batman.Dispatcher = (function() {
  1612. + __extends(Dispatcher, Batman.Object);
  1613. + function Dispatcher(app) {
  1614. - var controller, key, _ref2;
  1615. - this.app = app;
  1616. - this.app.route(this);
  1617. - this.app.controllers = new Batman.Object;
  1618. - _ref2 = this.app;
  1619. - for (key in _ref2) {
  1620. - controller = _ref2[key];
  1621. - if (!((controller != null ? controller.prototype : void 0) instanceof Batman.Controller)) {
  1622. - continue;
  1623. }
  1624. - this.prepareController(controller);
  1625. }
  1626. }
  1627. + Dispatcher.prototype.prepareController = function(controller) {
  1628. - var getter, name;
  1629. - name = helpers.underscore(controller.name.replace('Controller', ''));
  1630. - if (!name) {
  1631. - return;
  1632. }
  1633. - getter = function() {
  1634. - return this[name] = controller.get('sharedController');
  1635. };
  1636. - this.accessor(name, getter);
  1637. - return this.app.controllers.accessor(name, getter);
  1638. };
  1639. + Dispatcher.prototype.register = function(url, options) {
  1640. - var route;
  1641. - if (url.indexOf('/') !== 0) {
  1642. - url = "/" + url;
  1643. }
  1644. - route = $typeOf(options) === 'Function' ? new Batman.Route({
  1645. url: url,
  1646. action: options,
  1647. dispatcher: this
  1648. }) : new Batman.Route({
  1649. url: url,
  1650. options: options,
  1651. dispatcher: this
  1652. });
  1653. - this.routeMap || (this.routeMap = {});
  1654. - return this.routeMap[url] = route;
  1655. };
  1656. + Dispatcher.prototype.findRoute = function(url) {
  1657. - var route, routeUrl, _ref2;
  1658. - if (url.indexOf('/') !== 0) {
  1659. - url = "/" + url;
  1660. }
  1661. - if ((route = this.routeMap[url])) {
  1662. - return route;
  1663. }
  1664. - _ref2 = this.routeMap;
  1665. - for (routeUrl in _ref2) {
  1666. - route = _ref2[routeUrl];
  1667. - if (route.regexp.test(url)) {
  1668. - return route;
  1669. }
  1670. }
  1671. };
  1672. + Dispatcher.prototype.findUrl = function(params) {
  1673. - var action, controller, key, matches, options, route, url, value, _ref2, _ref3;
  1674. - _ref2 = this.routeMap;
  1675. - for (url in _ref2) {
  1676. - route = _ref2[url];
  1677. - matches = false;
  1678. - options = route.options;
  1679. - if (params.resource) {
  1680. - matches = options.resource === params.resource && options.action === params.action;
  1681. } else {
  1682. - action = route.get('action');
  1683. - if (typeof action === 'function') {
  1684. - continue;
  1685. }
  1686. - _ref3 = action, controller = _ref3.controller, action = _ref3.action;
  1687. - if (controller === params.controller && action === (params.action || 'index')) {
  1688. - matches = true;
  1689. }
  1690. }
  1691. - if (!matches) {
  1692. - continue;
  1693. }
  1694. - for (key in params) {
  1695. - value = params[key];
  1696. - url = url.replace(new RegExp('[:|\*]' + key), value);
  1697. }
  1698. - return url;
  1699. }
  1700. };
  1701. + Dispatcher.prototype.dispatch = function(url) {
  1702. - var route;
  1703. - route = this.findRoute(url);
  1704. - if (route) {
  1705. - route.dispatch(url);
  1706. - } else if (url !== '/404') {
  1707. - $redirect('/404');
  1708. }
  1709. - return this.app.set('currentURL', url);
  1710. };
  1711. + return Dispatcher;
  1712. })();
  1713. + Batman.HistoryManager = (function() {
  1714. + function HistoryManager(app) {
  1715. + this.app = app;
  1716. }
  1717. + HistoryManager.prototype.dispatch = function(url) {
  1718. - if (url.indexOf('/') !== 0) {
  1719. - url = "/" + url;
  1720. }
  1721. - this.app.dispatcher.dispatch(url);
  1722. - return url;
  1723. };
  1724. + HistoryManager.prototype.redirect = function(url) {
  1725. - if ($typeOf(url) !== 'String') {
  1726. - url = this.app.dispatcher.findUrl(url);
  1727. }
  1728. - return this.dispatch(url);
  1729. };
  1730. + return HistoryManager;
  1731. })();
  1732. + Batman.HashHistory = (function() {
  1733. + __extends(HashHistory, Batman.HistoryManager);
  1734. + function HashHistory() {
  1735. + this.parseHash = __bind(this.parseHash, this);
  1736. + this.stop = __bind(this.stop, this);
  1737. + this.start = __bind(this.start, this);
  1738. + HashHistory.__super__.constructor.apply(this, arguments);
  1739. }
  1740. + HashHistory.prototype.HASH_PREFIX = '#!';
  1741. + HashHistory.prototype.start = function() {
  1742. - if (typeof window === 'undefined') {
  1743. - return;
  1744. }
  1745. - if (this.started) {
  1746. - return;
  1747. }
  1748. - this.started = true;
  1749. - if ('onhashchange' in window) {
  1750. - window.addEventListener('hashchange', this.parseHash, false);
  1751. } else {
  1752. - this.interval = setInterval(this.parseHash, 100);
  1753. }
  1754. - return setTimeout(this.parseHash, 0);
  1755. };
  1756. + HashHistory.prototype.stop = function() {
  1757. - if (this.interval) {
  1758. - this.interval = clearInterval(this.interval);
  1759. } else {
  1760. - window.removeEventListener('hashchange', this.parseHash, false);
  1761. }
  1762. - return this.started = false;
  1763. };
  1764. + HashHistory.prototype.urlFor = function(url) {
  1765. + return this.HASH_PREFIX + url;
  1766. };
  1767. + HashHistory.prototype.parseHash = function() {
  1768. - var hash;
  1769. - hash = window.location.hash.replace(this.HASH_PREFIX, '');
  1770. - if (hash === this.cachedHash) {
  1771. - return;
  1772. }
  1773. - return this.dispatch((this.cachedHash = hash));
  1774. };
  1775. + HashHistory.prototype.redirect = function(params) {
  1776. - var url;
  1777. - url = HashHistory.__super__.redirect.apply(this, arguments);
  1778. - this.cachedHash = url;
  1779. - return window.location.hash = this.HASH_PREFIX + url;
  1780. };
  1781. + return HashHistory;
  1782. })();
  1783. + Batman.redirect = $redirect = function(url) {
  1784. + var _ref2;
  1785. + return (_ref2 = Batman.historyManager) != null ? _ref2.redirect(url) : void 0;
  1786. };
  1787. + Batman.App.classMixin({
  1788. route: function(url, signature, options) {
  1789. - var dispatcher, key, value, _ref2;
  1790. - if (options == null) {
  1791. - options = {};
  1792. }
  1793. - if (!url) {
  1794. - return;
  1795. }
  1796. - if (url instanceof Batman.Dispatcher) {
  1797. - dispatcher = url;
  1798. - _ref2 = this._dispatcherCache;
  1799. - for (key in _ref2) {
  1800. - value = _ref2[key];
  1801. - dispatcher.register(key, value);
  1802. }
  1803. - this._dispatcherCache = null;
  1804. - return dispatcher;
  1805. }
  1806. - if ($typeOf(signature) === 'String') {
  1807. - options.signature = signature;
  1808. - } else if ($typeOf(signature) === 'Function') {
  1809. - options = signature;
  1810. - } else if (signature) {
  1811. - $mixin(options, signature);
  1812. }
  1813. - this._dispatcherCache || (this._dispatcherCache = {});
  1814. - return this._dispatcherCache[url] = options;
  1815. },
  1816. root: function(signature, options) {
  1817. - return this.route('/', signature, options);
  1818. },
  1819. resources: function(resource, options, callback) {
  1820. - var app, controller, ops;
  1821. - if (typeof options === 'function') {
  1822. - callback = options;
  1823. - options = null;
  1824. }
  1825. - resource = helpers.pluralize(resource);
  1826. - controller = (options != null ? options.controller : void 0) || resource;
  1827. - this.route(resource, "" + controller + "#index", {
  1828. resource: controller,
  1829. action: 'index'
  1830. });
  1831. - this.route("" + resource + "/:id", "" + controller + "#show", {
  1832. resource: controller,
  1833. action: 'show'
  1834. });
  1835. - this.route("" + resource + "/:id/edit", "" + controller + "#edit", {
  1836. resource: controller,
  1837. action: 'edit'
  1838. });
  1839. - this.route("" + resource + "/:id/destroy", "" + controller + "#destroy", {
  1840. resource: controller,
  1841. action: 'destroy'
  1842. });
  1843. - if (callback) {
  1844. - app = this;
  1845. - ops = {
  1846. collection: function(collectionCallback) {
  1847. - return collectionCallback != null ? collectionCallback.call({
  1848. route: function(url, methodName) {
  1849. - return app.route("" + resource + "/" + url, "" + controller + "#" + (methodName || url));
  1850. }
  1851. }) : void 0;
  1852. },
  1853. member: function(memberCallback) {
  1854. - return memberCallback != null ? memberCallback.call({
  1855. route: function(url, methodName) {
  1856. - return app.route("" + resource + "/:id/" + url, "" + controller + "#" + (methodName || url));
  1857. }
  1858. }) : void 0;
  1859. }
  1860. };
  1861. - return callback.call(ops);
  1862. }
  1863. },
  1864. redirect: $redirect
  1865. });
  1866. + Batman.Controller = (function() {
  1867. + __extends(Controller, Batman.Object);
  1868. + function Controller() {
  1869. + this.redirect = __bind(this.redirect, this);
  1870. + Controller.__super__.constructor.apply(this, arguments);
  1871. }
  1872. + Controller.singleton('sharedController');
  1873. + Controller.beforeFilter = function(nameOrFunction) {
  1874. - var filters, _base;
  1875. - Batman.initializeObject(this);
  1876. - filters = (_base = this._batman).beforeFilters || (_base.beforeFilters = []);
  1877. - if (filters.indexOf(nameOrFunction) === -1) {
  1878. - return filters.push(nameOrFunction);
  1879. }
  1880. };
  1881. + Controller.accessor('controllerName', {
  1882. get: function() {
  1883. + return this._controllerName || (this._controllerName = helpers.underscore(this.constructor.name.replace('Controller', '')));
  1884. }
  1885. });
  1886. + Controller.accessor('action', {
  1887. get: function() {
  1888. + return this._currentAction;
  1889. },
  1890. set: function(key, value) {
  1891. + return this._currentAction = value;
  1892. }
  1893. });
  1894. + Controller.prototype.dispatch = function(action, params) {
  1895. + var filter, filters, oldRedirect, _j, _k, _len2, _len3, _ref2, _ref3, _ref4, _ref5, _ref6;
  1896. + if (params == null) {
  1897. + params = {};
  1898. }
  1899. + params.controller || (params.controller = this.get('controllerName'));
  1900. + params.action || (params.action = action);
  1901. + params.target || (params.target = this);
  1902. + oldRedirect = (_ref2 = Batman.historyManager) != null ? _ref2.redirect : void 0;
  1903. + if ((_ref3 = Batman.historyManager) != null) {
  1904. + _ref3.redirect = this.redirect;
  1905. }
  1906. + this._actedDuringAction = false;
  1907. + this.set('action', action);
  1908. + if (filters = (_ref4 = this.constructor._batman) != null ? _ref4.get('beforeFilters') : void 0) {
  1909. - for (_j = 0, _len2 = filters.length; _j < _len2; _j++) {
  1910. - filter = filters[_j];
  1911. - if (typeof filter === 'function') {
  1912. - filter.call(this, params);
  1913. } else {
  1914. - this[filter](params);
  1915. }
  1916. }
  1917. }
  1918. + this[action](params);
  1919. + if (!this._actedDuringAction) {
  1920. + this.render();
  1921. }
  1922. + if (filters = (_ref5 = this.constructor._batman) != null ? _ref5.get('afterFilters') : void 0) {
  1923. - for (_k = 0, _len3 = filters.length; _k < _len3; _k++) {
  1924. - filter = filters[_k];
  1925. - if (typeof filter === 'function') {
  1926. - filter.call(this, params);
  1927. } else {
  1928. - this[filter](params);
  1929. }
  1930. }
  1931. }
  1932. + delete this._actedDuringAction;
  1933. + this.set('action', null);
  1934. + if ((_ref6 = Batman.historyManager) != null) {
  1935. + _ref6.redirect = oldRedirect;
  1936. }
  1937. + if (this._afterFilterRedirect) {
  1938. + $redirect(this._afterFilterRedirect);
  1939. }
  1940. + return delete this._afterFilterRedirect;
  1941. };
  1942. + Controller.prototype.redirect = function(url) {
  1943. + if (this._actedDuringAction) {
  1944. - throw 'DoubleRedirectError';
  1945. }
  1946. + if (this.get('action')) {
  1947. + this._actedDuringAction = true;
  1948. + return this._afterFilterRedirect = url;
  1949. } else {
  1950. - if ($typeOf(url) === 'Object') {
  1951. - if (!url.controller) {
  1952. - url.controller = this;
  1953. }
  1954. }
  1955. - return $redirect(url);
  1956. }
  1957. };
  1958. + Controller.prototype.render = function(options) {
  1959. + var view;
  1960. + if (options == null) {
  1961. + options = {};
  1962. }
  1963. + if (this._actedDuringAction) {
  1964. - throw 'DoubleRenderError';
  1965. }
  1966. + this._actedDuringAction = true;
  1967. + if (options === false) {
  1968. + return;
  1969. }
  1970. + if (!options.view) {
  1971. + options.source = helpers.underscore(this.constructor.name.replace('Controller', '')) + '/' + this._currentAction + '.html';
  1972. + options.view = new Batman.View(options);
  1973. }
  1974. + if (view = options.view) {
  1975. + view.contexts.push(this);
  1976. + return view.ready(function() {
  1977. + return Batman.DOM.contentFor('main', view.get('node'));
  1978. });
  1979. }
  1980. };
  1981. + return Controller;
  1982. })();
  1983. + Batman.Model = (function() {
  1984. + var k, _j, _k, _len2, _len3, _ref2, _ref3;
  1985. + __extends(Model, Batman.Object);
  1986. + Model.primaryKey = 'id';
  1987. + Model.persist = function() {
  1988. + var mechanism, mechanisms, storage, _base, _j, _len2;
  1989. + mechanisms = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
  1990. + Batman.initializeObject(this.prototype);
  1991. + storage = (_base = this.prototype._batman).storage || (_base.storage = []);
  1992. + for (_j = 0, _len2 = mechanisms.length; _j < _len2; _j++) {
  1993. + mechanism = mechanisms[_j];
  1994. + storage.push(mechanism.isStorageAdapter ? mechanism : new mechanism(this));
  1995. }
  1996. + return this;
  1997. };
  1998. + Model.encode = function() {
  1999. + var decoder, encoder, encoderOrLastKey, key, keys, _base, _base2, _j, _k, _len2, _results;
  2000. + keys = 2 <= arguments.length ? __slice.call(arguments, 0, _j = arguments.length - 1) : (_j = 0, []), encoderOrLastKey = arguments[_j++];
  2001. + Batman.initializeObject(this.prototype);
  2002. + (_base = this.prototype._batman).encoders || (_base.encoders = new Batman.SimpleHash);
  2003. + (_base2 = this.prototype._batman).decoders || (_base2.decoders = new Batman.SimpleHash);
  2004. + switch ($typeOf(encoderOrLastKey)) {
  2005. case 'String':
  2006. + keys.push(encoderOrLastKey);
  2007. + break;
  2008. case 'Function':
  2009. + encoder = encoderOrLastKey;
  2010. + break;
  2011. default:
  2012. + encoder = encoderOrLastKey.encode;
  2013. + decoder = encoderOrLastKey.decode;
  2014. }
  2015. + _results = [];
  2016. + for (_k = 0, _len2 = keys.length; _k < _len2; _k++) {
  2017. + key = keys[_k];
  2018. + this.prototype._batman.encoders.set(key, encoder || this.defaultEncoder.encode);
  2019. + _results.push(this.prototype._batman.decoders.set(key, decoder || this.defaultEncoder.decode));
  2020. }
  2021. + return _results;
  2022. };
  2023. + Model.defaultEncoder = {
  2024. encode: function(x) {
  2025. + return x;
  2026. },
  2027. decode: function(x) {
  2028. + return x;
  2029. }
  2030. };
  2031. + Model.observe('primaryKey', true, function(newPrimaryKey) {
  2032. + return this.encode(newPrimaryKey, this.defaultEncoder);
  2033. });
  2034. + Model.validate = function() {
  2035. + var keys, match, matches, options, optionsOrFunction, validator, validators, _base, _j, _k, _len2, _results;
  2036. + keys = 2 <= arguments.length ? __slice.call(arguments, 0, _j = arguments.length - 1) : (_j = 0, []), optionsOrFunction = arguments[_j++];
  2037. + Batman.initializeObject(this.prototype);
  2038. + validators = (_base = this.prototype._batman).validators || (_base.validators = []);
  2039. + if (typeof optionsOrFunction === 'function') {
  2040. + return validators.push({
  2041. keys: keys,
  2042. callback: optionsOrFunction
  2043. });
  2044. } else {
  2045. + options = optionsOrFunction;
  2046. + _results = [];
  2047. + for (_k = 0, _len2 = Validators.length; _k < _len2; _k++) {
  2048. + validator = Validators[_k];
  2049. + _results.push((function() {
  2050. + var _l, _len3;
  2051. + if ((matches = validator.matches(options))) {
  2052. + for (_l = 0, _len3 = matches.length; _l < _len3; _l++) {
  2053. + match = matches[_l];
  2054. + delete options[match];
  2055. }
  2056. + return validators.push({
  2057. keys: keys,
  2058. validator: new validator(matches)
  2059. });
  2060. }
  2061. })());
  2062. }
  2063. + return _results;
  2064. }
  2065. };
  2066. + Model.classAccessor('all', {
  2067. get: function() {
  2068. + if (!this.all) {
  2069. + this.all = new Batman.SortableSet;
  2070. + this.all.sortBy("id asc");
  2071. }
  2072. + return this.all;
  2073. },
  2074. set: function(k, v) {
  2075. - return this.all = v;
  2076. }
  2077. });
  2078. + Model.classAccessor('first', function() {
  2079. - return this.get('all').toArray()[0];
  2080. });
  2081. + Model.classAccessor('last', function() {
  2082. - var x;
  2083. - x = this.get('all').toArray();
  2084. - return x[x.length - 1];
  2085. });
  2086. + Model.find = function(id, callback) {
  2087. + var newRecord, record;
  2088. + if (!callback) {
  2089. + throw "missing callback";
  2090. }
  2091. + record = new this(id);
  2092. + newRecord = this._mapIdentities([record])[0];
  2093. + newRecord.load(callback);
  2094. };
  2095. + Model.load = function(options, callback) {
  2096. + if ($typeOf(options) === 'Function') {
  2097. + callback = options;
  2098. + options = {};
  2099. }
  2100. + if (!(this.prototype._batman.getAll('storage').length > 0)) {
  2101. + throw new Error("Can't load model " + this.name + " without any storage adapters!");
  2102. }
  2103. + this.loading();
  2104. + return this.prototype._doStorageOperation('readAll', options, __bind(function(err, records) {
  2105. + if (err != null) {
  2106. - return typeof callback === "function" ? callback(err, []) : void 0;
  2107. } else {
  2108. + records = this._mapIdentities(records);
  2109. + this.loaded();
  2110. + return typeof callback === "function" ? callback(err, records) : void 0;
  2111. }
  2112. }, this));
  2113. };
  2114. + Model._mapIdentities = function(records) {
  2115. + var all, existingRecord, id, newRecords, potential, record, returnRecords, _j, _k, _len2, _len3, _ref2;
  2116. + all = this.get('all').toArray();
  2117. + newRecords = [];
  2118. + returnRecords = [];
  2119. + for (_j = 0, _len2 = records.length; _j < _len2; _j++) {
  2120. + record = records[_j];
  2121. + if (typeof record === 'undefined') {
  2122. + continue;
  2123. }
  2124. + if (typeof (id = record.get('id')) === 'undefined' || id === '') {
  2125. - returnRecords.push(record);
  2126. } else {
  2127. + existingRecord = false;
  2128. + for (_k = 0, _len3 = all.length; _k < _len3; _k++) {
  2129. + potential = all[_k];
  2130. + if (record.get('id') === potential.get('id')) {
  2131. + existingRecord = potential;
  2132. + break;
  2133. }
  2134. }
  2135. + if (existingRecord) {
  2136. + returnRecords.push(existingRecord);
  2137. } else {
  2138. + newRecords.push(record);
  2139. + returnRecords.push(record);
  2140. }
  2141. }
  2142. }
  2143. + if (newRecords.length > 0) {
  2144. + (_ref2 = this.get('all')).add.apply(_ref2, newRecords);
  2145. }
  2146. + return returnRecords;
  2147. };
  2148. + Model.accessor('id', {
  2149. get: function() {
  2150. + var pk;
  2151. + pk = this.constructor.get('primaryKey');
  2152. + if (pk === 'id') {
  2153. + return this.id;
  2154. } else {
  2155. + return this.get(pk);
  2156. }
  2157. },
  2158. set: function(k, v) {
  2159. + var pk;
  2160. + pk = this.constructor.get('primaryKey');
  2161. + if (pk === 'id') {
  2162. + return this.id = v;
  2163. } else {
  2164. - return this.set(pk, v);
  2165. }
  2166. }
  2167. });
  2168. + function Model(idOrAttributes) {
  2169. + if (idOrAttributes == null) {
  2170. + idOrAttributes = {};
  2171. }
  2172. + this.destroy = __bind(this.destroy, this);
  2173. + this.save = __bind(this.save, this);
  2174. + this.load = __bind(this.load, this);
  2175. + if (!(this instanceof Batman.Object)) {
  2176. + throw "constructors must be called with new";
  2177. }
  2178. + this.dirtyKeys = new Batman.Hash;
  2179. + this.errors = new Batman.ErrorsHash;
  2180. + if ($typeOf(idOrAttributes) === 'Object') {
  2181. + Model.__super__.constructor.call(this, idOrAttributes);
  2182. } else {
  2183. + Model.__super__.constructor.call(this);
  2184. + this.set('id', idOrAttributes);
  2185. }
  2186. + if (!this.state()) {
  2187. + this.empty();
  2188. }
  2189. }
  2190. + Model.prototype.set = function(key, value) {
  2191. + var oldValue, result, _ref2;
  2192. + oldValue = this.get(key);
  2193. + if (oldValue === value) {
  2194. + return;
  2195. }
  2196. + result = Model.__super__.set.apply(this, arguments);
  2197. + this.dirtyKeys.set(key, oldValue);
  2198. + if ((_ref2 = this.state()) !== 'dirty' && _ref2 !== 'loading' && _ref2 !== 'creating') {
  2199. + this.dirty();
  2200. }
  2201. + return result;
  2202. };
  2203. + Model.prototype.toString = function() {
  2204. + return "" + this.constructor.name + ": " + (this.get('id'));
  2205. };
  2206. + Model.prototype.toJSON = function() {
  2207. + var encoders, obj;
  2208. + obj = {};
  2209. + encoders = this._batman.get('encoders');
  2210. + if (!(!encoders || encoders.isEmpty())) {
  2211. + encoders.forEach(__bind(function(key, encoder) {
  2212. + var encodedVal, val;
  2213. + val = this.get(key);
  2214. + if (typeof val !== 'undefined') {
  2215. + encodedVal = encoder(this.get(key));
  2216. + if (typeof encodedVal !== 'undefined') {
  2217. + return obj[key] = encodedVal;
  2218. }
  2219. }
  2220. }, this));
  2221. }
  2222. + return obj;
  2223. };
  2224. + Model.prototype.fromJSON = function(data) {
  2225. + var decoders, key, obj, value;
  2226. + obj = {};
  2227. + decoders = this._batman.get('decoders');
  2228. + if (!decoders || decoders.isEmpty()) {
  2229. + for (key in data) {
  2230. + value = data[key];
  2231. + obj[key] = value;
  2232. }
  2233. } else {
  2234. + decoders.forEach(function(key, decoder) {
  2235. + return obj[key] = decoder(data[key]);
  2236. });
  2237. }
  2238. + return this.mixin(obj);
  2239. };
  2240. + Model.actsAsStateMachine(true);
  2241. + _ref2 = ['empty', 'dirty', 'loading', 'loaded', 'saving', 'saved', 'creating', 'created', 'validating', 'validated', 'destroying', 'destroyed'];
  2242. + for (_j = 0, _len2 = _ref2.length; _j < _len2; _j++) {
  2243. + k = _ref2[_j];
  2244. + Model.state(k);
  2245. }
  2246. + _ref3 = ['loading', 'loaded'];
  2247. + for (_k = 0, _len3 = _ref3.length; _k < _len3; _k++) {
  2248. + k = _ref3[_k];
  2249. + Model.classState(k);
  2250. }
  2251. + Model.prototype._doStorageOperation = function(operation, options, callback) {
  2252. + var mechanism, mechanisms, _l, _len4;
  2253. + mechanisms = this._batman.get('storage') || [];
  2254. + if (!(mechanisms.length > 0)) {
  2255. - throw new Error("Can't " + operation + " model " + this.constructor.name + " without any storage adapters!");
  2256. }
  2257. + for (_l = 0, _len4 = mechanisms.length; _l < _len4; _l++) {
  2258. + mechanism = mechanisms[_l];
  2259. + mechanism[operation](this, options, callback);
  2260. }
  2261. + return true;
  2262. };
  2263. + Model.prototype._hasStorage = function() {
  2264. - return this._batman.getAll('storage').length > 0;
  2265. };
  2266. + Model.prototype.load = function(callback) {
  2267. + var _ref4;
  2268. + if ((_ref4 = this.get('state')) === 'destroying' || _ref4 === 'destroyed') {
  2269. - if (typeof callback === "function") {
  2270. - callback(new Error("Can't load a destroyed record!"));
  2271. }
  2272. - return;
  2273. }
  2274. + this.loading();
  2275. + return this._doStorageOperation('read', {}, __bind(function(err, record) {
  2276. + if (!err) {
  2277. + this.loaded();
  2278. }
  2279. + record = this.constructor._mapIdentities([record])[0];
  2280. + return typeof callback === "function" ? callback(err, record) : void 0;
  2281. }, this));
  2282. };
  2283. + Model.prototype.save = function(callback) {
  2284. + var _ref4;
  2285. + if ((_ref4 = this.get('state')) === 'destroying' || _ref4 === 'destroyed') {
  2286. + if (typeof callback === "function") {
  2287. + callback(new Error("Can't save a destroyed record!"));
  2288. }
  2289. + return;
  2290. }
  2291. + return this.validate(__bind(function(isValid, errors) {
  2292. + var creating;
  2293. + if (!isValid) {
  2294. + if (typeof callback === "function") {
  2295. + callback(errors);
  2296. }
  2297. + return;
  2298. }
  2299. + creating = this.isNew();
  2300. + this.saving();
  2301. + if (creating) {
  2302. + this.creating();
  2303. }
  2304. + return this._doStorageOperation((creating ? 'create' : 'update'), {}, __bind(function(err, record) {
  2305. + if (!err) {
  2306. + if (creating) {
  2307. + this.created();
  2308. }
  2309. + this.saved();
  2310. + this.dirtyKeys.clear();
  2311. }
  2312. + record = this.constructor._mapIdentities([record])[0];
  2313. + return typeof callback === "function" ? callback(err, record) : void 0;
  2314. }, this));
  2315. }, this));
  2316. };
  2317. + Model.prototype.destroy = function(callback) {
  2318. + this.destroying();
  2319. + return this._doStorageOperation('destroy', {}, __bind(function(err, record) {
  2320. + if (!err) {
  2321. + this.constructor.get('all').remove(this);
  2322. + this.destroyed();
  2323. }
  2324. + return typeof callback === "function" ? callback(err) : void 0;
  2325. }, this));
  2326. };
  2327. + Model.prototype.validate = function(callback) {
  2328. + var count, finish, key, oldState, v, validationCallback, validator, validators, _l, _len4, _len5, _m, _ref4;
  2329. + oldState = this.state();
  2330. + this.errors.clear();
  2331. + this.validating();
  2332. + finish = __bind(function() {
  2333. + this.validated();
  2334. + this[oldState]();
  2335. + return typeof callback === "function" ? callback(this.errors.length === 0, this.errors) : void 0;
  2336. }, this);
  2337. + validators = this._batman.get('validators') || [];
  2338. + if (!(validators.length > 0)) {
  2339. + finish();
  2340. } else {
  2341. + count = validators.length;
  2342. + validationCallback = __bind(function() {
  2343. + if (--count === 0) {
  2344. + return finish();
  2345. }
  2346. }, this);
  2347. + for (_l = 0, _len4 = validators.length; _l < _len4; _l++) {
  2348. + validator = validators[_l];
  2349. + v = validator.validator;
  2350. + _ref4 = validator.keys;
  2351. + for (_m = 0, _len5 = _ref4.length; _m < _len5; _m++) {
  2352. + key = _ref4[_m];
  2353. + if (v) {
  2354. + v.validateEach(this.errors, this, key, validationCallback);
  2355. } else {
  2356. + validator.callback(this.errors, this, key, validationCallback);
  2357. }
  2358. }
  2359. }
  2360. }
  2361. };
  2362. + Model.prototype.isNew = function() {
  2363. + return typeof this.get('id') === 'undefined';
  2364. };
  2365. + return Model;
  2366. })();
  2367. + Batman.ErrorsHash = (function() {
  2368. + __extends(ErrorsHash, Batman.Hash);
  2369. + function ErrorsHash() {
  2370. + ErrorsHash.__super__.constructor.call(this, {
  2371. _sets: {}
  2372. });
  2373. }
  2374. + ErrorsHash.accessor({
  2375. get: function(key) {
  2376. + if (!this._sets[key]) {
  2377. + this._sets[key] = new Batman.Set;
  2378. + this.length++;
  2379. }
  2380. + return this._sets[key];
  2381. },
  2382. set: Batman.Property.defaultAccessor.set
  2383. });
  2384. + ErrorsHash.prototype.add = function(key, error) {
  2385. + return this.get(key).add(error);
  2386. };
  2387. + ErrorsHash.prototype.clear = function() {
  2388. + this._sets = {};
  2389. + return ErrorsHash.__super__.clear.apply(this, arguments);
  2390. };
  2391. + return ErrorsHash;
  2392. })();
  2393. + Batman.Validator = (function() {
  2394. + __extends(Validator, Batman.Object);
  2395. + function Validator() {
  2396. + var mixins, options;
  2397. + options = arguments[0], mixins = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
  2398. + this.options = options;
  2399. + Validator.__super__.constructor.apply(this, mixins);
  2400. }
  2401. + Validator.prototype.validate = function(record) {
  2402. - throw "You must override validate in Batman.Validator subclasses.";
  2403. };
  2404. + Validator.options = function() {
  2405. + var options;
  2406. + options = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
  2407. + Batman.initializeObject(this);
  2408. + if (this._batman.options) {
  2409. - return this._batman.options.concat(options);
  2410. } else {
  2411. + return this._batman.options = options;
  2412. }
  2413. };
  2414. + Validator.matches = function(options) {
  2415. + var key, results, shouldReturn, value, _ref2, _ref3;
  2416. + results = {};
  2417. + shouldReturn = false;
  2418. + for (key in options) {
  2419. + value = options[key];
  2420. + if (~((_ref2 = this._batman) != null ? (_ref3 = _ref2.options) != null ? _ref3.indexOf(key) : void 0 : void 0)) {
  2421. + results[key] = value;
  2422. + shouldReturn = true;
  2423. }
  2424. }
  2425. + if (shouldReturn) {
  2426. + return results;
  2427. }
  2428. };
  2429. + return Validator;
  2430. })();
  2431. + Validators = Batman.Validators = [
  2432. Batman.LengthValidator = (function() {
  2433. + __extends(LengthValidator, Batman.Validator);
  2434. + LengthValidator.options('minLength', 'maxLength', 'length', 'lengthWithin', 'lengthIn');
  2435. + function LengthValidator(options) {
  2436. + var range;
  2437. + if (range = options.lengthIn || options.lengthWithin) {
  2438. + options.minLength = range[0];
  2439. + options.maxLength = range[1] || -1;
  2440. + delete options.lengthWithin;
  2441. + delete options.lengthIn;
  2442. }
  2443. + LengthValidator.__super__.constructor.apply(this, arguments);
  2444. }
  2445. + LengthValidator.prototype.validateEach = function(errors, record, key, callback) {
  2446. + var options, value;
  2447. + options = this.options;
  2448. + value = record.get(key);
  2449. + if (options.minLength && value.length < options.minLength) {
  2450. + errors.add(key, "" + key + " must be at least " + options.minLength + " characters");
  2451. }
  2452. + if (options.maxLength && value.length > options.maxLength) {
  2453. + errors.add(key, "" + key + " must be less than " + options.maxLength + " characters");
  2454. }
  2455. + if (options.length && value.length !== options.length) {
  2456. + errors.add(key, "" + key + " must be " + options.length + " characters");
  2457. }
  2458. + return callback();
  2459. };
  2460. + return LengthValidator;
  2461. })(), Batman.PresenceValidator = (function() {
  2462. + __extends(PresenceValidator, Batman.Validator);
  2463. + function PresenceValidator() {
  2464. + PresenceValidator.__super__.constructor.apply(this, arguments);
  2465. }
  2466. + PresenceValidator.options('presence');
  2467. + PresenceValidator.prototype.validateEach = function(errors, record, key, callback) {
  2468. + var value;
  2469. + value = record.get(key);
  2470. + if (this.options.presence && !(value != null)) {
  2471. + errors.add(key, "" + key + " must be present");
  2472. }
  2473. + return callback();
  2474. };
  2475. + return PresenceValidator;
  2476. })()
  2477. ];
  2478. + Batman.StorageAdapter = (function() {
  2479. + function StorageAdapter(model) {
  2480. + this.model = model;
  2481. + this.modelKey = helpers.pluralize(helpers.underscore(this.model.name));
  2482. }
  2483. + StorageAdapter.prototype.isStorageAdapter = true;
  2484. + StorageAdapter.prototype.getRecordsFromData = function(datas) {
  2485. + var data, _j, _len2, _results;
  2486. + if (this.transformCollectionData != null) {
  2487. + datas = this.transformCollectionData(datas);
  2488. }
  2489. + _results = [];
  2490. + for (_j = 0, _len2 = datas.length; _j < _len2; _j++) {
  2491. + data = datas[_j];
  2492. + _results.push(this.getRecordFromData(data));
  2493. }
  2494. + return _results;
  2495. };
  2496. + StorageAdapter.prototype.getRecordFromData = function(data) {
  2497. + var record;
  2498. + if (this.transformRecordData != null) {
  2499. + data = this.transformRecordData(data);
  2500. }
  2501. + record = new this.model();
  2502. + record.fromJSON(data);
  2503. + return record;
  2504. };
  2505. + return StorageAdapter;
  2506. })();
  2507. + Batman.LocalStorage = (function() {
  2508. + __extends(LocalStorage, Batman.StorageAdapter);
  2509. + function LocalStorage() {
  2510. - if (typeof window.localStorage === 'undefined') {
  2511. - return null;
  2512. }
  2513. - LocalStorage.__super__.constructor.apply(this, arguments);
  2514. - this.storage = localStorage;
  2515. - this.key_re = new RegExp("^" + this.modelKey + "(\\d+)$");
  2516. - this.nextId = 1;
  2517. - this._forAllRecords(function(k, v) {
  2518. - var matches;
  2519. - if (matches = this.key_re.exec(k)) {
  2520. - return this.nextId = Math.max(this.nextId, parseInt(matches[1], 10) + 1);
  2521. }
  2522. });
  2523. - return;
  2524. }
  2525. + LocalStorage.prototype._forAllRecords = function(f) {
  2526. - var i, _ref2, _results;
  2527. - _results = [];
  2528. - for (i = 0, _ref2 = this.storage.length; 0 <= _ref2 ? i < _ref2 : i > _ref2; 0 <= _ref2 ? i++ : i--) {
  2529. - k = this.storage.key(i);
  2530. - _results.push(f.call(this, k, this.storage.getItem(k)));
  2531. }
  2532. - return _results;
  2533. };
  2534. + LocalStorage.prototype.getRecordFromData = function(data) {
  2535. - var record;
  2536. - record = LocalStorage.__super__.getRecordFromData.apply(this, arguments);
  2537. - this.nextId = Math.max(this.nextId, parseInt(record.get('id'), 10) + 1);
  2538. - return record;
  2539. };
  2540. + LocalStorage.prototype.update = function(record, options, callback) {
  2541. - var id;
  2542. - id = record.get('id');
  2543. - if (id != null) {
  2544. - this.storage.setItem(this.modelKey + id, JSON.stringify(record));
  2545. - return callback(void 0, record);
  2546. } else {
  2547. - return callback(new Error("Couldn't get record primary key."));
  2548. }
  2549. };
  2550. + LocalStorage.prototype.create = function(record, options, callback) {
  2551. - var id, key;
  2552. - id = record.get('id') || record.set('id', this.nextId++);
  2553. - if (id != null) {
  2554. - key = this.modelKey + id;
  2555. - if (this.storage.getItem(key)) {
  2556. - return callback(new Error("Can't create because the record already exists!"));
  2557. } else {
  2558. - this.storage.setItem(key, JSON.stringify(record));
  2559. - return callback(void 0, record);
  2560. }
  2561. } else {
  2562. - return callback(new Error("Couldn't set record primary key on create!"));
  2563. }
  2564. };
  2565. + LocalStorage.prototype.read = function(record, options, callback) {
  2566. - var attrs, id;
  2567. - id = record.get('id');
  2568. - if (id != null) {
  2569. - attrs = JSON.parse(this.storage.getItem(this.modelKey + id));
  2570. - if (attrs) {
  2571. - record.fromJSON(attrs);
  2572. - return callback(void 0, record);
  2573. } else {
  2574. - return callback(new Error("Couldn't find record!"));
  2575. }
  2576. } else {
  2577. - return callback(new Error("Couldn't get record primary key."));
  2578. }
  2579. };
  2580. + LocalStorage.prototype.readAll = function(_, options, callback) {
  2581. - var records;
  2582. - records = [];
  2583. - this._forAllRecords(function(storageKey, data) {
  2584. - var k, keyMatches, match, v, _name;
  2585. - if (keyMatches = this.key_re.exec(storageKey)) {
  2586. - match = true;
  2587. - data = JSON.parse(data);
  2588. - data[_name = this.model.primaryKey] || (data[_name] = parseInt(keyMatches[1], 10));
  2589. - for (k in options) {
  2590. - v = options[k];
  2591. - if (data[k] !== v) {
  2592. - match = false;
  2593. - break;
  2594. }
  2595. }
  2596. - if (match) {
  2597. - return records.push(data);
  2598. }
  2599. }
  2600. });
  2601. - return callback(void 0, this.getRecordsFromData(records));
  2602. };
  2603. + LocalStorage.prototype.destroy = function(record, options, callback) {
  2604. - var id, key;
  2605. - id = record.get('id');
  2606. - if (id != null) {
  2607. - key = this.modelKey + id;
  2608. - if (this.storage.getItem(key)) {
  2609. - this.storage.removeItem(key);
  2610. - return callback(void 0, record);
  2611. } else {
  2612. - return callback(new Error("Can't delete nonexistant record!"), record);
  2613. }
  2614. } else {
  2615. - return callback(new Error("Can't delete record without an primary key!"), record);
  2616. }
  2617. };
  2618. + return LocalStorage;
  2619. })();
  2620. + Batman.RestStorage = (function() {
  2621. + __extends(RestStorage, Batman.StorageAdapter);
  2622. + RestStorage.prototype.defaultOptions = {
  2623. type: 'json'
  2624. };
  2625. + RestStorage.prototype.recordJsonNamespace = false;
  2626. + RestStorage.prototype.collectionJsonNamespace = false;
  2627. + function RestStorage() {
  2628. + RestStorage.__super__.constructor.apply(this, arguments);
  2629. + this.recordJsonNamespace = helpers.singularize(this.modelKey);
  2630. + this.collectionJsonNamespace = helpers.pluralize(this.modelKey);
  2631. + this.model.encode('id');
  2632. }
  2633. + RestStorage.prototype.transformRecordData = function(data) {
  2634. + if (data[this.recordJsonNamespace]) {
  2635. + return data[this.recordJsonNamespace];
  2636. }
  2637. + return data;
  2638. };
  2639. + RestStorage.prototype.transformCollectionData = function(data) {
  2640. + if (data[this.collectionJsonNamespace]) {
  2641. + return data[this.collectionJsonNamespace];
  2642. }
  2643. - return data;
  2644. };
  2645. + RestStorage.prototype.optionsForRecord = function(record, idRequired, callback) {
  2646. + var id, url;
  2647. + if (record.url) {
  2648. - url = typeof record.url === 'function' ? record.url() : record.url;
  2649. } else {
  2650. + url = "/" + this.modelKey;
  2651. + if (idRequired || !record.isNew()) {
  2652. + id = record.get('id');
  2653. + if (!(id != null)) {
  2654. + callback(new Error("Couldn't get record primary key!"));
  2655. + return;
  2656. }
  2657. + url = url + "/" + id;
  2658. }
  2659. }
  2660. + if (!url) {
  2661. - return callback.call(this, new Error("Couldn't get model url!"));
  2662. } else {
  2663. + return callback.call(this, void 0, $mixin({}, this.defaultOptions, {
  2664. url: url,
  2665. data: record
  2666. }));
  2667. }
  2668. };
  2669. + RestStorage.prototype.optionsForCollection = function(recordsOptions, callback) {
  2670. + var url, _base;
  2671. + url = (typeof (_base = this.model).url === "function" ? _base.url() : void 0) || this.model.url || ("/" + this.modelKey);
  2672. + if (!url) {
  2673. - return callback.call(this, new Error("Couldn't get collection url!"));
  2674. } else {
  2675. + return callback.call(this, void 0, $mixin({}, this.defaultOptions, {
  2676. url: url,
  2677. data: $mixin({}, this.defaultOptions.data, recordsOptions)
  2678. }));
  2679. }
  2680. };
  2681. + RestStorage.prototype.create = function(record, recordOptions, callback) {
  2682. + return this.optionsForRecord(record, false, function(err, options) {
  2683. + if (err) {
  2684. - callback(err);
  2685. - return;
  2686. }
  2687. + return new Batman.Request($mixin(options, {
  2688. method: 'POST',
  2689. success: __bind(function(data) {
  2690. + record.fromJSON(this.transformRecordData(data));
  2691. + return callback(void 0, record);
  2692. }, this),
  2693. error: function(err) {
  2694. + return callback(err);
  2695. }
  2696. }));
  2697. });
  2698. };
  2699. + RestStorage.prototype.update = function(record, recordOptions, callback) {
  2700. + return this.optionsForRecord(record, true, function(err, options) {
  2701. + if (err) {
  2702. + callback(err);
  2703. + return;
  2704. }
  2705. + return new Batman.Request($mixin(options, {
  2706. method: 'PUT',
  2707. success: __bind(function(data) {
  2708. + record.fromJSON(this.transformRecordData(data));
  2709. + return callback(void 0, record);
  2710. }, this),
  2711. error: function(err) {
  2712. - return callback(err);
  2713. }
  2714. }));
  2715. });
  2716. };
  2717. + RestStorage.prototype.read = function(record, recordOptions, callback) {
  2718. + return this.optionsForRecord(record, true, function(err, options) {
  2719. + if (err) {
  2720. + callback(err);
  2721. + return;
  2722. }
  2723. + return new Batman.Request($mixin(options, {
  2724. method: 'GET',
  2725. success: __bind(function(data) {
  2726. + record.fromJSON(this.transformRecordData(data));
  2727. + return callback(void 0, record);
  2728. }, this),
  2729. error: function(err) {
  2730. + return callback(err);
  2731. }
  2732. }));
  2733. });
  2734. };
  2735. + RestStorage.prototype.readAll = function(_, recordsOptions, callback) {
  2736. + return this.optionsForCollection(recordsOptions, function(err, options) {
  2737. + if (err) {
  2738. - callback(err);
  2739. - return;
  2740. }
  2741. + return new Batman.Request($mixin(options, {
  2742. method: 'GET',
  2743. success: __bind(function(data) {
  2744. + return callback(void 0, this.getRecordsFromData(data));
  2745. }, this),
  2746. error: function(err) {
  2747. - return callback(err);
  2748. }
  2749. }));
  2750. });
  2751. };
  2752. + RestStorage.prototype.destroy = function(record, options, callback) {
  2753. + return this.optionsForRecord(record, true, function(err, options) {
  2754. + if (err) {
  2755. + callback(err);
  2756. + return;
  2757. }
  2758. + return new Batman.Request($mixin(options, {
  2759. method: 'DELETE',
  2760. success: function() {
  2761. + return callback(void 0, record);
  2762. },
  2763. error: function(err) {
  2764. - return callback(err);
  2765. }
  2766. }));
  2767. });
  2768. };
  2769. + return RestStorage;
  2770. })();
  2771. + Batman.View = (function() {
  2772. + var viewSources;
  2773. + __extends(View, Batman.Object);
  2774. + function View(options) {
  2775. + var context;
  2776. + this.contexts = [];
  2777. + View.__super__.constructor.call(this, options);
  2778. + if (context = this.get('context')) {
  2779. - this.contexts.push(context);
  2780. - this.unset('context');
  2781. }
  2782. }
  2783. + viewSources = {};
  2784. + View.prototype.source = '';
  2785. + View.prototype.html = '';
  2786. + View.prototype.node = null;
  2787. + View.prototype.contentFor = null;
  2788. + View.prototype.ready = View.eventOneShot(function() {});
  2789. + View.prototype.prefix = 'views';
  2790. + View.observeAll('source', function() {
  2791. + return setTimeout((__bind(function() {
  2792. + return this.reloadSource();
  2793. }, this)), 0);
  2794. });
  2795. + View.prototype.reloadSource = function() {
  2796. + var source;
  2797. + source = this.get('source');
  2798. + if (!source) {
  2799. - return;
  2800. }
  2801. + if (viewSources[source]) {
  2802. - return this.set('html', viewSources[source]);
  2803. } else {
  2804. + return new Batman.Request({
  2805. url: "views/" + this.source,
  2806. type: 'html',
  2807. success: __bind(function(response) {
  2808. + viewSources[source] = response;
  2809. + return this.set('html', response);
  2810. }, this),
  2811. error: function(response) {
  2812. - throw "Could not load view from " + url;
  2813. }
  2814. });
  2815. }
  2816. };
  2817. + View.observeAll('html', function(html) {
  2818. + var node;
  2819. + node = this.node || document.createElement('div');
  2820. + node.innerHTML = html;
  2821. + if (this.node !== node) {
  2822. + return this.set('node', node);
  2823. }
  2824. });
  2825. + View.observeAll('node', function(node) {
  2826. + if (!node) {
  2827. - return;
  2828. }
  2829. + this.ready.fired = false;
  2830. + if (this._renderer) {
  2831. - this._renderer.forgetAll();
  2832. }
  2833. + if (node) {
  2834. + this._renderer = new Batman.Renderer(node, __bind(function() {
  2835. + var content, _ref2;
  2836. + content = this.contentFor;
  2837. + if (typeof content === 'string') {
  2838. - this.contentFor = (_ref2 = Batman.DOM._yields) != null ? _ref2[content] : void 0;
  2839. }
  2840. + if (this.contentFor && node) {
  2841. - this.contentFor.innerHTML = '';
  2842. - return this.contentFor.appendChild(node);
  2843. }
  2844. }, this), this.contexts);
  2845. + return this._renderer.rendered(__bind(function() {
  2846. + return this.ready(node);
  2847. }, this));
  2848. }
  2849. });
  2850. + return View;
  2851. })();
  2852. + Batman.Renderer = (function() {
  2853. + var bindingRegexp, sortBindings;
  2854. + __extends(Renderer, Batman.Object);
  2855. + function Renderer(node, callback, contexts) {
  2856. + this.node = node;
  2857. + this.callback = callback;
  2858. + if (contexts == null) {
  2859. - contexts = [];
  2860. }
  2861. + this.resume = __bind(this.resume, this);
  2862. + this.start = __bind(this.start, this);
  2863. + Renderer.__super__.constructor.apply(this, arguments);
  2864. + this.context = contexts instanceof RenderContext ? contexts : (function(func, args, ctor) {
  2865. + ctor.prototype = func.prototype;
  2866. + var child = new ctor, result = func.apply(child, args);
  2867. + return typeof result === "object" ? result : child;
  2868. })(RenderContext, contexts, function() {});
  2869. + setTimeout(this.start, 0);
  2870. }
  2871. + Renderer.prototype.start = function() {
  2872. + this.startTime = new Date;
  2873. + return this.parseNode(this.node);
  2874. };
  2875. + Renderer.prototype.resume = function() {
  2876. + this.startTime = new Date;
  2877. + return this.parseNode(this.resumeNode);
  2878. };
  2879. + Renderer.prototype.finish = function() {
  2880. + this.startTime = null;
  2881. + this.fire('parsed');
  2882. + if (typeof this.callback === "function") {
  2883. + this.callback();
  2884. }
  2885. + return this.fire('rendered');
  2886. };
  2887. + Renderer.prototype.forgetAll = function() {};
  2888. + Renderer.prototype.parsed = Renderer.eventOneShot(function() {});
  2889. + Renderer.prototype.rendered = Renderer.eventOneShot(function() {});
  2890. + bindingRegexp = /data\-(.*)/;
  2891. + sortBindings = function(a, b) {
  2892. + if (a[0] === 'foreach') {
  2893. + return -1;
  2894. + } else if (b[0] === 'foreach') {
  2895. - return 1;
  2896. + } else if (a[0] === 'formfor') {
  2897. - return -1;
  2898. + } else if (b[0] === 'formfor') {
  2899. - return 1;
  2900. + } else if (a[0] === 'bind') {
  2901. + return -1;
  2902. + } else if (b[0] === 'bind') {
  2903. + return 1;
  2904. } else {
  2905. + return 0;
  2906. }
  2907. };
  2908. + Renderer.prototype.parseNode = function(node) {
  2909. + var attr, bindings, key, name, nextNode, readerArgs, result, skipChildren, varIndex, _base, _base2, _j, _len2, _name, _name2, _ref2;
  2910. + if (new Date - this.startTime > 50) {
  2911. + this.resumeNode = node;
  2912. + setTimeout(this.resume, 0);
  2913. + return;
  2914. }
  2915. + if (node.getAttribute) {
  2916. + bindings = (function() {
  2917. + var _j, _len2, _ref2, _ref3, _results;
  2918. + _ref2 = node.attributes;
  2919. + _results = [];
  2920. + for (_j = 0, _len2 = _ref2.length; _j < _len2; _j++) {
  2921. + attr = _ref2[_j];
  2922. + name = (_ref3 = attr.nodeName.match(bindingRegexp)) != null ? _ref3[1] : void 0;
  2923. + if (!name) {
  2924. + continue;
  2925. }
  2926. + _results.push(~(varIndex = name.indexOf('-')) ? [name.substr(0, varIndex), name.substr(varIndex + 1), attr.value] : [name, attr.value]);
  2927. }
  2928. + return _results;
  2929. })();
  2930. + _ref2 = bindings.sort(sortBindings);
  2931. + for (_j = 0, _len2 = _ref2.length; _j < _len2; _j++) {
  2932. + readerArgs = _ref2[_j];
  2933. + key = readerArgs[1];
  2934. + if (key === 'property') {
  2935. - throw "property is a reserved keyword";
  2936. }
  2937. + result = readerArgs.length === 2 ? typeof (_base = Batman.DOM.readers)[_name = readerArgs[0]] === "function" ? _base[_name](node, key, this.context, this) : void 0 : typeof (_base2 = Batman.DOM.attrReaders)[_name2 = readerArgs[0]] === "function" ? _base2[_name2](node, key, readerArgs[2], this.context, this) : void 0;
  2938. + if (result === false) {
  2939. + skipChildren = true;
  2940. + break;
  2941. }
  2942. }
  2943. }
  2944. + if ((nextNode = this.nextNode(node, skipChildren))) {
  2945. + return this.parseNode(nextNode);
  2946. } else {
  2947. + return this.finish();
  2948. }
  2949. };
  2950. + Renderer.prototype.nextNode = function(node, skipChildren) {
  2951. + var children, nextParent, parentSibling, sibling;
  2952. + if (!skipChildren) {
  2953. + children = node.childNodes;
  2954. + if (children != null ? children.length : void 0) {
  2955. + return children[0];
  2956. }
  2957. }
  2958. + if (typeof node.onParseExit === "function") {
  2959. - node.onParseExit();
  2960. }
  2961. + if (this.node.isSameNode(node)) {
  2962. + return;
  2963. }
  2964. + sibling = node.nextSibling;
  2965. + if (sibling) {
  2966. + return sibling;
  2967. }
  2968. + nextParent = node;
  2969. + while (nextParent = nextParent.parentNode) {
  2970. + if (typeof nextParent.onParseExit === "function") {
  2971. + nextParent.onParseExit();
  2972. }
  2973. + if (this.node.isSameNode(nextParent)) {
  2974. + return;
  2975. }
  2976. + parentSibling = nextParent.nextSibling;
  2977. + if (parentSibling) {
  2978. + return parentSibling;
  2979. }
  2980. }
  2981. };
  2982. + return Renderer;
  2983. })();
  2984. + Binding = (function() {
  2985. + var get_rx, keypath_rx;
  2986. + __extends(Binding, Batman.Object);
  2987. + keypath_rx = /(?:^|,)\s*(?!(?:true|false)\s*(?:$|,))([a-zA-Z][\w\.]*)\s*(?:$|,)/;
  2988. + get_rx = /(\w)\[(.+?)\]/;
  2989. + Binding.accessor('filteredValue', function() {
  2990. + var value;
  2991. + value = this.get('unfilteredValue');
  2992. + if (this.filterFunctions.length > 0) {
  2993. + return this.filterFunctions.reduce(__bind(function(value, fn, i) {
  2994. + var args;
  2995. + args = this.filterArguments[i].map(function(argument) {
  2996. + if (argument._keypath) {
  2997. + return argument.context.get(argument._keypath);
  2998. } else {
  2999. + return argument;
  3000. }
  3001. });
  3002. + return fn.apply(null, [value].concat(__slice.call(args)));
  3003. }, this), value);
  3004. } else {
  3005. + return value;
  3006. }
  3007. });
  3008. + Binding.accessor('unfilteredValue', function() {
  3009. + if (k = this.get('key')) {
  3010. + return this.get("keyContext." + k);
  3011. } else {
  3012. + return this.get('value');
  3013. }
  3014. });
  3015. + Binding.accessor('keyContext', function() {
  3016. + var unfilteredValue, _ref2;
  3017. + if (!this._keyContext) {
  3018. + _ref2 = this.renderContext.findKey(this.key), unfilteredValue = _ref2[0], this._keyContext = _ref2[1];
  3019. }
  3020. + return this._keyContext;
  3021. });
  3022. + function Binding() {
  3023. + var shouldSet;
  3024. + Binding.__super__.constructor.apply(this, arguments);
  3025. + this.parseFilter();
  3026. + this.nodeChange || (this.nodeChange = __bind(function(node, context) {
  3027. + if (this.key) {
  3028. + return this.get('keyContext').set(this.key, this.node.value);
  3029. }
  3030. }, this));
  3031. + this.dataChange || (this.dataChange = function(value, node) {
  3032. + return Batman.DOM.valueForNode(this.node, value);
  3033. });
  3034. + shouldSet = true;
  3035. + if (Batman.DOM.nodeIsEditable(this.node)) {
  3036. + Batman.DOM.events.change(this.node, __bind(function() {
  3037. + shouldSet = false;
  3038. + this.nodeChange(this.node, this._keyContext || this.value, this);
  3039. + return shouldSet = true;
  3040. }, this));
  3041. }
  3042. + this.observe('filteredValue', true, __bind(function(value) {
  3043. + if (shouldSet) {
  3044. + return this.dataChange(value, this.node, this);
  3045. }
  3046. }, this));
  3047. + this;
  3048. }
  3049. + Binding.prototype.parseFilter = function() {
  3050. + var args, filter, filterName, filterString, filters, key, orig, split;
  3051. + this.filterFunctions = [];
  3052. + this.filterArguments = [];
  3053. + filters = this.keyPath.replace(get_rx, "$1 | get $2 ").replace(/'/g, '"').split(/(?!")\s+\|\s+(?!")/);
  3054. + try {
  3055. + key = this.parseSegment(orig = filters.shift())[0];
  3056. } catch (e) {
  3057. - throw "Bad binding keypath \"" + orig + "\"!";
  3058. }
  3059. + if (key && key._keypath) {
  3060. + this.key = key._keypath;
  3061. } else {
  3062. + this.value = key;
  3063. }
  3064. + if (filters.length) {
  3065. + while (filterString = filters.shift()) {
  3066. + split = filterString.indexOf(' ');
  3067. + if (~split) {
  3068. + filterName = filterString.substr(0, split);
  3069. + args = filterString.substr(split);
  3070. } else {
  3071. + filterName = filterString;
  3072. }
  3073. + if (filter = Batman.Filters[filterName]) {
  3074. + this.filterFunctions.push(filter);
  3075. + if (args) {
  3076. + try {
  3077. + this.filterArguments.push(this.parseSegment(args));
  3078. } catch (e) {
  3079. - throw new Error("Bad filter arguments \"" + args + "\"!");
  3080. }
  3081. } else {
  3082. + this.filterArguments.push([]);
  3083. }
  3084. } else {
  3085. - throw new Error("Unrecognized filter '" + filterName + "' in key \"" + this.keyPath + "\"!");
  3086. }
  3087. }
  3088. + return this.filterArguments = this.filterArguments.map(__bind(function(argumentList) {
  3089. + return argumentList.map(__bind(function(argument) {
  3090. + var _, _ref2;
  3091. + if (argument._keypath) {
  3092. + _ref2 = this.renderContext.findKey(argument._keypath), _ = _ref2[0], argument.context = _ref2[1];
  3093. }
  3094. + return argument;
  3095. }, this));
  3096. }, this));
  3097. }
  3098. };
  3099. + Binding.prototype.parseSegment = function(segment) {
  3100. + return JSON.parse("[" + segment.replace(keypath_rx, "{\"_keypath\": \"$1\"}") + "]");
  3101. };
  3102. + return Binding;
  3103. })();
  3104. + RenderContext = (function() {
  3105. + var BindingProxy;
  3106. + function RenderContext() {
  3107. + var contexts;
  3108. + contexts = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
  3109. + this.contexts = contexts;
  3110. + this.storage = new Batman.Object;
  3111. + this.defaultContexts = [this.storage];
  3112. + if (Batman.currentApp) {
  3113. - this.defaultContexts.push(Batman.currentApp);
  3114. }
  3115. }
  3116. + RenderContext.prototype.findKey = function(key) {
  3117. + var base, context, contexts, i, val, _j, _len2, _ref2;
  3118. + base = key.split('.')[0].split('|')[0].trim();
  3119. + _ref2 = [this.contexts, this.defaultContexts];
  3120. + for (_j = 0, _len2 = _ref2.length; _j < _len2; _j++) {
  3121. + contexts = _ref2[_j];
  3122. + i = contexts.length;
  3123. + while (i--) {
  3124. + context = contexts[i];
  3125. + if (context.get != null) {
  3126. + val = context.get(base);
  3127. } else {
  3128. + val = context[base];
  3129. }
  3130. + if (typeof val !== 'undefined') {
  3131. + return [$get(context, key), context];
  3132. }
  3133. }
  3134. }
  3135. + return [container.get(key), container];
  3136. };
  3137. + RenderContext.prototype.set = function() {
  3138. - var args, _ref2;
  3139. - args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
  3140. - return (_ref2 = this.storage).set.apply(_ref2, args);
  3141. };
  3142. + RenderContext.prototype.push = function(x) {
  3143. + return this.contexts.push(x);
  3144. };
  3145. + RenderContext.prototype.pop = function() {
  3146. + return this.contexts.pop();
  3147. };
  3148. + RenderContext.prototype.clone = function() {
  3149. + var context, newStorage;
  3150. + context = (function(func, args, ctor) {
  3151. + ctor.prototype = func.prototype;
  3152. + var child = new ctor, result = func.apply(child, args);
  3153. + return typeof result === "object" ? result : child;
  3154. })(this.constructor, this.contexts, function() {});
  3155. + newStorage = $mixin({}, this.storage);
  3156. + context.setStorage(newStorage);
  3157. + return context;
  3158. };
  3159. + RenderContext.prototype.setStorage = function(storage) {
  3160. + return this.defaultContexts[0] = storage;
  3161. };
  3162. + BindingProxy = (function() {
  3163. + __extends(BindingProxy, Batman.Object);
  3164. + BindingProxy.prototype.isBindingProxy = true;
  3165. + function BindingProxy(binding, localKey) {
  3166. + this.binding = binding;
  3167. + this.localKey = localKey;
  3168. + if (this.localKey) {
  3169. + this.accessor(this.localKey, function() {
  3170. + return this.binding.get('filteredValue');
  3171. });
  3172. } else {
  3173. + this.accessor(function(key) {
  3174. + return this.binding.get("filteredValue." + key);
  3175. });
  3176. }
  3177. }
  3178. + return BindingProxy;
  3179. })();
  3180. + RenderContext.prototype.addKeyToScopeForNode = function(node, key, localName) {
  3181. + this.bind(node, key, __bind(function(value, node, binding) {
  3182. + return this.push(new BindingProxy(binding, localName));
  3183. }, this), function() {
  3184. - return true;
  3185. });
  3186. + return node.onParseExit = __bind(function() {
  3187. + return this.pop();
  3188. }, this);
  3189. };
  3190. + RenderContext.prototype.bind = function(node, key, dataChange, nodeChange) {
  3191. + return new Binding({
  3192. renderContext: this,
  3193. keyPath: key,
  3194. node: node,
  3195. dataChange: dataChange,
  3196. nodeChange: nodeChange
  3197. });
  3198. };
  3199. + return RenderContext;
  3200. })();
  3201. + Batman.DOM = {
  3202. readers: {
  3203. bind: function(node, key, context, renderer) {
  3204. + if (node.nodeName.toLowerCase() === 'input' && node.getAttribute('type') === 'checkbox') {
  3205. + return Batman.DOM.attrReaders.bind(node, 'checked', key, context);
  3206. + } else if (node.nodeName.toLowerCase() === 'select') {
  3207. + return renderer.rendered(function() {
  3208. + return Batman.DOM.attrReaders.bind(node, 'value', key, context);
  3209. });
  3210. } else {
  3211. + return context.bind(node, key);
  3212. }
  3213. },
  3214. context: function(node, key, context) {
  3215. + return context.addKeyToScopeForNode(node, key);
  3216. },
  3217. mixin: function(node, key, context) {
  3218. + context.push(Batman.mixins);
  3219. + context.bind(node, key, function(mixin) {
  3220. + return $mixin(node, mixin);
  3221. }, function() {});
  3222. + return context.pop();
  3223. },
  3224. showif: function(node, key, context, renderer, invert) {
  3225. + var originalDisplay;
  3226. + originalDisplay = node.style.display || '';
  3227. + return context.bind(node, key, function(value) {
  3228. + if (!!value === !invert) {
  3229. + if (typeof node.show === "function") {
  3230. - node.show();
  3231. }
  3232. + return node.style.display = originalDisplay;
  3233. } else {
  3234. + if (typeof node.hide === 'function') {
  3235. - return node.hide();
  3236. } else {
  3237. + return node.style.display = 'none';
  3238. }
  3239. }
  3240. }, function() {});
  3241. },
  3242. hideif: function() {
  3243. - var args, _ref2;
  3244. - args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
  3245. - return (_ref2 = Batman.DOM.readers).showif.apply(_ref2, __slice.call(args).concat([true]));
  3246. },
  3247. route: function(node, key, context) {
  3248. + var action, app, container, dispatcher, model, name, url, _ref2, _ref3, _ref4;
  3249. + if (key.substr(0, 1) === '/') {
  3250. + url = key;
  3251. } else {
  3252. - _ref2 = key.split('/'), key = _ref2[0], action = _ref2[1];
  3253. - _ref3 = context.findKey('dispatcher'), dispatcher = _ref3[0], app = _ref3[1];
  3254. - _ref4 = context.findKey(key), model = _ref4[0], container = _ref4[1];
  3255. - dispatcher || (dispatcher = Batman.currentApp.dispatcher);
  3256. - if (dispatcher && model instanceof Batman.Model) {
  3257. - action || (action = 'show');
  3258. - name = helpers.underscore(helpers.pluralize(model.constructor.name));
  3259. - url = dispatcher.findUrl({
  3260. resource: name,
  3261. id: model.get('id'),
  3262. action: action
  3263. });
  3264. - } else if (model != null ? model.prototype : void 0) {
  3265. - name = helpers.underscore(helpers.pluralize(model.name));
  3266. - url = dispatcher.findUrl({
  3267. resource: name,
  3268. action: 'index'
  3269. });
  3270. }
  3271. }
  3272. + if (!url) {
  3273. - return;
  3274. }
  3275. + if (node.nodeName.toUpperCase() === 'A') {
  3276. + node.href = Batman.HashHistory.prototype.urlFor(url);
  3277. }
  3278. + return Batman.DOM.events.click(node, (function() {
  3279. - return $redirect(url);
  3280. }));
  3281. },
  3282. partial: function(node, path, context) {
  3283. - var view;
  3284. - return view = new Batman.View({
  3285. source: path + '.html',
  3286. contentFor: node,
  3287. contexts: Array.prototype.slice.call(context.contexts)
  3288. });
  3289. },
  3290. yield: function(node, key) {
  3291. + return setTimeout((function() {
  3292. + return Batman.DOM.yield(key, node);
  3293. }), 0);
  3294. },
  3295. contentfor: function(node, key) {
  3296. + return setTimeout((function() {
  3297. + return Batman.DOM.contentFor(key, node);
  3298. }), 0);
  3299. }
  3300. },
  3301. attrReaders: {
  3302. _parseAttribute: function(value) {
  3303. + if (value === 'false') {
  3304. - value = false;
  3305. }
  3306. + if (value === 'true') {
  3307. - value = true;
  3308. }
  3309. + return value;
  3310. },
  3311. bind: function(node, attr, key, context) {
  3312. + var contextChange, nodeChange;
  3313. + switch (attr) {
  3314. case 'checked':
  3315. case 'disabled':
  3316. + contextChange = function(value) {
  3317. + return node[attr] = !!value;
  3318. };
  3319. + nodeChange = function(node, subContext) {
  3320. + return subContext.set(key, Batman.DOM.attrReaders._parseAttribute(node[attr]));
  3321. };
  3322. + break;
  3323. case 'value':
  3324. + contextChange = function(value) {
  3325. + return node.value = value;
  3326. };
  3327. + nodeChange = function(node, subContext) {
  3328. - return subContext.set(key, Batman.DOM.attrReaders._parseAttribute(node.value));
  3329. };
  3330. + break;
  3331. default:
  3332. + contextChange = function(value) {
  3333. + return node.setAttribute(attr, value);
  3334. };
  3335. + nodeChange = function(node, subContext) {
  3336. - return subContext.set(key, Batman.DOM.attrReaders._parseAttribute(node.getAttribute(attr)));
  3337. };
  3338. }
  3339. + return context.bind(node, key, contextChange, nodeChange);
  3340. },
  3341. context: function(node, contextName, key, context) {
  3342. + return context.addKeyToScopeForNode(node, key, contextName);
  3343. },
  3344. event: function(node, eventName, key, context) {
  3345. + var callback, subContext, _ref2;
  3346. + if (key.substr(0, 1) === '@') {
  3347. - callback = new Function(key.substr(1));
  3348. } else {
  3349. + _ref2 = context.findKey(key), callback = _ref2[0], subContext = _ref2[1];
  3350. }
  3351. + return Batman.DOM.events[eventName](node, function() {
  3352. + var confirmText, x;
  3353. + confirmText = node.getAttribute('data-confirm');
  3354. + if (confirmText && !confirm(confirmText)) {
  3355. - return;
  3356. }
  3357. + x = eventName;
  3358. + x = key;
  3359. + return callback != null ? callback.apply(subContext, arguments) : void 0;
  3360. });
  3361. },
  3362. addclass: function(node, className, key, context, parentRenderer, invert) {
  3363. + className = className.replace(/\|/g, ' ');
  3364. + return context.bind(node, key, function(value) {
  3365. + var currentName, includesClassName;
  3366. + currentName = node.className;
  3367. + includesClassName = currentName.indexOf(className) !== -1;
  3368. + if (!!value === !invert) {
  3369. + if (!includesClassName) {
  3370. + return node.className = "" + currentName + " " + className;
  3371. }
  3372. } else {
  3373. + if (includesClassName) {
  3374. - return node.className = currentName.replace(className, '');
  3375. }
  3376. }
  3377. }, function() {});
  3378. },
  3379. removeclass: function() {
  3380. + var args, _ref2;
  3381. + args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
  3382. + return (_ref2 = Batman.DOM.attrReaders).addclass.apply(_ref2, __slice.call(args).concat([true]));
  3383. },
  3384. foreach: function(node, iteratorName, key, context, parentRenderer) {
  3385. + var fragment, nodeMap, numPendingChildren, observers, oldCollection, parent, prototype, sibling;
  3386. + prototype = node.cloneNode(true);
  3387. + prototype.removeAttribute("data-foreach-" + iteratorName);
  3388. + parent = node.parentNode;
  3389. + sibling = node.nextSibling;
  3390. + fragment = document.createDocumentFragment();
  3391. + numPendingChildren = 0;
  3392. + parentRenderer.parsed(function() {
  3393. + return parent.removeChild(node);
  3394. });
  3395. + nodeMap = new Batman.Hash;
  3396. + observers = {};
  3397. + oldCollection = false;
  3398. + context.bind(node, key, function(collection) {
  3399. + var k, v, _results;
  3400. + if (oldCollection) {
  3401. + if (collection === oldCollection) {
  3402. + return;
  3403. }
  3404. + nodeMap.forEach(function(item, node) {
  3405. + return parent.removeChild(node);
  3406. });
  3407. + oldCollection.forget('itemsWereAdded', observers.add);
  3408. + oldCollection.forget('itemsWereRemoved', observers.remove);
  3409. + oldCollection.forget('setWasSorted', observers.reorder);
  3410. }
  3411. + oldCollection = collection;
  3412. + observers.add = function() {
  3413. + var item, items, iteratorContext, localClone, newNode, _j, _len2, _results;
  3414. + items = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
  3415. + numPendingChildren += items.length;
  3416. + _results = [];
  3417. + for (_j = 0, _len2 = items.length; _j < _len2; _j++) {
  3418. + item = items[_j];
  3419. + parentRenderer.prevent('rendered');
  3420. + newNode = prototype.cloneNode(true);
  3421. + nodeMap.set(item, newNode);
  3422. + localClone = context.clone();
  3423. + iteratorContext = new Batman.Object;
  3424. + iteratorContext[iteratorName] = item;
  3425. + localClone.push(iteratorContext);
  3426. + localClone.push(item);
  3427. + _results.push(new Batman.Renderer(newNode, (function(newNode) {
  3428. + return function() {
  3429. + if (typeof collection.isSorted === "function" ? collection.isSorted() : void 0) {
  3430. + observers.reorder();
  3431. } else {
  3432. + if (typeof newNode.show === 'function') {
  3433. - newNode.show({
  3434. before: sibling
  3435. });
  3436. } else {
  3437. + fragment.appendChild(newNode);
  3438. }
  3439. }
  3440. + if (--numPendingChildren === 0) {
  3441. + parent.insertBefore(fragment, sibling);
  3442. + fragment = document.createDocumentFragment();
  3443. }
  3444. + parentRenderer.allow('rendered');
  3445. + return parentRenderer.fire('rendered');
  3446. };
  3447. })(newNode), localClone));
  3448. }
  3449. + return _results;
  3450. };
  3451. + observers.remove = function() {
  3452. + var item, items, oldNode, _j, _len2, _ref2;
  3453. + items = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
  3454. + for (_j = 0, _len2 = items.length; _j < _len2; _j++) {
  3455. + item = items[_j];
  3456. + oldNode = nodeMap.get(item);
  3457. + nodeMap.unset(item);
  3458. + if (typeof oldNode.hide === 'function') {
  3459. - oldNode.hide(true);
  3460. } else {
  3461. + if (oldNode != null) {
  3462. + if ((_ref2 = oldNode.parentNode) != null) {
  3463. + _ref2.removeChild(oldNode);
  3464. }
  3465. }
  3466. }
  3467. }
  3468. + return true;
  3469. };
  3470. + observers.reorder = function() {
  3471. + var item, items, thisNode, _j, _len2, _results;
  3472. + items = collection.toArray();
  3473. + _results = [];
  3474. + for (_j = 0, _len2 = items.length; _j < _len2; _j++) {
  3475. + item = items[_j];
  3476. + thisNode = nodeMap.get(item);
  3477. + _results.push(typeof thisNode.show === 'function' ? thisNode.show({
  3478. before: sibling
  3479. }) : parent.insertBefore(thisNode, sibling));
  3480. }
  3481. + return _results;
  3482. };
  3483. + if (collection != null ? collection.observe : void 0) {
  3484. + collection.observe('itemsWereAdded', observers.add);
  3485. + collection.observe('itemsWereRemoved', observers.remove);
  3486. + collection.observe('setWasSorted', observers.reorder);
  3487. }
  3488. + if (collection.forEach) {
  3489. + return collection.forEach(function(item) {
  3490. + return observers.add(item);
  3491. });
  3492. } else {
  3493. + _results = [];
  3494. + for (k in collection) {
  3495. + v = collection[k];
  3496. + _results.push(observers.add(k));
  3497. }
  3498. + return _results;
  3499. }
  3500. }, function() {});
  3501. + return false;
  3502. },
  3503. formfor: function(node, localName, key, context) {
  3504. + var binding;
  3505. + binding = context.addKeyToScopeForNode(node, key, localName);
  3506. + return Batman.DOM.events.submit(node, function(node, e) {
  3507. - return e.preventDefault();
  3508. });
  3509. }
  3510. },
  3511. events: {
  3512. click: function(node, callback) {
  3513. + Batman.DOM.addEventListener(node, 'click', function() {
  3514. + var args;
  3515. + args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
  3516. + callback.apply(null, [node].concat(__slice.call(args)));
  3517. + return args[0].preventDefault();
  3518. });
  3519. + if (node.nodeName.toUpperCase() === 'A' && !node.href) {
  3520. - node.href = '#';
  3521. }
  3522. + return node;
  3523. },
  3524. change: function(node, callback) {
  3525. + var eventName, eventNames, oldCallback, _j, _len2, _results;
  3526. + eventNames = (function() {
  3527. + switch (node.nodeName.toUpperCase()) {
  3528. case 'TEXTAREA':
  3529. + return ['keyup', 'change'];
  3530. case 'INPUT':
  3531. + if (node.type.toUpperCase() === 'TEXT') {
  3532. + oldCallback = callback;
  3533. + callback = function(e) {
  3534. + var _ref2;
  3535. + if (e.type === 'keyup' && (13 <= (_ref2 = e.keyCode) && _ref2 <= 14)) {
  3536. - return;
  3537. }
  3538. + return oldCallback.apply(null, arguments);
  3539. };
  3540. + return ['keyup', 'change'];
  3541. } else {
  3542. + return ['change'];
  3543. }
  3544. - break;
  3545. default:
  3546. + return ['change'];
  3547. }
  3548. })();
  3549. + _results = [];
  3550. + for (_j = 0, _len2 = eventNames.length; _j < _len2; _j++) {
  3551. + eventName = eventNames[_j];
  3552. + _results.push(Batman.DOM.addEventListener(node, eventName, function() {
  3553. + var args;
  3554. + args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
  3555. + return callback.apply(null, [node].concat(__slice.call(args)));
  3556. }));
  3557. }
  3558. + return _results;
  3559. },
  3560. submit: function(node, callback) {
  3561. + if (Batman.DOM.nodeIsEditable(node)) {
  3562. - Batman.DOM.addEventListener(node, 'keyup', function() {
  3563. - var args;
  3564. - args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
  3565. - if (args[0].keyCode === 13 || args[0].which === 13 || args[0].keyIdentifier === 'Enter') {
  3566. - callback.apply(null, [node].concat(__slice.call(args)));
  3567. - return args[0].preventDefault();
  3568. }
  3569. });
  3570. } else {
  3571. + Batman.DOM.addEventListener(node, 'submit', function() {
  3572. - var args;
  3573. - args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
  3574. - callback.apply(null, [node].concat(__slice.call(args)));
  3575. - return args[0].preventDefault();
  3576. });
  3577. }
  3578. + return node;
  3579. }
  3580. },
  3581. yield: function(name, node) {
  3582. + var content, yields, _base, _ref2;
  3583. + yields = (_base = Batman.DOM)._yields || (_base._yields = {});
  3584. + yields[name] = node;
  3585. + if ((content = (_ref2 = Batman.DOM._yieldContents) != null ? _ref2[name] : void 0)) {
  3586. + node.innerHTML = '';
  3587. + if (content) {
  3588. + return node.appendChild(content);
  3589. }
  3590. }
  3591. },
  3592. contentFor: function(name, node) {
  3593. + var contents, yield, _base, _ref2;
  3594. + contents = (_base = Batman.DOM)._yieldContents || (_base._yieldContents = {});
  3595. + contents[name] = node;
  3596. + if ((yield = (_ref2 = Batman.DOM._yields) != null ? _ref2[name] : void 0)) {
  3597. + yield.innerHTML = '';
  3598. + if (node) {
  3599. + return yield.appendChild(node);
  3600. }
  3601. }
  3602. },
  3603. valueForNode: function(node, value) {
  3604. + var isSetting;
  3605. + if (value == null) {
  3606. + value = '';
  3607. }
  3608. + isSetting = arguments.length > 1;
  3609. + switch (node.nodeName.toUpperCase()) {
  3610. case 'INPUT':
  3611. + if (isSetting) {
  3612. + return node.value = value;
  3613. } else {
  3614. - return node.value;
  3615. }
  3616. - break;
  3617. case 'TEXTAREA':
  3618. + if (isSetting) {
  3619. + return node.innerHTML = node.value = value;
  3620. } else {
  3621. - return node.innerHTML;
  3622. }
  3623. - break;
  3624. case 'SELECT':
  3625. - return node.value = value;
  3626. default:
  3627. + if (isSetting) {
  3628. + return node.innerHTML = value;
  3629. } else {
  3630. - return node.innerHTML;
  3631. }
  3632. }
  3633. },
  3634. nodeIsEditable: function(node) {
  3635. + var _ref2;
  3636. + return (_ref2 = node.nodeName.toUpperCase()) === 'INPUT' || _ref2 === 'TEXTAREA' || _ref2 === 'SELECT';
  3637. },
  3638. addEventListener: function(node, eventName, callback) {
  3639. + if (node.addEventListener) {
  3640. + return node.addEventListener(eventName, callback, false);
  3641. } else {
  3642. - return node.attachEvent("on" + eventName, callback);
  3643. }
  3644. }
  3645. };
  3646. + camelize_rx = /(?:^|_|\-)(.)/g;
  3647. + capitalize_rx = /(^|\s)([a-z])/g;
  3648. + underscore_rx1 = /([A-Z]+)([A-Z][a-z])/g;
  3649. + underscore_rx2 = /([a-z\d])([A-Z])/g;
  3650. + helpers = Batman.helpers = {
  3651. camelize: function(string, firstLetterLower) {
  3652. - string = string.replace(camelize_rx, function(str, p1) {
  3653. - return p1.toUpperCase();
  3654. });
  3655. - if (firstLetterLower) {
  3656. - return string.substr(0, 1).toLowerCase() + string.substr(1);
  3657. } else {
  3658. - return string;
  3659. }
  3660. },
  3661. underscore: function(string) {
  3662. + return string.replace(underscore_rx1, '$1_$2').replace(underscore_rx2, '$1_$2').replace('-', '_').toLowerCase();
  3663. },
  3664. singularize: function(string) {
  3665. + if (string.substr(-3) === 'ies') {
  3666. - return string.substr(0, string.length - 3) + 'y';
  3667. + } else if (string.substr(-1) === 's') {
  3668. + return string.substr(0, string.length - 1);
  3669. } else {
  3670. - return string;
  3671. }
  3672. },
  3673. pluralize: function(count, string) {
  3674. + var lastLetter;
  3675. + if (string) {
  3676. - if (count === 1) {
  3677. - return string;
  3678. }
  3679. } else {
  3680. + string = count;
  3681. }
  3682. + lastLetter = string.substr(-1);
  3683. + if (lastLetter === 'y') {
  3684. - return "" + (string.substr(0, string.length - 1)) + "ies";
  3685. + } else if (lastLetter === 's') {
  3686. + return string;
  3687. } else {
  3688. + return "" + string + "s";
  3689. }
  3690. },
  3691. capitalize: function(string) {
  3692. - return string.replace(capitalize_rx, function(m, p1, p2) {
  3693. - return p1 + p2.toUpperCase();
  3694. });
  3695. }
  3696. };
  3697. + buntUndefined = function(f) {
  3698. + return function(value) {
  3699. + if (typeof value === 'undefined') {
  3700. - return;
  3701. } else {
  3702. + return f.apply(this, arguments);
  3703. }
  3704. };
  3705. };
  3706. + filters = Batman.Filters = {
  3707. get: buntUndefined(function(value, key) {
  3708. + if (value.get != null) {
  3709. + return value.get(key);
  3710. } else {
  3711. + return value[key];
  3712. }
  3713. }),
  3714. equals: buntUndefined(function(lhs, rhs) {
  3715. - return lhs === rhs;
  3716. }),
  3717. not: function(value) {
  3718. + return !!!value;
  3719. },
  3720. truncate: buntUndefined(function(value, length, end) {
  3721. + if (end == null) {
  3722. + end = "...";
  3723. }
  3724. + if (value.length > length) {
  3725. + value = value.substr(0, length - end.length) + end;
  3726. }
  3727. + return value;
  3728. }),
  3729. "default": function(value, string) {
  3730. - return value || string;
  3731. },
  3732. prepend: function(value, string) {
  3733. + return string + value;
  3734. },
  3735. append: function(value, string) {
  3736. + return value + string;
  3737. },
  3738. downcase: buntUndefined(function(value) {
  3739. + return value.toLowerCase();
  3740. }),
  3741. upcase: buntUndefined(function(value) {
  3742. + return value.toUpperCase();
  3743. }),
  3744. pluralize: buntUndefined(function(string, count) {
  3745. - return helpers.pluralize(count, string);
  3746. }),
  3747. join: buntUndefined(function(value, byWhat) {
  3748. + if (byWhat == null) {
  3749. + byWhat = '';
  3750. }
  3751. + return value.join(byWhat);
  3752. }),
  3753. sort: buntUndefined(function(value) {
  3754. + return value.sort();
  3755. }),
  3756. map: buntUndefined(function(value, key) {
  3757. + return value.map(function(x) {
  3758. + return x[key];
  3759. });
  3760. }),
  3761. first: buntUndefined(function(value) {
  3762. + return value[0];
  3763. })
  3764. };
  3765. + _ref2 = ['capitalize', 'singularize', 'underscore', 'camelize'];
  3766. + for (_j = 0, _len2 = _ref2.length; _j < _len2; _j++) {
  3767. + k = _ref2[_j];
  3768. + filters[k] = buntUndefined(helpers[k]);
  3769. }
  3770. + mixins = Batman.mixins = new Batman.Object;
  3771. + container = typeof exports !== "undefined" && exports !== null ? (module.exports = Batman, global) : (window.Batman = Batman, window);
  3772. + $mixin(container, Batman.Observable);
  3773. + Batman.exportHelpers = function(onto) {
  3774. + var k, _k, _len3, _ref3;
  3775. + _ref3 = ['mixin', 'unmixin', 'route', 'redirect', 'event', 'eventOneShot', 'typeOf', 'redirect'];
  3776. + for (_k = 0, _len3 = _ref3.length; _k < _len3; _k++) {
  3777. + k = _ref3[_k];
  3778. + onto["$" + k] = Batman[k];
  3779. }
  3780. + return onto;
  3781. };
  3782. + Batman.exportGlobals = function() {
  3783. - return Batman.exportHelpers(container);
  3784. };
  3785. }).call(this);
Add Comment
Please, Sign In to add comment