Repository: Shopify/dashing Branch: master Commit: bc1c106e42d5 Files: 75 Total size: 786.2 KB Directory structure: gitextract_5ra_d6aq/ ├── .gitignore ├── .travis.yml ├── CONTRIBUTING.md ├── Gemfile ├── MIT-LICENSE ├── README.md ├── Rakefile ├── bin/ │ └── dashing ├── dashing.gemspec ├── javascripts/ │ ├── batman.jquery.js │ ├── batman.js │ ├── dashing.coffee │ ├── es5-shim.js │ └── jquery.js ├── lib/ │ ├── dashing/ │ │ ├── app.rb │ │ ├── cli.rb │ │ └── downloader.rb │ └── dashing.rb ├── shipit.rubygems.yml ├── templates/ │ ├── dashboard/ │ │ └── %name%.erb.tt │ ├── job/ │ │ └── %name%.rb │ ├── project/ │ │ ├── .gitignore │ │ ├── Gemfile │ │ ├── README.md │ │ ├── assets/ │ │ │ ├── fonts/ │ │ │ │ └── FontAwesome.otf │ │ │ ├── javascripts/ │ │ │ │ ├── application.coffee │ │ │ │ ├── d3-3.2.8.js │ │ │ │ ├── dashing.gridster.coffee │ │ │ │ └── jquery.knob.js │ │ │ └── stylesheets/ │ │ │ ├── application.scss │ │ │ └── font-awesome.css │ │ ├── config.ru │ │ ├── dashboards/ │ │ │ ├── layout.erb │ │ │ ├── sample.erb │ │ │ └── sampletv.erb │ │ ├── jobs/ │ │ │ ├── buzzwords.rb │ │ │ ├── convergence.rb │ │ │ ├── sample.rb │ │ │ └── twitter.rb │ │ ├── lib/ │ │ │ └── .empty_directory │ │ ├── public/ │ │ │ └── 404.html │ │ └── widgets/ │ │ ├── clock/ │ │ │ ├── clock.coffee │ │ │ ├── clock.html │ │ │ └── clock.scss │ │ ├── comments/ │ │ │ ├── comments.coffee │ │ │ ├── comments.html │ │ │ └── comments.scss │ │ ├── graph/ │ │ │ ├── graph.coffee │ │ │ ├── graph.html │ │ │ └── graph.scss │ │ ├── iframe/ │ │ │ ├── iframe.coffee │ │ │ ├── iframe.html │ │ │ └── iframe.scss │ │ ├── image/ │ │ │ ├── image.coffee │ │ │ ├── image.html │ │ │ └── image.scss │ │ ├── list/ │ │ │ ├── list.coffee │ │ │ ├── list.html │ │ │ └── list.scss │ │ ├── meter/ │ │ │ ├── meter.coffee │ │ │ ├── meter.html │ │ │ └── meter.scss │ │ ├── number/ │ │ │ ├── number.coffee │ │ │ ├── number.html │ │ │ └── number.scss │ │ └── text/ │ │ ├── text.coffee │ │ ├── text.html │ │ └── text.scss │ └── widget/ │ └── %name%/ │ ├── %name%.coffee.tt │ ├── %name%.html │ └── %name%.scss.tt └── test/ ├── app_test.rb ├── cli_test.rb ├── downloader_test.rb └── test_helper.rb ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ *DS_STORE /Gemfile.lock *.gem coverage/ log/ tmp/ .ruby-version history.yml ================================================ FILE: .travis.yml ================================================ language: ruby rvm: - 2.3.0 - 2.2.4 - 2.1.8 script: "rake test" ================================================ FILE: CONTRIBUTING.md ================================================ ## Have an Issue? Dashing is no longer being actively maintained. 1. Check the [Troubleshooting Guide](https://github.com/Shopify/dashing/wiki#how-tos) in the wiki. 2. Use the [GitHub Issue Search](https://help.github.com/articles/searching-issues/) to check if the issue has already been reported. 3. You can ask your issue on the tracker, but your best bet is to go to [Stack Overflow](http://stackoverflow.com/questions/tagged/dashing) If you feel that you have a really amazing, super neato idea that should be a part of Dashing, it may be a good candidate for an external Gem which supercharges a project. An excellent example of this is [dashing-contrib](https://github.com/QubitProducts/dashing-contrib). If you do create a third-party extension for Dashing, please add it [here](https://github.com/Shopify/dashing/wiki/Additional-Widgets#other-third-party-tools). ================================================ FILE: Gemfile ================================================ source 'https://rubygems.org' gemspec ================================================ FILE: MIT-LICENSE ================================================ Copyright (c) 2016 Shopify Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ # [Dashing](http://shopify.github.com/dashing) [![Build Status](https://secure.travis-ci.org/Shopify/dashing.png?branch=master)](http://travis-ci.org/Shopify/dashing) Dashing is a Sinatra based framework that lets you build beautiful dashboards. It looks especially great on TVs. [Check out the homepage](http://shopify.github.com/dashing). Note: Dashing is no longer being actively maintained. Read about it [here](https://github.com/Shopify/dashing/issues/711). There is a fork of the project being maintained at at [https://github.com/dashing-io/dashing](https://github.com/dashing-io/dashing) # License Distributed under the [MIT license](MIT-LICENSE) ================================================ FILE: Rakefile ================================================ require 'rubygems' require 'rake' require 'bundler/gem_tasks' require 'rake/testtask' Rake::TestTask.new(:test) do |test| test.libs << 'lib' << 'test' test.pattern = 'test/**/*_test.rb' end task :default => [:test] ================================================ FILE: bin/dashing ================================================ #!/usr/bin/env ruby require "pathname" bin_file = Pathname.new(__FILE__).realpath $:.unshift File.expand_path("../../lib", bin_file) require 'dashing/cli' require 'dashing/downloader' Dashing::CLI.source_root(File.expand_path('../../templates', bin_file)) Dashing::CLI.start(ARGV) ================================================ FILE: dashing.gemspec ================================================ # -*- encoding: utf-8 -*- Gem::Specification.new do |s| s.name = 'dashing' s.version = '1.3.7' s.date = '2016-04-11' s.executables = %w(dashing) s.summary = "The exceptionally handsome dashboard framework." s.description = "This framework lets you build & easily layout dashboards with your own custom widgets. Use it to make a status boards for your ops team, or use it to track signups, conversion rates, or whatever else metrics you'd like to see in one spot. Included with the framework are ready-made widgets for you to use or customize. All of this code was extracted out of a project at Shopify that displays dashboards on TVs around the office." s.author = "Daniel Beauchamp" s.email = 'daniel.beauchamp@shopify.com' s.homepage = 'http://shopify.github.com/dashing' s.license = "MIT" s.files = Dir['README.md', 'javascripts/**/*', 'templates/**/*','templates/**/.[a-z]*', 'lib/**/*'] s.add_dependency('sass', '~> 3.2.12') s.add_dependency('coffee-script', '~> 2.2.0') s.add_dependency('execjs', '~> 2.0.2') s.add_dependency('sinatra', '~> 1.4.4') s.add_dependency('sinatra-contrib', '~> 1.4.2') s.add_dependency('thin', '~> 1.6.1') s.add_dependency('rufus-scheduler', '~> 2.0.24') s.add_dependency('thor', '> 0.18.1') s.add_dependency('sprockets', '~> 2.10.1') s.add_dependency('rack', '~> 1.5.4') s.add_development_dependency('rake', '~> 10.1.0') s.add_development_dependency('haml', '~> 4.0.4') s.add_development_dependency('minitest', '~> 5.2.0') s.add_development_dependency('mocha', '~> 0.14.0') s.add_development_dependency('fakeweb', '~> 1.3.0') s.add_development_dependency('simplecov', '~> 0.8.2') end ================================================ FILE: javascripts/batman.jquery.js ================================================ (function() { Batman.extend(Batman.DOM, { querySelectorAll: function(node, selector) { return jQuery(selector, node); }, querySelector: function(node, selector) { return jQuery(selector, node)[0]; }, setInnerHTML: function(node, html) { var child, childNodes, result, _i, _j, _len, _len1; childNodes = (function() { var _i, _len, _ref, _results; _ref = node.childNodes; _results = []; for (_i = 0, _len = _ref.length; _i < _len; _i++) { child = _ref[_i]; _results.push(child); } return _results; })(); for (_i = 0, _len = childNodes.length; _i < _len; _i++) { child = childNodes[_i]; Batman.DOM.willRemoveNode(child); } result = jQuery(node).html(html); for (_j = 0, _len1 = childNodes.length; _j < _len1; _j++) { child = childNodes[_j]; Batman.DOM.didRemoveNode(child); } return result; }, removeNode: function(node) { var _ref; Batman.DOM.willRemoveNode(node); if ((_ref = node.parentNode) != null) { _ref.removeChild(node); } return Batman.DOM.didRemoveNode(node); }, destroyNode: function(node) { Batman.DOM.willDestroyNode(node); Batman.DOM.willRemoveNode(node); jQuery(node).remove(); Batman.DOM.didRemoveNode(node); return Batman.DOM.didDestroyNode(node); }, appendChild: function(parent, child) { Batman.DOM.willInsertNode(child); jQuery(parent).append(child); return Batman.DOM.didInsertNode(child); }, innerText: function(node) { return jQuery(node).text(); } }); Batman.Request.prototype._parseResponseHeaders = function(xhr) { var headers; return headers = xhr.getAllResponseHeaders().split('\n').reduce(function(acc, header) { var key, matches, value; if (matches = header.match(/([^:]*):\s*(.*)/)) { key = matches[1]; value = matches[2]; acc[key] = value; } return acc; }, {}); }; Batman.Request.prototype._prepareOptions = function(data) { var options, _ref, _this = this; options = { url: this.get('url'), type: this.get('method'), dataType: this.get('type'), data: data || this.get('data'), username: this.get('username'), password: this.get('password'), headers: this.get('headers'), beforeSend: function() { return _this.fire('loading'); }, success: function(response, textStatus, xhr) { _this.mixin({ xhr: xhr, status: xhr.status, response: response, responseHeaders: _this._parseResponseHeaders(xhr) }); return _this.fire('success', response); }, error: function(xhr, status, error) { _this.mixin({ xhr: xhr, status: xhr.status, response: xhr.responseText, responseHeaders: _this._parseResponseHeaders(xhr) }); xhr.request = _this; return _this.fire('error', xhr); }, complete: function() { return _this.fire('loaded'); } }; if ((_ref = this.get('method')) === 'PUT' || _ref === 'POST') { if (!this.hasFileUploads()) { options.contentType = this.get('contentType'); if (typeof options.data === 'object') { options.processData = false; options.data = Batman.URI.queryFromParams(options.data); } } else { options.contentType = false; options.processData = false; options.data = this.constructor.objectToFormData(options.data); } } return options; }; Batman.Request.prototype.send = function(data) { return jQuery.ajax(this._prepareOptions(data)); }; Batman.mixins.animation = { show: function(addToParent) { var jq, show, _ref, _ref1; jq = $(this); show = function() { return jq.show(600); }; if (addToParent) { if ((_ref = addToParent.append) != null) { _ref.appendChild(this); } if ((_ref1 = addToParent.before) != null) { _ref1.parentNode.insertBefore(this, addToParent.before); } jq.hide(); setTimeout(show, 0); } else { show(); } return this; }, hide: function(removeFromParent) { var _this = this; $(this).hide(600, function() { var _ref; if (removeFromParent) { if ((_ref = _this.parentNode) != null) { _ref.removeChild(_this); } } return Batman.DOM.didRemoveNode(_this); }); return this; } }; }).call(this); ================================================ FILE: javascripts/batman.js ================================================ (function() { var Batman, __slice = [].slice; Batman = function() { var mixins; mixins = 1 <= arguments.length ? __slice.call(arguments, 0) : []; return (function(func, args, ctor) { ctor.prototype = func.prototype; var child = new ctor, result = func.apply(child, args), t = typeof result; return t == "object" || t == "function" ? result || child : child; })(Batman.Object, mixins, function() {}); }; Batman.version = '0.14.1'; Batman.config = { pathPrefix: '/', viewPrefix: 'views', fetchRemoteViews: true, usePushState: false, minificationErrors: true }; (Batman.container = (function() { return this; })()).Batman = Batman; if (typeof define === 'function') { define('batman', [], function() { return Batman; }); } Batman.exportHelpers = function(onto) { var k, _i, _len, _ref; _ref = ['mixin', 'extend', 'unmixin', 'redirect', 'typeOf', 'redirect', 'setImmediate', 'clearImmediate']; for (_i = 0, _len = _ref.length; _i < _len; _i++) { k = _ref[_i]; onto["$" + k] = Batman[k]; } return onto; }; Batman.exportGlobals = function() { return Batman.exportHelpers(Batman.container); }; }).call(this); (function() { var _Batman; Batman._Batman = _Batman = (function() { function _Batman(object) { this.object = object; } _Batman.prototype.check = function(object) { if (object !== this.object) { object._batman = new Batman._Batman(object); return false; } return true; }; _Batman.prototype.get = function(key) { var reduction, results; results = this.getAll(key); switch (results.length) { case 0: return void 0; case 1: return results[0]; default: reduction = results[0].concat != null ? function(a, b) { return a.concat(b); } : results[0].merge != null ? function(a, b) { return a.merge(b); } : results.every(function(x) { return typeof x === 'object'; }) ? (results.unshift({}), function(a, b) { return Batman.extend(a, b); }) : void 0; if (reduction) { return results.reduceRight(reduction); } else { return results; } } }; _Batman.prototype.getFirst = function(key) { var results; results = this.getAll(key); return results[0]; }; _Batman.prototype.getAll = function(keyOrGetter) { var getter, results, val; if (typeof keyOrGetter === 'function') { getter = keyOrGetter; } else { getter = function(ancestor) { var _ref; return (_ref = ancestor._batman) != null ? _ref[keyOrGetter] : void 0; }; } results = this.ancestors(getter); if (val = getter(this.object)) { results.unshift(val); } return results; }; _Batman.prototype.ancestors = function(getter) { var ancestor, results, val, _i, _len, _ref; this._allAncestors || (this._allAncestors = this.allAncestors()); if (getter) { results = []; _ref = this._allAncestors; for (_i = 0, _len = _ref.length; _i < _len; _i++) { ancestor = _ref[_i]; val = getter(ancestor); if (val != null) { results.push(val); } } return results; } else { return this._allAncestors; } }; _Batman.prototype.allAncestors = function() { var isClass, parent, proto, results, _ref, _ref1; results = []; isClass = !! this.object.prototype; parent = isClass ? (_ref = this.object.__super__) != null ? _ref.constructor : void 0 : (proto = Object.getPrototypeOf(this.object)) === this.object ? this.object.constructor.__super__ : proto; if (parent != null) { if ((_ref1 = parent._batman) != null) { _ref1.check(parent); } results.push(parent); if (parent._batman != null) { results = results.concat(parent._batman.allAncestors()); } } return results; }; _Batman.prototype.set = function(key, value) { return this[key] = value; }; return _Batman; })(); }).call(this); (function() { var chr, _encodedChars, _encodedCharsPattern, _entityMap, _implementImmediates, _objectToString, _unsafeChars, _unsafeCharsPattern, __slice = [].slice, __hasProp = {}.hasOwnProperty, __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; Batman.typeOf = function(object) { if (typeof object === 'undefined') { return "Undefined"; } return _objectToString.call(object).slice(8, -1); }; _objectToString = Object.prototype.toString; Batman.extend = function() { var key, object, objects, to, value, _i, _len; to = arguments[0], objects = 2 <= arguments.length ? __slice.call(arguments, 1) : []; for (_i = 0, _len = objects.length; _i < _len; _i++) { object = objects[_i]; for (key in object) { value = object[key]; to[key] = value; } } return to; }; Batman.mixin = function() { var hasSet, key, mixin, mixins, to, value, _i, _len; to = arguments[0], mixins = 2 <= arguments.length ? __slice.call(arguments, 1) : []; hasSet = typeof to.set === 'function'; for (_i = 0, _len = mixins.length; _i < _len; _i++) { mixin = mixins[_i]; if (Batman.typeOf(mixin) !== 'Object') { continue; } for (key in mixin) { if (!__hasProp.call(mixin, key)) continue; value = mixin[key]; if (key === 'initialize' || key === 'uninitialize' || key === 'prototype') { continue; } if (hasSet) { to.set(key, value); } else if (to.nodeName != null) { Batman.data(to, key, value); } else { to[key] = value; } } if (typeof mixin.initialize === 'function') { mixin.initialize.call(to); } } return to; }; Batman.unmixin = function() { var from, key, mixin, mixins, _i, _len; from = arguments[0], mixins = 2 <= arguments.length ? __slice.call(arguments, 1) : []; for (_i = 0, _len = mixins.length; _i < _len; _i++) { mixin = mixins[_i]; for (key in mixin) { if (key === 'initialize' || key === 'uninitialize') { continue; } delete from[key]; } if (typeof mixin.uninitialize === 'function') { mixin.uninitialize.call(from); } } return from; }; Batman._functionName = Batman.functionName = function(f) { var _ref; if (f.__name__) { return f.__name__; } if (f.name) { return f.name; } return (_ref = f.toString().match(/\W*function\s+([\w\$]+)\(/)) != null ? _ref[1] : void 0; }; Batman._isChildOf = Batman.isChildOf = function(parentNode, childNode) { var node; node = childNode.parentNode; while (node) { if (node === parentNode) { return true; } node = node.parentNode; } return false; }; _implementImmediates = function(container) { var canUsePostMessage, count, functions, getHandle, handler, prefix, tasks; canUsePostMessage = function() { var async, oldMessage; if (!container.postMessage) { return false; } async = true; oldMessage = container.onmessage; container.onmessage = function() { return async = false; }; container.postMessage("", "*"); container.onmessage = oldMessage; return async; }; tasks = new Batman.SimpleHash; count = 0; getHandle = function() { return "go" + (++count); }; if (container.setImmediate && container.clearImmediate) { Batman.setImmediate = container.setImmediate; return Batman.clearImmediate = container.clearImmediate; } else if (canUsePostMessage()) { prefix = 'com.batman.'; functions = new Batman.SimpleHash; handler = function(e) { var handle, _base; if (!~e.data.search(prefix)) { return; } handle = e.data.substring(prefix.length); return typeof(_base = tasks.unset(handle)) === "function" ? _base() : void 0; }; if (container.addEventListener) { container.addEventListener('message', handler, false); } else { container.attachEvent('onmessage', handler); } Batman.setImmediate = function(f) { var handle; tasks.set(handle = getHandle(), f); container.postMessage(prefix + handle, "*"); return handle; }; return Batman.clearImmediate = function(handle) { return tasks.unset(handle); }; } else if (typeof document !== 'undefined' && __indexOf.call(document.createElement("script"), "onreadystatechange") >= 0) { Batman.setImmediate = function(f) { var handle, script; handle = getHandle(); script = document.createElement("script"); script.onreadystatechange = function() { var _base; if (typeof(_base = tasks.get(handle)) === "function") { _base(); } script.onreadystatechange = null; script.parentNode.removeChild(script); return script = null; }; document.documentElement.appendChild(script); return handle; }; return Batman.clearImmediate = function(handle) { return tasks.unset(handle); }; } else if (typeof process !== "undefined" && process !== null ? process.nextTick : void 0) { functions = {}; Batman.setImmediate = function(f) { var handle; handle = getHandle(); functions[handle] = f; process.nextTick(function() { if (typeof functions[handle] === "function") { functions[handle](); } return delete functions[handle]; }); return handle; }; return Batman.clearImmediate = function(handle) { return delete functions[handle]; }; } else { Batman.setImmediate = function(f) { return setTimeout(f, 0); }; return Batman.clearImmediate = function(handle) { return clearTimeout(handle); }; } }; Batman.setImmediate = function() { _implementImmediates(Batman.container); return Batman.setImmediate.apply(this, arguments); }; Batman.clearImmediate = function() { _implementImmediates(Batman.container); return Batman.clearImmediate.apply(this, arguments); }; Batman.forEach = function(container, iterator, ctx) { var e, i, k, v, _i, _len, _results, _results1; if (container.forEach) { return container.forEach(iterator, ctx); } else if (container.indexOf) { _results = []; for (i = _i = 0, _len = container.length; _i < _len; i = ++_i) { e = container[i]; _results.push(iterator.call(ctx, e, i, container)); } return _results; } else { _results1 = []; for (k in container) { v = container[k]; _results1.push(iterator.call(ctx, k, v, container)); } return _results1; } }; Batman.objectHasKey = function(object, key) { if (typeof object.hasKey === 'function') { return object.hasKey(key); } else { return key in object; } }; Batman.contains = function(container, item) { if (container.indexOf) { return __indexOf.call(container, item) >= 0; } else if (typeof container.has === 'function') { return container.has(item); } else { return Batman.objectHasKey(container, item); } }; Batman.get = function(base, key) { if (typeof base.get === 'function') { return base.get(key); } else { return Batman.Property.forBaseAndKey(base, key).getValue(); } }; Batman.getPath = function(base, segments) { var segment, _i, _len; for (_i = 0, _len = segments.length; _i < _len; _i++) { segment = segments[_i]; if (base != null) { base = Batman.get(base, segment); if (base == null) { return base; } } else { return void 0; } } return base; }; _entityMap = { "&": "&", "<": "<", ">": ">", "\"": """, "'": "'" }; _unsafeChars = []; _encodedChars = []; for (chr in _entityMap) { _unsafeChars.push(chr); _encodedChars.push(_entityMap[chr]); } _unsafeCharsPattern = new RegExp("[" + (_unsafeChars.join('')) + "]", "g"); _encodedCharsPattern = new RegExp("(" + (_encodedChars.join('|')) + ")", "g"); Batman.escapeHTML = (function() { return function(s) { return ("" + s).replace(_unsafeCharsPattern, function(c) { return _entityMap[c]; }); }; })(); Batman.unescapeHTML = (function() { return function(s) { var node; if (s == null) { return; } node = Batman._unescapeHTMLNode || (Batman._unescapeHTMLNode = document.createElement('DIV')); node.innerHTML = s; return Batman.DOM.innerText(node); }; })(); Batman.translate = function(x, values) { if (values == null) { values = {}; } return Batman.helpers.interpolate(Batman.get(Batman.translate.messages, x), values); }; Batman.translate.messages = {}; Batman.t = function() { return Batman.translate.apply(Batman, arguments); }; Batman.redirect = function(url) { var _ref; return (_ref = Batman.navigator) != null ? _ref.redirect(url) : void 0; }; Batman.initializeObject = function(object) { if (object._batman != null) { return object._batman.check(object); } else { return object._batman = new Batman._Batman(object); } }; }).call(this); (function() { var __slice = [].slice, __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; Batman.Inflector = (function() { Inflector.prototype.plural = function(regex, replacement) { return this._plural.unshift([regex, replacement]); }; Inflector.prototype.singular = function(regex, replacement) { return this._singular.unshift([regex, replacement]); }; Inflector.prototype.human = function(regex, replacement) { return this._human.unshift([regex, replacement]); }; Inflector.prototype.uncountable = function() { var strings; strings = 1 <= arguments.length ? __slice.call(arguments, 0) : []; return this._uncountable = this._uncountable.concat(strings.map(function(x) { return new RegExp("" + x + "$", 'i'); })); }; Inflector.prototype.irregular = function(singular, plural) { if (singular.charAt(0) === plural.charAt(0)) { this.plural(new RegExp("(" + (singular.charAt(0)) + ")" + (singular.slice(1)) + "$", "i"), "$1" + plural.slice(1)); this.plural(new RegExp("(" + (singular.charAt(0)) + ")" + (plural.slice(1)) + "$", "i"), "$1" + plural.slice(1)); return this.singular(new RegExp("(" + (plural.charAt(0)) + ")" + (plural.slice(1)) + "$", "i"), "$1" + singular.slice(1)); } else { this.plural(new RegExp("" + singular + "$", 'i'), plural); this.plural(new RegExp("" + plural + "$", 'i'), plural); return this.singular(new RegExp("" + plural + "$", 'i'), singular); } }; function Inflector() { this._plural = []; this._singular = []; this._uncountable = []; this._human = []; } Inflector.prototype.ordinalize = function(number) { var absNumber, _ref; absNumber = Math.abs(parseInt(number)); if (_ref = absNumber % 100, __indexOf.call([11, 12, 13], _ref) >= 0) { return number + "th"; } else { switch (absNumber % 10) { case 1: return number + "st"; case 2: return number + "nd"; case 3: return number + "rd"; default: return number + "th"; } } }; Inflector.prototype.pluralize = function(word) { var regex, replace_string, uncountableRegex, _i, _j, _len, _len1, _ref, _ref1, _ref2; _ref = this._uncountable; for (_i = 0, _len = _ref.length; _i < _len; _i++) { uncountableRegex = _ref[_i]; if (uncountableRegex.test(word)) { return word; } } _ref1 = this._plural; for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { _ref2 = _ref1[_j], regex = _ref2[0], replace_string = _ref2[1]; if (regex.test(word)) { return word.replace(regex, replace_string); } } return word; }; Inflector.prototype.singularize = function(word) { var regex, replace_string, uncountableRegex, _i, _j, _len, _len1, _ref, _ref1, _ref2; _ref = this._uncountable; for (_i = 0, _len = _ref.length; _i < _len; _i++) { uncountableRegex = _ref[_i]; if (uncountableRegex.test(word)) { return word; } } _ref1 = this._singular; for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { _ref2 = _ref1[_j], regex = _ref2[0], replace_string = _ref2[1]; if (regex.test(word)) { return word.replace(regex, replace_string); } } return word; }; Inflector.prototype.humanize = function(word) { var regex, replace_string, _i, _len, _ref, _ref1; _ref = this._human; for (_i = 0, _len = _ref.length; _i < _len; _i++) { _ref1 = _ref[_i], regex = _ref1[0], replace_string = _ref1[1]; if (regex.test(word)) { return word.replace(regex, replace_string); } } return word; }; return Inflector; })(); }).call(this); (function() { var Inflector, camelize_rx, capitalize_rx, humanize_rx1, humanize_rx2, humanize_rx3, underscore_rx1, underscore_rx2; camelize_rx = /(?:^|_|\-)(.)/g; capitalize_rx = /(^|\s)([a-z])/g; underscore_rx1 = /([A-Z]+)([A-Z][a-z])/g; underscore_rx2 = /([a-z\d])([A-Z])/g; humanize_rx1 = /_id$/; humanize_rx2 = /_|-/g; humanize_rx3 = /^\w/g; Batman.helpers = { ordinalize: function() { return Batman.helpers.inflector.ordinalize.apply(Batman.helpers.inflector, arguments); }, singularize: function() { return Batman.helpers.inflector.singularize.apply(Batman.helpers.inflector, arguments); }, pluralize: function(count, singular, plural, includeCount) { var result; if (includeCount == null) { includeCount = true; } if (arguments.length < 2) { return Batman.helpers.inflector.pluralize(count); } else { result = +count === 1 ? singular : plural || Batman.helpers.inflector.pluralize(singular); if (includeCount) { result = ("" + (count || 0) + " ") + result; } return result; } }, camelize: function(string, firstLetterLower) { string = string.replace(camelize_rx, function(str, p1) { return p1.toUpperCase(); }); if (firstLetterLower) { return string.substr(0, 1).toLowerCase() + string.substr(1); } else { return string; } }, underscore: function(string) { return string.replace(underscore_rx1, '$1_$2').replace(underscore_rx2, '$1_$2').replace('-', '_').toLowerCase(); }, capitalize: function(string) { return string.replace(capitalize_rx, function(m, p1, p2) { return p1 + p2.toUpperCase(); }); }, trim: function(string) { if (string) { return string.trim(); } else { return ""; } }, interpolate: function(stringOrObject, keys) { var key, string, value; if (typeof stringOrObject === 'object') { string = stringOrObject[keys.count]; if (!string) { string = stringOrObject['other']; } } else { string = stringOrObject; } for (key in keys) { value = keys[key]; string = string.replace(new RegExp("%\\{" + key + "\\}", "g"), value); } return string; }, humanize: function(string) { string = Batman.helpers.underscore(string); string = Batman.helpers.inflector.humanize(string); return string.replace(humanize_rx1, '').replace(humanize_rx2, ' ').replace(humanize_rx3, function(match) { return match.toUpperCase(); }); } }; Inflector = new Batman.Inflector; Batman.helpers.inflector = Inflector; Inflector.plural(/$/, 's'); Inflector.plural(/s$/i, 's'); Inflector.plural(/(ax|test)is$/i, '$1es'); Inflector.plural(/(octop|vir)us$/i, '$1i'); Inflector.plural(/(octop|vir)i$/i, '$1i'); Inflector.plural(/(alias|status)$/i, '$1es'); Inflector.plural(/(bu)s$/i, '$1ses'); Inflector.plural(/(buffal|tomat)o$/i, '$1oes'); Inflector.plural(/([ti])um$/i, '$1a'); Inflector.plural(/([ti])a$/i, '$1a'); Inflector.plural(/sis$/i, 'ses'); Inflector.plural(/(?:([^f])fe|([lr])f)$/i, '$1$2ves'); Inflector.plural(/(hive)$/i, '$1s'); Inflector.plural(/([^aeiouy]|qu)y$/i, '$1ies'); Inflector.plural(/(x|ch|ss|sh)$/i, '$1es'); Inflector.plural(/(matr|vert|ind)(?:ix|ex)$/i, '$1ices'); Inflector.plural(/([m|l])ouse$/i, '$1ice'); Inflector.plural(/([m|l])ice$/i, '$1ice'); Inflector.plural(/^(ox)$/i, '$1en'); Inflector.plural(/^(oxen)$/i, '$1'); Inflector.plural(/(quiz)$/i, '$1zes'); Inflector.singular(/s$/i, ''); Inflector.singular(/(n)ews$/i, '$1ews'); Inflector.singular(/([ti])a$/i, '$1um'); Inflector.singular(/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i, '$1$2sis'); Inflector.singular(/(^analy)ses$/i, '$1sis'); Inflector.singular(/([^f])ves$/i, '$1fe'); Inflector.singular(/(hive)s$/i, '$1'); Inflector.singular(/(tive)s$/i, '$1'); Inflector.singular(/([lr])ves$/i, '$1f'); Inflector.singular(/([^aeiouy]|qu)ies$/i, '$1y'); Inflector.singular(/(s)eries$/i, '$1eries'); Inflector.singular(/(m)ovies$/i, '$1ovie'); Inflector.singular(/(x|ch|ss|sh)es$/i, '$1'); Inflector.singular(/([m|l])ice$/i, '$1ouse'); Inflector.singular(/(bus)es$/i, '$1'); Inflector.singular(/(o)es$/i, '$1'); Inflector.singular(/(shoe)s$/i, '$1'); Inflector.singular(/(cris|ax|test)es$/i, '$1is'); Inflector.singular(/(octop|vir)i$/i, '$1us'); Inflector.singular(/(alias|status)es$/i, '$1'); Inflector.singular(/^(ox)en/i, '$1'); Inflector.singular(/(vert|ind)ices$/i, '$1ex'); Inflector.singular(/(matr)ices$/i, '$1ix'); Inflector.singular(/(quiz)zes$/i, '$1'); Inflector.singular(/(database)s$/i, '$1'); Inflector.irregular('person', 'people'); Inflector.irregular('man', 'men'); Inflector.irregular('child', 'children'); Inflector.irregular('sex', 'sexes'); Inflector.irregular('move', 'moves'); Inflector.irregular('cow', 'kine'); Inflector.irregular('zombie', 'zombies'); Inflector.uncountable('equipment', 'information', 'rice', 'money', 'species', 'series', 'fish', 'sheep', 'jeans'); }).call(this); (function() { var developer; Batman.developer = { suppressed: false, DevelopmentError: (function() { var DevelopmentError; DevelopmentError = function(message) { this.message = message; return this.name = "DevelopmentError"; }; DevelopmentError.prototype = Error.prototype; return DevelopmentError; })(), _ie_console: function(f, args) { var arg, _i, _len, _results; if (args.length !== 1) { if (typeof console !== "undefined" && console !== null) { console[f]("..." + f + " of " + args.length + " items..."); } } _results = []; for (_i = 0, _len = args.length; _i < _len; _i++) { arg = args[_i]; _results.push(typeof console !== "undefined" && console !== null ? console[f](arg) : void 0); } return _results; }, suppress: function(f) { developer.suppressed = true; if (f) { f(); return developer.suppressed = false; } }, unsuppress: function() { return developer.suppressed = false; }, log: function() { if (developer.suppressed || !((typeof console !== "undefined" && console !== null ? console.log : void 0) != null)) { return; } if (console.log.apply) { return console.log.apply(console, arguments); } else { return developer._ie_console("log", arguments); } }, warn: function() { if (developer.suppressed || !((typeof console !== "undefined" && console !== null ? console.warn : void 0) != null)) { return; } if (console.warn.apply) { return console.warn.apply(console, arguments); } else { return developer._ie_console("warn", arguments); } }, error: function(message) { throw new developer.DevelopmentError(message); }, assert: function(result, message) { if (!result) { return developer.error(message); } }, "do": function(f) { if (!developer.suppressed) { return f(); } }, addFilters: function() { return Batman.extend(Batman.Filters, { log: function(value, key) { if (typeof console !== "undefined" && console !== null) { if (typeof console.log === "function") { console.log(arguments); } } return value; }, logStack: function(value) { if (typeof console !== "undefined" && console !== null) { if (typeof console.log === "function") { console.log(developer.currentFilterStack); } } return value; } }); }, deprecated: function(deprecatedName, upgradeString) { return Batman.developer.warn("" + deprecatedName + " has been deprecated.", upgradeString || ''); } }; developer = Batman.developer; Batman.developer.assert((function() {}).bind, "Error! Batman needs Function.bind to work! Please shim it using something like es5-shim or augmentjs!"); }).call(this); (function() { Batman.Event = (function() { Event.forBaseAndKey = function(base, key) { if (base.isEventEmitter) { return base.event(key); } else { return new Batman.Event(base, key); } }; function Event(base, key) { this.base = base; this.key = key; this._preventCount = 0; } Event.prototype.isEvent = true; Event.prototype.isEqual = function(other) { return this.constructor === other.constructor && this.base === other.base && this.key === other.key; }; Event.prototype.hashKey = function() { var key; this.hashKey = function() { return key; }; return key = ""; }; Event.prototype.addHandler = function(handler) { this.handlers || (this.handlers = []); if (this.handlers.indexOf(handler) === -1) { this.handlers.push(handler); } if (this.oneShot) { this.autofireHandler(handler); } return this; }; Event.prototype.removeHandler = function(handler) { var index; if (this.handlers && (index = this.handlers.indexOf(handler)) !== -1) { this.handlers.splice(index, 1); } return this; }; Event.prototype.eachHandler = function(iterator) { var ancestor, key, _i, _len, _ref, _ref1, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7, _results; if ((_ref = this.handlers) != null) { _ref.slice().forEach(iterator); } if ((_ref1 = this.base) != null ? _ref1.isEventEmitter : void 0) { key = this.key; _ref3 = (_ref2 = this.base._batman) != null ? _ref2.ancestors() : void 0; _results = []; for (_i = 0, _len = _ref3.length; _i < _len; _i++) { ancestor = _ref3[_i]; if (ancestor.isEventEmitter && ((_ref4 = ancestor._batman) != null ? (_ref5 = _ref4.events) != null ? _ref5.hasOwnProperty(key) : void 0 : void 0)) { _results.push((_ref6 = ancestor.event(key, false)) != null ? (_ref7 = _ref6.handlers) != null ? _ref7.slice().forEach(iterator) : void 0 : void 0); } else { _results.push(void 0); } } return _results; } }; Event.prototype.clearHandlers = function() { return this.handlers = void 0; }; Event.prototype.handlerContext = function() { return this.base; }; Event.prototype.prevent = function() { return ++this._preventCount; }; Event.prototype.allow = function() { if (this._preventCount) { --this._preventCount; } return this._preventCount; }; Event.prototype.isPrevented = function() { return this._preventCount > 0; }; Event.prototype.autofireHandler = function(handler) { if (this._oneShotFired && (this._oneShotArgs != null)) { return handler.apply(this.handlerContext(), this._oneShotArgs); } }; Event.prototype.resetOneShot = function() { this._oneShotFired = false; return this._oneShotArgs = null; }; Event.prototype.fire = function() { return this.fireWithContext(this.handlerContext(), arguments); }; Event.prototype.fireWithContext = function(context, args) { if (this.isPrevented() || this._oneShotFired) { return false; } if (this.oneShot) { this._oneShotFired = true; this._oneShotArgs = args; } return this.eachHandler(function(handler) { return handler.apply(context, args); }); }; Event.prototype.allowAndFire = function() { return this.allowAndFireWithContext(this.handlerContext, arguments); }; Event.prototype.allowAndFireWithContext = function(context, args) { this.allow(); return this.fireWithContext(context, args); }; return Event; })(); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Batman.PropertyEvent = (function(_super) { __extends(PropertyEvent, _super); function PropertyEvent() { return PropertyEvent.__super__.constructor.apply(this, arguments); } PropertyEvent.prototype.eachHandler = function(iterator) { return this.base.eachObserver(iterator); }; PropertyEvent.prototype.handlerContext = function() { return this.base.base; }; return PropertyEvent; })(Batman.Event); }).call(this); (function() { var __slice = [].slice; Batman.EventEmitter = { isEventEmitter: true, hasEvent: function(key) { var _ref, _ref1; return (_ref = this._batman) != null ? typeof _ref.get === "function" ? (_ref1 = _ref.get('events')) != null ? _ref1.hasOwnProperty(key) : void 0 : void 0 : void 0; }, event: function(key, createEvent) { var ancestor, eventClass, events, existingEvent, newEvent, _base, _i, _len, _ref, _ref1, _ref2, _ref3; if (createEvent == null) { createEvent = true; } Batman.initializeObject(this); eventClass = this.eventClass || Batman.Event; if ((_ref = this._batman.events) != null ? _ref.hasOwnProperty(key) : void 0) { return existingEvent = this._batman.events[key]; } else { _ref1 = this._batman.ancestors(); for (_i = 0, _len = _ref1.length; _i < _len; _i++) { ancestor = _ref1[_i]; existingEvent = (_ref2 = ancestor._batman) != null ? (_ref3 = _ref2.events) != null ? _ref3[key] : void 0 : void 0; if (existingEvent) { break; } } if (createEvent || (existingEvent != null ? existingEvent.oneShot : void 0)) { events = (_base = this._batman).events || (_base.events = {}); newEvent = events[key] = new eventClass(this, key); newEvent.oneShot = existingEvent != null ? existingEvent.oneShot : void 0; return newEvent; } else { return existingEvent; } } }, on: function() { var handler, key, keys, _i, _j, _len, _results; keys = 2 <= arguments.length ? __slice.call(arguments, 0, _i = arguments.length - 1) : (_i = 0, []), handler = arguments[_i++]; _results = []; for (_j = 0, _len = keys.length; _j < _len; _j++) { key = keys[_j]; _results.push(this.event(key).addHandler(handler)); } return _results; }, once: function(key, handler) { var event, handlerWrapper; event = this.event(key); handlerWrapper = function() { handler.apply(this, arguments); return event.removeHandler(handlerWrapper); }; return event.addHandler(handlerWrapper); }, registerAsMutableSource: function() { return Batman.Property.registerSource(this); }, mutation: function(wrappedFunction) { return function() { var result, _ref; result = wrappedFunction.apply(this, arguments); if ((_ref = this.event('change', false)) != null) { _ref.fire(this, this); } return result; }; }, prevent: function(key) { this.event(key).prevent(); return this; }, allow: function(key) { this.event(key).allow(); return this; }, isPrevented: function(key) { var _ref; return (_ref = this.event(key, false)) != null ? _ref.isPrevented() : void 0; }, fire: function() { var args, key, _ref; key = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : []; return (_ref = this.event(key, false)) != null ? _ref.fireWithContext(this, args) : void 0; }, allowAndFire: function() { var args, key, _ref; key = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : []; return (_ref = this.event(key, false)) != null ? _ref.allowAndFireWithContext(this, args) : void 0; } }; }).call(this); (function() { var __slice = [].slice; Batman.Enumerable = { isEnumerable: true, map: function(f, ctx) { var result; if (ctx == null) { ctx = Batman.container; } result = []; this.forEach(function() { return result.push(f.apply(ctx, arguments)); }); return result; }, mapToProperty: function(key) { var result; result = []; this.forEach(function(item) { return result.push(item.get(key)); }); return result; }, every: function(f, ctx) { var result; if (ctx == null) { ctx = Batman.container; } result = true; this.forEach(function() { return result = result && f.apply(ctx, arguments); }); return result; }, some: function(f, ctx) { var result; if (ctx == null) { ctx = Batman.container; } result = false; this.forEach(function() { return result = result || f.apply(ctx, arguments); }); return result; }, reduce: function(f, accumulator) { var count, initialValuePassed, self; count = 0; self = this; if (accumulator != null) { initialValuePassed = true; } else { initialValuePassed = false; } this.forEach(function() { if (!initialValuePassed) { accumulator = arguments[0]; initialValuePassed = true; return; } return accumulator = f.apply(null, [accumulator].concat(__slice.call(arguments), [count], [self])); }); return accumulator; }, filter: function(f) { var result, wrap; result = new this.constructor; if (result.add) { wrap = function(result, element) { if (f(element)) { result.add(element); } return result; }; } else if (result.set) { wrap = function(result, key, value) { if (f(key, value)) { result.set(key, value); } return result; }; } else { if (!result.push) { result = []; } wrap = function(result, element) { if (f(element)) { result.push(element); } return result; }; } return this.reduce(wrap, result); }, inGroupsOf: function(groupSize) { var current, i, result; result = []; current = false; i = 0; this.forEach(function(element) { if (i++ % groupSize === 0) { current = []; result.push(current); } return current.push(element); }); return result; } }; }).call(this); (function() { var _objectToString, __slice = [].slice; _objectToString = Object.prototype.toString; Batman.SimpleHash = (function() { function SimpleHash(obj) { this._storage = {}; this.length = 0; if (obj != null) { this.update(obj); } } Batman.extend(SimpleHash.prototype, Batman.Enumerable); SimpleHash.prototype.hasKey = function(key) { var pair, pairs, _i, _len; if (this.objectKey(key)) { if (!this._objectStorage) { return false; } if (pairs = this._objectStorage[this.hashKeyFor(key)]) { for (_i = 0, _len = pairs.length; _i < _len; _i++) { pair = pairs[_i]; if (this.equality(pair[0], key)) { return true; } } } return false; } else { key = this.prefixedKey(key); return this._storage.hasOwnProperty(key); } }; SimpleHash.prototype.get = function(key) { var pair, pairs, _i, _len; if (this.objectKey(key)) { if (!this._objectStorage) { return void 0; } if (pairs = this._objectStorage[this.hashKeyFor(key)]) { for (_i = 0, _len = pairs.length; _i < _len; _i++) { pair = pairs[_i]; if (this.equality(pair[0], key)) { return pair[1]; } } } } else { return this._storage[this.prefixedKey(key)]; } }; SimpleHash.prototype.set = function(key, val) { var pair, pairs, _base, _i, _len, _name; if (this.objectKey(key)) { this._objectStorage || (this._objectStorage = {}); pairs = (_base = this._objectStorage)[_name = this.hashKeyFor(key)] || (_base[_name] = []); for (_i = 0, _len = pairs.length; _i < _len; _i++) { pair = pairs[_i]; if (this.equality(pair[0], key)) { return pair[1] = val; } } this.length++; pairs.push([key, val]); return val; } else { key = this.prefixedKey(key); if (this._storage[key] == null) { this.length++; } return this._storage[key] = val; } }; SimpleHash.prototype.unset = function(key) { var hashKey, index, obj, pair, pairs, val, value, _i, _len, _ref; if (this.objectKey(key)) { if (!this._objectStorage) { return void 0; } hashKey = this.hashKeyFor(key); if (pairs = this._objectStorage[hashKey]) { for (index = _i = 0, _len = pairs.length; _i < _len; index = ++_i) { _ref = pairs[index], obj = _ref[0], value = _ref[1]; if (this.equality(obj, key)) { pair = pairs.splice(index, 1); if (!pairs.length) { delete this._objectStorage[hashKey]; } this.length--; return pair[0][1]; } } } } else { key = this.prefixedKey(key); val = this._storage[key]; if (this._storage[key] != null) { this.length--; delete this._storage[key]; } return val; } }; SimpleHash.prototype.getOrSet = function(key, valueFunction) { var currentValue; currentValue = this.get(key); if (!currentValue) { currentValue = valueFunction(); this.set(key, currentValue); } return currentValue; }; SimpleHash.prototype.prefixedKey = function(key) { return "_" + key; }; SimpleHash.prototype.unprefixedKey = function(key) { return key.slice(1); }; SimpleHash.prototype.hashKeyFor = function(obj) { var hashKey, typeString; if (hashKey = obj != null ? typeof obj.hashKey === "function" ? obj.hashKey() : void 0 : void 0) { return hashKey; } else { typeString = _objectToString.call(obj); if (typeString === "[object Array]") { return typeString; } else { return obj; } } }; SimpleHash.prototype.equality = function(lhs, rhs) { if (lhs === rhs) { return true; } if (lhs !== lhs && rhs !== rhs) { return true; } if ((lhs != null ? typeof lhs.isEqual === "function" ? lhs.isEqual(rhs) : void 0 : void 0) && (rhs != null ? typeof rhs.isEqual === "function" ? rhs.isEqual(lhs) : void 0 : void 0)) { return true; } return false; }; SimpleHash.prototype.objectKey = function(key) { return typeof key !== 'string'; }; SimpleHash.prototype.forEach = function(iterator, ctx) { var key, obj, results, value, values, _i, _len, _ref, _ref1, _ref2, _ref3; results = []; if (this._objectStorage) { _ref = this._objectStorage; for (key in _ref) { values = _ref[key]; _ref1 = values.slice(); for (_i = 0, _len = _ref1.length; _i < _len; _i++) { _ref2 = _ref1[_i], obj = _ref2[0], value = _ref2[1]; results.push(iterator.call(ctx, obj, value, this)); } } } _ref3 = this._storage; for (key in _ref3) { value = _ref3[key]; results.push(iterator.call(ctx, this.unprefixedKey(key), value, this)); } return results; }; SimpleHash.prototype.keys = function() { var result; result = []; Batman.SimpleHash.prototype.forEach.call(this, function(key) { return result.push(key); }); return result; }; SimpleHash.prototype.toArray = SimpleHash.prototype.keys; SimpleHash.prototype.clear = function() { this._storage = {}; delete this._objectStorage; return this.length = 0; }; SimpleHash.prototype.isEmpty = function() { return this.length === 0; }; SimpleHash.prototype.merge = function() { var hash, merged, others, _i, _len; others = 1 <= arguments.length ? __slice.call(arguments, 0) : []; merged = new this.constructor; others.unshift(this); for (_i = 0, _len = others.length; _i < _len; _i++) { hash = others[_i]; hash.forEach(function(obj, value) { return merged.set(obj, value); }); } return merged; }; SimpleHash.prototype.update = function(object) { var k, v, _results; _results = []; for (k in object) { v = object[k]; _results.push(this.set(k, v)); } return _results; }; SimpleHash.prototype.replace = function(object) { var _this = this; this.forEach(function(key, value) { if (!(key in object)) { return _this.unset(key); } }); return this.update(object); }; SimpleHash.prototype.toObject = function() { var key, obj, pair, value, _ref, _ref1; obj = {}; _ref = this._storage; for (key in _ref) { value = _ref[key]; obj[this.unprefixedKey(key)] = value; } if (this._objectStorage) { _ref1 = this._objectStorage; for (key in _ref1) { pair = _ref1[key]; obj[key] = pair[0][1]; } } return obj; }; SimpleHash.prototype.toJSON = SimpleHash.prototype.toObject; return SimpleHash; })(); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, __slice = [].slice; Batman.AssociationCurator = (function(_super) { __extends(AssociationCurator, _super); AssociationCurator.availableAssociations = ['belongsTo', 'hasOne', 'hasMany']; function AssociationCurator(model) { this.model = model; AssociationCurator.__super__.constructor.call(this); this._byTypeStorage = new Batman.SimpleHash; } AssociationCurator.prototype.add = function(association) { var associationTypeSet; this.set(association.label, association); if (!(associationTypeSet = this._byTypeStorage.get(association.associationType))) { associationTypeSet = new Batman.SimpleSet; this._byTypeStorage.set(association.associationType, associationTypeSet); } return associationTypeSet.add(association); }; AssociationCurator.prototype.getByType = function(type) { return this._byTypeStorage.get(type); }; AssociationCurator.prototype.getByLabel = function(label) { return this.get(label); }; AssociationCurator.prototype.reset = function() { this.forEach(function(label, association) { return association.reset(); }); return true; }; AssociationCurator.prototype.merge = function() { var others, result; others = 1 <= arguments.length ? __slice.call(arguments, 0) : []; result = AssociationCurator.__super__.merge.apply(this, arguments); result._byTypeStorage = this._byTypeStorage.merge(others.map(function(other) { return other._byTypeStorage; })); return result; }; AssociationCurator.prototype._markDirtyAttribute = function(key, oldValue) { var _ref; if ((_ref = this.lifecycle.get('state')) !== 'loading' && _ref !== 'creating' && _ref !== 'saving' && _ref !== 'saved') { if (this.lifecycle.startTransition('set')) { return this.dirtyKeys.set(key, oldValue); } else { throw new Batman.StateMachine.InvalidTransitionError("Can't set while in state " + (this.lifecycle.get('state'))); } } }; return AssociationCurator; })(Batman.SimpleHash); }).call(this); (function() { var __slice = [].slice; Batman.SimpleSet = (function() { function SimpleSet() { var item, itemsToAdd; this._storage = []; this.length = 0; itemsToAdd = (function() { var _i, _len, _results; _results = []; for (_i = 0, _len = arguments.length; _i < _len; _i++) { item = arguments[_i]; if (item != null) { _results.push(item); } } return _results; }).apply(this, arguments); if (itemsToAdd.length > 0) { this.add.apply(this, itemsToAdd); } } Batman.extend(SimpleSet.prototype, Batman.Enumerable); SimpleSet.prototype.has = function(item) { return !!(~this._indexOfItem(item)); }; SimpleSet.prototype.add = function() { var addedItems, item, items, _i, _len; items = 1 <= arguments.length ? __slice.call(arguments, 0) : []; addedItems = []; for (_i = 0, _len = items.length; _i < _len; _i++) { item = items[_i]; if (!(!~this._indexOfItem(item))) { continue; } this._storage.push(item); addedItems.push(item); } this.length = this._storage.length; if (this.fire && addedItems.length !== 0) { this.fire('change', this, this); this.fire.apply(this, ['itemsWereAdded'].concat(__slice.call(addedItems))); } return addedItems; }; SimpleSet.prototype.remove = function() { var index, item, items, removedItems, _i, _len; items = 1 <= arguments.length ? __slice.call(arguments, 0) : []; removedItems = []; for (_i = 0, _len = items.length; _i < _len; _i++) { item = items[_i]; if (!(~ (index = this._indexOfItem(item)))) { continue; } this._storage.splice(index, 1); removedItems.push(item); } this.length = this._storage.length; if (this.fire && removedItems.length !== 0) { this.fire('change', this, this); this.fire.apply(this, ['itemsWereRemoved'].concat(__slice.call(removedItems))); } return removedItems; }; SimpleSet.prototype.find = function(f) { var item, _i, _len, _ref; _ref = this._storage; for (_i = 0, _len = _ref.length; _i < _len; _i++) { item = _ref[_i]; if (f(item)) { return item; } } }; SimpleSet.prototype.forEach = function(iterator, ctx) { var key, _i, _len, _ref, _results; _ref = this._storage; _results = []; for (_i = 0, _len = _ref.length; _i < _len; _i++) { key = _ref[_i]; _results.push(iterator.call(ctx, key, null, this)); } return _results; }; SimpleSet.prototype.isEmpty = function() { return this.length === 0; }; SimpleSet.prototype.clear = function() { var items; items = this._storage; this._storage = []; this.length = 0; if (this.fire && items.length !== 0) { this.fire('change', this, this); this.fire.apply(this, ['itemsWereRemoved'].concat(__slice.call(items))); } return items; }; SimpleSet.prototype.replace = function(other) { try { if (typeof this.prevent === "function") { this.prevent('change'); } this.clear(); return this.add.apply(this, other.toArray()); } finally { if (typeof this.allowAndFire === "function") { this.allowAndFire('change', this, this); } } }; SimpleSet.prototype.toArray = function() { return this._storage.slice(); }; SimpleSet.prototype.merge = function() { var merged, others, set, _i, _len; others = 1 <= arguments.length ? __slice.call(arguments, 0) : []; merged = new this.constructor; others.unshift(this); for (_i = 0, _len = others.length; _i < _len; _i++) { set = others[_i]; set.forEach(function(v) { return merged.add(v); }); } return merged; }; SimpleSet.prototype.indexedBy = function(key) { this._indexes || (this._indexes = new Batman.SimpleHash); return this._indexes.get(key) || this._indexes.set(key, new Batman.SetIndex(this, key)); }; SimpleSet.prototype.indexedByUnique = function(key) { this._uniqueIndexes || (this._uniqueIndexes = new Batman.SimpleHash); return this._uniqueIndexes.get(key) || this._uniqueIndexes.set(key, new Batman.UniqueSetIndex(this, key)); }; SimpleSet.prototype.sortedBy = function(key, order) { var sortsForKey; if (order == null) { order = "asc"; } order = order.toLowerCase() === "desc" ? "desc" : "asc"; this._sorts || (this._sorts = new Batman.SimpleHash); sortsForKey = this._sorts.get(key) || this._sorts.set(key, new Batman.Object); return sortsForKey.get(order) || sortsForKey.set(order, new Batman.SetSort(this, key, order)); }; SimpleSet.prototype.equality = Batman.SimpleHash.prototype.equality; SimpleSet.prototype._indexOfItem = function(givenItem) { var index, item, _i, _len, _ref; _ref = this._storage; for (index = _i = 0, _len = _ref.length; _i < _len; index = ++_i) { item = _ref[index]; if (this.equality(givenItem, item)) { return index; } } return -1; }; return SimpleSet; })(); }).call(this); (function() { var SOURCE_TRACKER_STACK, SOURCE_TRACKER_STACK_VALID, __slice = [].slice; SOURCE_TRACKER_STACK = []; SOURCE_TRACKER_STACK_VALID = true; Batman.Property = (function() { Batman.mixin(Property.prototype, Batman.EventEmitter); Property._sourceTrackerStack = SOURCE_TRACKER_STACK; Property._sourceTrackerStackValid = SOURCE_TRACKER_STACK_VALID; Property.defaultAccessor = { get: function(key) { return this[key]; }, set: function(key, val) { return this[key] = val; }, unset: function(key) { var x; x = this[key]; delete this[key]; return x; }, cache: false }; Property.defaultAccessorForBase = function(base) { var _ref; return ((_ref = base._batman) != null ? _ref.getFirst('defaultAccessor') : void 0) || Batman.Property.defaultAccessor; }; Property.accessorForBaseAndKey = function(base, key) { var accessor, ancestor, _bm, _i, _len, _ref, _ref1, _ref2, _ref3; if ((_bm = base._batman) != null) { accessor = (_ref = _bm.keyAccessors) != null ? _ref.get(key) : void 0; if (!accessor) { _ref1 = _bm.ancestors(); for (_i = 0, _len = _ref1.length; _i < _len; _i++) { ancestor = _ref1[_i]; accessor = (_ref2 = ancestor._batman) != null ? (_ref3 = _ref2.keyAccessors) != null ? _ref3.get(key) : void 0 : void 0; if (accessor) { break; } } } } return accessor || this.defaultAccessorForBase(base); }; Property.forBaseAndKey = function(base, key) { if (base.isObservable) { return base.property(key); } else { return new Batman.Keypath(base, key); } }; Property.withoutTracking = function(block) { return this.wrapTrackingPrevention(block)(); }; Property.wrapTrackingPrevention = function(block) { return function() { Batman.Property.pushDummySourceTracker(); try { return block.apply(this, arguments); } finally { Batman.Property.popSourceTracker(); } }; }; Property.registerSource = function(obj) { var set; if (!obj.isEventEmitter) { return; } if (SOURCE_TRACKER_STACK_VALID) { set = SOURCE_TRACKER_STACK[SOURCE_TRACKER_STACK.length - 1]; } else { set = []; SOURCE_TRACKER_STACK.push(set); SOURCE_TRACKER_STACK_VALID = true; } if (set != null) { set.push(obj); } return void 0; }; Property.pushSourceTracker = function() { if (SOURCE_TRACKER_STACK_VALID) { return SOURCE_TRACKER_STACK_VALID = false; } else { return SOURCE_TRACKER_STACK.push([]); } }; Property.popSourceTracker = function() { if (SOURCE_TRACKER_STACK_VALID) { return SOURCE_TRACKER_STACK.pop(); } else { SOURCE_TRACKER_STACK_VALID = true; return void 0; } }; Property.pushDummySourceTracker = function() { if (!SOURCE_TRACKER_STACK_VALID) { SOURCE_TRACKER_STACK.push([]); SOURCE_TRACKER_STACK_VALID = true; } return SOURCE_TRACKER_STACK.push(null); }; function Property(base, key) { this.base = base; this.key = key; } Property.prototype._isolationCount = 0; Property.prototype.cached = false; Property.prototype.value = null; Property.prototype.sources = null; Property.prototype.isProperty = true; Property.prototype.isDead = false; Property.prototype.eventClass = Batman.PropertyEvent; Property.prototype.isEqual = function(other) { return this.constructor === other.constructor && this.base === other.base && this.key === other.key; }; Property.prototype.hashKey = function() { return this._hashKey || (this._hashKey = ""); }; Property.prototype.event = function(key) { var eventClass, _base; eventClass = this.eventClass || Batman.Event; this.events || (this.events = {}); (_base = this.events)[key] || (_base[key] = new eventClass(this, key)); return this.events[key]; }; Property.prototype.changeEvent = function() { return this._changeEvent || (this._changeEvent = this.event('change')); }; Property.prototype.accessor = function() { return this._accessor || (this._accessor = this.constructor.accessorForBaseAndKey(this.base, this.key)); }; Property.prototype.eachObserver = function(iterator) { var ancestor, handlers, key, object, property, _i, _j, _len, _len1, _ref, _ref1, _ref2, _results; key = this.key; handlers = (_ref = this.changeEvent().handlers) != null ? _ref.slice() : void 0; if (handlers) { for (_i = 0, _len = handlers.length; _i < _len; _i++) { object = handlers[_i]; iterator(object); } } if (this.base.isObservable) { _ref1 = this.base._batman.ancestors(); _results = []; for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { ancestor = _ref1[_j]; if (ancestor.isObservable && ancestor.hasProperty(key)) { property = ancestor.property(key); handlers = (_ref2 = property.changeEvent().handlers) != null ? _ref2.slice() : void 0; if (handlers) { _results.push((function() { var _k, _len2, _results1; _results1 = []; for (_k = 0, _len2 = handlers.length; _k < _len2; _k++) { object = handlers[_k]; _results1.push(iterator(object)); } return _results1; })()); } else { _results.push(void 0); } } else { _results.push(void 0); } } return _results; } }; Property.prototype.observers = function() { var results; results = []; this.eachObserver(function(observer) { return results.push(observer); }); return results; }; Property.prototype.hasObservers = function() { return this.observers().length > 0; }; Property.prototype.updateSourcesFromTracker = function() { var handler, newSources, source, _i, _j, _len, _len1, _ref, _ref1, _results; newSources = this.constructor.popSourceTracker(); handler = this.sourceChangeHandler(); if (this.sources) { _ref = this.sources; for (_i = 0, _len = _ref.length; _i < _len; _i++) { source = _ref[_i]; if (source != null) { source.event('change').removeHandler(handler); } } } this.sources = newSources; if (this.sources) { _ref1 = this.sources; _results = []; for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { source = _ref1[_j]; _results.push(source != null ? source.event('change').addHandler(handler) : void 0); } return _results; } }; Property.prototype.getValue = function() { this.registerAsMutableSource(); if (!this.isCached()) { this.constructor.pushSourceTracker(); try { this.value = this.valueFromAccessor(); this.cached = true; } finally { this.updateSourcesFromTracker(); } } return this.value; }; Property.prototype.isCachable = function() { var cacheable; if (this.isFinal()) { return true; } cacheable = this.accessor().cache; if (cacheable != null) { return !!cacheable; } else { return true; } }; Property.prototype.isCached = function() { return this.isCachable() && this.cached; }; Property.prototype.isFinal = function() { return !!this.accessor()['final']; }; Property.prototype.refresh = function() { var previousValue, value; this.cached = false; previousValue = this.value; value = this.getValue(); if (value !== previousValue && !this.isIsolated()) { this.fire(value, previousValue); } if (this.value !== void 0 && this.isFinal()) { return this.lockValue(); } }; Property.prototype.sourceChangeHandler = function() { var _this = this; this._sourceChangeHandler || (this._sourceChangeHandler = this._handleSourceChange.bind(this)); Batman.developer["do"](function() { return _this._sourceChangeHandler.property = _this; }); return this._sourceChangeHandler; }; Property.prototype._handleSourceChange = function() { if (this.isIsolated()) { return this._needsRefresh = true; } else if (!this.isFinal() && !this.hasObservers()) { return this.cached = false; } else { return this.refresh(); } }; Property.prototype.valueFromAccessor = function() { var _ref; return (_ref = this.accessor().get) != null ? _ref.call(this.base, this.key) : void 0; }; Property.prototype.setValue = function(val) { var set; if (!(set = this.accessor().set)) { return; } return this._changeValue(function() { return set.call(this.base, this.key, val); }); }; Property.prototype.unsetValue = function() { var unset; if (!(unset = this.accessor().unset)) { return; } return this._changeValue(function() { return unset.call(this.base, this.key); }); }; Property.prototype._changeValue = function(block) { var result; this.cached = false; this.constructor.pushDummySourceTracker(); try { result = block.apply(this); this.refresh(); } finally { this.constructor.popSourceTracker(); } if (!(this.isCached() || this.hasObservers())) { this.die(); } return result; }; Property.prototype.forget = function(handler) { if (handler != null) { return this.changeEvent().removeHandler(handler); } else { return this.changeEvent().clearHandlers(); } }; Property.prototype.observeAndFire = function(handler) { this.observe(handler); return handler.call(this.base, this.value, this.value, this.key); }; Property.prototype.observe = function(handler) { this.changeEvent().addHandler(handler); if (this.sources == null) { this.getValue(); } return this; }; Property.prototype.observeOnce = function(originalHandler) { var event, handler; event = this.changeEvent(); handler = function() { originalHandler.apply(this, arguments); return event.removeHandler(handler); }; event.addHandler(handler); if (this.sources == null) { this.getValue(); } return this; }; Property.prototype._removeHandlers = function() { var handler, source, _i, _len, _ref; handler = this.sourceChangeHandler(); if (this.sources) { _ref = this.sources; for (_i = 0, _len = _ref.length; _i < _len; _i++) { source = _ref[_i]; source.event('change').removeHandler(handler); } } delete this.sources; return this.changeEvent().clearHandlers(); }; Property.prototype.lockValue = function() { this._removeHandlers(); this.getValue = function() { return this.value; }; return this.setValue = this.unsetValue = this.refresh = this.observe = function() {}; }; Property.prototype.die = function() { var _ref, _ref1; this._removeHandlers(); if ((_ref = this.base._batman) != null) { if ((_ref1 = _ref.properties) != null) { _ref1.unset(this.key); } } return this.isDead = true; }; Property.prototype.fire = function() { var _ref; return (_ref = this.changeEvent()).fire.apply(_ref, __slice.call(arguments).concat([this.key])); }; Property.prototype.isolate = function() { if (this._isolationCount === 0) { this._preIsolationValue = this.getValue(); } return this._isolationCount++; }; Property.prototype.expose = function() { if (this._isolationCount === 1) { this._isolationCount--; if (this._needsRefresh) { this.value = this._preIsolationValue; this.refresh(); } else if (this.value !== this._preIsolationValue) { this.fire(this.value, this._preIsolationValue); } return this._preIsolationValue = null; } else if (this._isolationCount > 0) { return this._isolationCount--; } }; Property.prototype.isIsolated = function() { return this._isolationCount > 0; }; return Property; })(); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Batman.Keypath = (function(_super) { __extends(Keypath, _super); function Keypath(base, key) { if (typeof key === 'string') { this.segments = key.split('.'); this.depth = this.segments.length; } else { this.segments = [key]; this.depth = 1; } Keypath.__super__.constructor.apply(this, arguments); } Keypath.prototype.isCachable = function() { if (this.depth === 1) { return Keypath.__super__.isCachable.apply(this, arguments); } else { return true; } }; Keypath.prototype.terminalProperty = function() { var base; base = Batman.getPath(this.base, this.segments.slice(0, -1)); if (base == null) { return; } return Batman.Keypath.forBaseAndKey(base, this.segments[this.depth - 1]); }; Keypath.prototype.valueFromAccessor = function() { if (this.depth === 1) { return Keypath.__super__.valueFromAccessor.apply(this, arguments); } else { return Batman.getPath(this.base, this.segments); } }; Keypath.prototype.setValue = function(val) { var _ref; if (this.depth === 1) { return Keypath.__super__.setValue.apply(this, arguments); } else { return (_ref = this.terminalProperty()) != null ? _ref.setValue(val) : void 0; } }; Keypath.prototype.unsetValue = function() { var _ref; if (this.depth === 1) { return Keypath.__super__.unsetValue.apply(this, arguments); } else { return (_ref = this.terminalProperty()) != null ? _ref.unsetValue() : void 0; } }; return Keypath; })(Batman.Property); }).call(this); (function() { var __slice = [].slice; Batman.Observable = { isObservable: true, hasProperty: function(key) { var _ref, _ref1; return (_ref = this._batman) != null ? (_ref1 = _ref.properties) != null ? typeof _ref1.hasKey === "function" ? _ref1.hasKey(key) : void 0 : void 0 : void 0; }, property: function(key) { var properties, propertyClass, _base; Batman.initializeObject(this); propertyClass = this.propertyClass || Batman.Keypath; properties = (_base = this._batman).properties || (_base.properties = new Batman.SimpleHash); return properties.get(key) || properties.set(key, new propertyClass(this, key)); }, get: function(key) { return this.property(key).getValue(); }, set: function(key, val) { return this.property(key).setValue(val); }, unset: function(key) { return this.property(key).unsetValue(); }, getOrSet: Batman.SimpleHash.prototype.getOrSet, forget: function(key, observer) { var _ref; if (key) { this.property(key).forget(observer); } else { if ((_ref = this._batman.properties) != null) { _ref.forEach(function(key, property) { return property.forget(); }); } } return this; }, observe: function() { var args, key, _ref; key = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : []; (_ref = this.property(key)).observe.apply(_ref, args); return this; }, observeAndFire: function() { var args, key, _ref; key = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : []; (_ref = this.property(key)).observeAndFire.apply(_ref, args); return this; }, observeOnce: function() { var args, key, _ref; key = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : []; (_ref = this.property(key)).observeOnce.apply(_ref, args); return this; } }; }).call(this); (function() { Batman.DOM = { textInputTypes: ['text', 'search', 'tel', 'url', 'email', 'password'], scrollIntoView: function(elementID) { var _ref; return (_ref = document.getElementById(elementID)) != null ? typeof _ref.scrollIntoView === "function" ? _ref.scrollIntoView() : void 0 : void 0; }, partial: function(container, path, context, renderer) { var view; renderer.prevent('rendered'); view = new Batman.View({ source: path, context: context }); return view.on('ready', function() { Batman.DOM.setInnerHTML(container, ''); Batman.DOM.appendChild(container, view.get('node')); return renderer.allowAndFire('rendered'); }); }, propagateBindingEvent: function(binding, node) { var current, parentBinding, parentBindings, _i, _len; while ((current = (current || node).parentNode)) { parentBindings = Batman._data(current, 'bindings'); if (parentBindings != null) { for (_i = 0, _len = parentBindings.length; _i < _len; _i++) { parentBinding = parentBindings[_i]; if (typeof parentBinding.childBindingAdded === "function") { parentBinding.childBindingAdded(binding); } } } } }, propagateBindingEvents: function(newNode) { var binding, bindings, child, _i, _j, _len, _len1, _ref; _ref = newNode.childNodes; for (_i = 0, _len = _ref.length; _i < _len; _i++) { child = _ref[_i]; Batman.DOM.propagateBindingEvents(child); } if (bindings = Batman._data(newNode, 'bindings')) { for (_j = 0, _len1 = bindings.length; _j < _len1; _j++) { binding = bindings[_j]; Batman.DOM.propagateBindingEvent(binding, newNode); } } }, trackBinding: function(binding, node) { var bindings; if (bindings = Batman._data(node, 'bindings')) { bindings.push(binding); } else { Batman._data(node, 'bindings', [binding]); } Batman.DOM.fire('bindingAdded', binding); Batman.DOM.propagateBindingEvent(binding, node); return true; }, onParseExit: function(node, callback) { var set; set = Batman._data(node, 'onParseExit') || Batman._data(node, 'onParseExit', new Batman.SimpleSet); if (callback != null) { set.add(callback); } return set; }, forgetParseExit: function(node, callback) { return Batman.removeData(node, 'onParseExit', true); }, defineView: function(name, node) { var contents; contents = node.innerHTML; Batman.View.store.set(Batman.Navigator.normalizePath(name), contents); return contents; }, setStyleProperty: function(node, property, value, importance) { if (node.style.setProperty) { return node.style.setProperty(property, value, importance); } else { return node.style.setAttribute(property, value, importance); } }, removeOrDestroyNode: function(node) { var view; view = Batman._data(node, 'view'); view || (view = Batman._data(node, 'yielder')); if ((view != null) && view.get('cached')) { return Batman.DOM.removeNode(node); } else { return Batman.DOM.destroyNode(node); } }, insertBefore: function(parentNode, newNode, referenceNode) { if (referenceNode == null) { referenceNode = null; } if (!referenceNode || parentNode.childNodes.length <= 0) { return Batman.DOM.appendChild(parentNode, newNode); } else { Batman.DOM.willInsertNode(newNode); parentNode.insertBefore(newNode, referenceNode); return Batman.DOM.didInsertNode(newNode); } }, valueForNode: function(node, value, escapeValue) { var isSetting; if (value == null) { value = ''; } if (escapeValue == null) { escapeValue = true; } isSetting = arguments.length > 1; switch (node.nodeName.toUpperCase()) { case 'INPUT': case 'TEXTAREA': if (isSetting) { return node.value = value; } else { return node.value; } break; case 'SELECT': if (isSetting) { return node.value = value; } break; default: if (isSetting) { return Batman.DOM.setInnerHTML(node, escapeValue ? Batman.escapeHTML(value) : value); } else { return node.innerHTML; } } }, nodeIsEditable: function(node) { var _ref; return (_ref = node.nodeName.toUpperCase()) === 'INPUT' || _ref === 'TEXTAREA' || _ref === 'SELECT'; }, addEventListener: function(node, eventName, callback) { var listeners; if (!(listeners = Batman._data(node, 'listeners'))) { listeners = Batman._data(node, 'listeners', {}); } if (!listeners[eventName]) { listeners[eventName] = []; } listeners[eventName].push(callback); if (Batman.DOM.hasAddEventListener) { return node.addEventListener(eventName, callback, false); } else { return node.attachEvent("on" + eventName, callback); } }, removeEventListener: function(node, eventName, callback) { var eventListeners, index, listeners; if (listeners = Batman._data(node, 'listeners')) { if (eventListeners = listeners[eventName]) { index = eventListeners.indexOf(callback); if (index !== -1) { eventListeners.splice(index, 1); } } } if (Batman.DOM.hasAddEventListener) { return node.removeEventListener(eventName, callback, false); } else { return node.detachEvent('on' + eventName, callback); } }, hasAddEventListener: !! (typeof window !== "undefined" && window !== null ? window.addEventListener : void 0), preventDefault: function(e) { if (typeof e.preventDefault === "function") { return e.preventDefault(); } else { return e.returnValue = false; } }, stopPropagation: function(e) { if (e.stopPropagation) { return e.stopPropagation(); } else { return e.cancelBubble = true; } }, willInsertNode: function(node) { var child, view, _i, _len, _ref, _ref1; view = Batman._data(node, 'view'); if (view != null) { view.fire('beforeAppear', node); } if ((_ref = Batman.data(node, 'show')) != null) { _ref.call(node); } _ref1 = node.childNodes; for (_i = 0, _len = _ref1.length; _i < _len; _i++) { child = _ref1[_i]; Batman.DOM.willInsertNode(child); } return true; }, didInsertNode: function(node) { var child, view, _i, _len, _ref; view = Batman._data(node, 'view'); if (view) { view.fire('appear', node); view.applyYields(); } _ref = node.childNodes; for (_i = 0, _len = _ref.length; _i < _len; _i++) { child = _ref[_i]; Batman.DOM.didInsertNode(child); } return true; }, willRemoveNode: function(node) { var child, view, _i, _len, _ref, _ref1; view = Batman._data(node, 'view'); if (view) { view.fire('beforeDisappear', node); } if ((_ref = Batman.data(node, 'hide')) != null) { _ref.call(node); } _ref1 = node.childNodes; for (_i = 0, _len = _ref1.length; _i < _len; _i++) { child = _ref1[_i]; Batman.DOM.willRemoveNode(child); } return true; }, didRemoveNode: function(node) { var child, view, _i, _len, _ref; view = Batman._data(node, 'view'); if (view) { view.retractYields(); view.fire('disappear', node); } _ref = node.childNodes; for (_i = 0, _len = _ref.length; _i < _len; _i++) { child = _ref[_i]; Batman.DOM.didRemoveNode(child); } return true; }, willDestroyNode: function(node) { var child, view, _i, _len, _ref; view = Batman._data(node, 'view'); if (view) { view.fire('beforeDestroy', node); view.get('yields').forEach(function(name, actions) { var _i, _len, _results; _results = []; for (_i = 0, _len = actions.length; _i < _len; _i++) { node = actions[_i].node; _results.push(Batman.DOM.willDestroyNode(node)); } return _results; }); } _ref = node.childNodes; for (_i = 0, _len = _ref.length; _i < _len; _i++) { child = _ref[_i]; Batman.DOM.willDestroyNode(child); } return true; }, didDestroyNode: function(node) { var bindings, child, eventListeners, eventName, listeners, view, _i, _len, _ref; view = Batman._data(node, 'view'); if (view) { view.die(); } if (bindings = Batman._data(node, 'bindings')) { bindings.forEach(function(binding) { return binding.die(); }); } if (listeners = Batman._data(node, 'listeners')) { for (eventName in listeners) { eventListeners = listeners[eventName]; eventListeners.forEach(function(listener) { return Batman.DOM.removeEventListener(node, eventName, listener); }); } } Batman.removeData(node); Batman.removeData(node, void 0, true); _ref = node.childNodes; for (_i = 0, _len = _ref.length; _i < _len; _i++) { child = _ref[_i]; Batman.DOM.didDestroyNode(child); } return true; } }; Batman.mixin(Batman.DOM, Batman.EventEmitter, Batman.Observable); Batman.DOM.event('bindingAdded'); }).call(this); (function() { Batman.DOM.ReaderBindingDefinition = (function() { function ReaderBindingDefinition(node, keyPath, context, renderer) { this.node = node; this.keyPath = keyPath; this.context = context; this.renderer = renderer; } return ReaderBindingDefinition; })(); Batman.BindingDefinitionOnlyObserve = { Data: 'data', Node: 'node', All: 'all', None: 'none' }; Batman.DOM.readers = { target: function(definition) { definition.onlyObserve = Batman.BindingDefinitionOnlyObserve.Node; return Batman.DOM.readers.bind(definition); }, source: function(definition) { definition.onlyObserve = Batman.BindingDefinitionOnlyObserve.Data; return Batman.DOM.readers.bind(definition); }, bind: function(definition) { var bindingClass, node; node = definition.node; switch (node.nodeName.toLowerCase()) { case 'input': switch (node.getAttribute('type')) { case 'checkbox': definition.attr = 'checked'; Batman.DOM.attrReaders.bind(definition); return true; case 'radio': bindingClass = Batman.DOM.RadioBinding; break; case 'file': bindingClass = Batman.DOM.FileBinding; } break; case 'select': bindingClass = Batman.DOM.SelectBinding; } bindingClass || (bindingClass = Batman.DOM.ValueBinding); return new bindingClass(definition); }, context: function(definition) { return definition.context.descendWithDefinition(definition); }, mixin: function(definition) { definition.context = definition.context.descend(Batman.mixins); return new Batman.DOM.MixinBinding(definition); }, showif: function(definition) { return new Batman.DOM.ShowHideBinding(definition); }, hideif: function(definition) { definition.invert = true; return new Batman.DOM.ShowHideBinding(definition); }, insertif: function(definition) { return new Batman.DOM.InsertionBinding(definition); }, removeif: function(definition) { definition.invert = true; return new Batman.DOM.InsertionBinding(definition); }, route: function(definition) { return new Batman.DOM.RouteBinding(definition); }, view: function(definition) { return new Batman.DOM.ViewBinding(definition); }, partial: function(definition) { return Batman.DOM.partial(definition.node, definition.keyPath, definition.context, definition.renderer); }, defineview: function(definition) { var node; node = definition.node; Batman.DOM.onParseExit(node, function() { var _ref; return (_ref = node.parentNode) != null ? _ref.removeChild(node) : void 0; }); Batman.DOM.defineView(definition.keyPath, node); return { skipChildren: true }; }, renderif: function(definition) { return new Batman.DOM.DeferredRenderingBinding(definition); }, "yield": function(definition) { var keyPath, node; node = definition.node, keyPath = definition.keyPath; return Batman.DOM.onParseExit(node, function() { return Batman.DOM.Yield.withName(keyPath).set('containerNode', node); }); }, contentfor: function(definition) { var keyPath, node, renderer, swapMethod, value; node = definition.node, value = definition.value, swapMethod = definition.swapMethod, renderer = definition.renderer, keyPath = definition.keyPath; swapMethod || (swapMethod = 'append'); return Batman.DOM.onParseExit(node, function() { var _ref; if ((_ref = node.parentNode) != null) { _ref.removeChild(node); } return renderer.view.pushYieldAction(keyPath, swapMethod, node); }); }, replace: function(definition) { definition.swapMethod = 'replace'; return Batman.DOM.readers.contentfor(definition); } }; }).call(this); (function() { var __slice = [].slice, __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; Batman.DOM.events = { click: function(node, callback, context, eventName) { if (eventName == null) { eventName = 'click'; } Batman.DOM.addEventListener(node, eventName, function() { var args, event; event = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : []; if (event.metaKey || event.ctrlKey || event.button === 1) { return; } Batman.DOM.preventDefault(event); if (!Batman.DOM.eventIsAllowed(eventName, event)) { return; } return callback.apply(null, [node, event].concat(__slice.call(args), [context])); }); if (node.nodeName.toUpperCase() === 'A' && !node.href) { node.href = '#'; } return node; }, doubleclick: function(node, callback, context) { return Batman.DOM.events.click(node, callback, context, 'dblclick'); }, change: function(node, callback, context) { var eventName, eventNames, oldCallback, _i, _len, _results; eventNames = (function() { var _ref; switch (node.nodeName.toUpperCase()) { case 'TEXTAREA': return ['input', 'keyup', 'change']; case 'INPUT': if (_ref = node.type.toLowerCase(), __indexOf.call(Batman.DOM.textInputTypes, _ref) >= 0) { oldCallback = callback; callback = function(node, event) { if (event.type === 'keyup' && Batman.DOM.events.isEnter(event)) { return; } return oldCallback(node, event); }; return ['input', 'keyup', 'change']; } else { return ['input', 'change']; } break; default: return ['change']; } })(); _results = []; for (_i = 0, _len = eventNames.length; _i < _len; _i++) { eventName = eventNames[_i]; _results.push(Batman.DOM.addEventListener(node, eventName, function() { var args; args = 1 <= arguments.length ? __slice.call(arguments, 0) : []; return callback.apply(null, [node].concat(__slice.call(args), [context])); })); } return _results; }, isEnter: function(ev) { var _ref, _ref1; return ((13 <= (_ref = ev.keyCode) && _ref <= 14)) || ((13 <= (_ref1 = ev.which) && _ref1 <= 14)) || ev.keyIdentifier === 'Enter' || ev.key === 'Enter'; }, submit: function(node, callback, context) { if (Batman.DOM.nodeIsEditable(node)) { Batman.DOM.addEventListener(node, 'keydown', function() { var args; args = 1 <= arguments.length ? __slice.call(arguments, 0) : []; if (Batman.DOM.events.isEnter(args[0])) { return Batman.DOM._keyCapturingNode = node; } }); Batman.DOM.addEventListener(node, 'keyup', function() { var args; args = 1 <= arguments.length ? __slice.call(arguments, 0) : []; if (Batman.DOM.events.isEnter(args[0])) { if (Batman.DOM._keyCapturingNode === node) { Batman.DOM.preventDefault(args[0]); callback.apply(null, [node].concat(__slice.call(args), [context])); } return Batman.DOM._keyCapturingNode = null; } }); } else { Batman.DOM.addEventListener(node, 'submit', function() { var args; args = 1 <= arguments.length ? __slice.call(arguments, 0) : []; Batman.DOM.preventDefault(args[0]); return callback.apply(null, [node].concat(__slice.call(args), [context])); }); } return node; }, other: function(node, eventName, callback, context) { return Batman.DOM.addEventListener(node, eventName, function() { var args; args = 1 <= arguments.length ? __slice.call(arguments, 0) : []; return callback.apply(null, [node].concat(__slice.call(args), [context])); }); } }; Batman.DOM.eventIsAllowed = function(eventName, event) { var delegate, _ref, _ref1; if (delegate = (_ref = Batman.currentApp) != null ? (_ref1 = _ref.shouldAllowEvent) != null ? _ref1[eventName] : void 0 : void 0) { if (delegate(event) === false) { return false; } } return true; }; }).call(this); (function() { Batman.DOM.AttrReaderBindingDefinition = (function() { function AttrReaderBindingDefinition(node, attr, keyPath, context, renderer) { this.node = node; this.attr = attr; this.keyPath = keyPath; this.context = context; this.renderer = renderer; } return AttrReaderBindingDefinition; })(); Batman.DOM.attrReaders = { _parseAttribute: function(value) { if (value === 'false') { value = false; } if (value === 'true') { value = true; } return value; }, source: function(definition) { definition.onlyObserve = Batman.BindingDefinitionOnlyObserve.Data; return Batman.DOM.attrReaders.bind(definition); }, bind: function(definition) { var bindingClass; bindingClass = (function() { switch (definition.attr) { case 'checked': case 'disabled': case 'selected': return Batman.DOM.CheckedBinding; case 'value': case 'href': case 'src': case 'size': return Batman.DOM.NodeAttributeBinding; case 'class': return Batman.DOM.ClassBinding; case 'style': return Batman.DOM.StyleBinding; default: return Batman.DOM.AttributeBinding; } })(); return new bindingClass(definition); }, context: function(definition) { return definition.context.descendWithDefinition(definition); }, event: function(definition) { return new Batman.DOM.EventBinding(definition); }, addclass: function(definition) { return new Batman.DOM.AddClassBinding(definition); }, removeclass: function(definition) { definition.invert = true; return new Batman.DOM.AddClassBinding(definition); }, foreach: function(definition) { return new Batman.DOM.IteratorBinding(definition); }, formfor: function(definition) { new Batman.DOM.FormBinding(definition); return definition.context.descendWithDefinition(definition); } }; }).call(this); (function() { var BatmanObject, ObjectFunctions, getAccessorObject, promiseWrapper, wrapSingleAccessor, __slice = [].slice, __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; getAccessorObject = function(base, accessor) { var deprecated, _i, _len, _ref; if (typeof accessor === 'function') { accessor = { get: accessor }; } _ref = ['cachable', 'cacheable']; for (_i = 0, _len = _ref.length; _i < _len; _i++) { deprecated = _ref[_i]; if (deprecated in accessor) { Batman.developer.warn("Property accessor option \"" + deprecated + "\" is deprecated. Use \"cache\" instead."); if (!('cache' in accessor)) { accessor.cache = accessor[deprecated]; } } } return accessor; }; promiseWrapper = function(fetcher) { return function(defaultAccessor) { return { get: function(key) { var asyncDeliver, existingValue, newValue, _base, _base1, _ref, _ref1, _this = this; if ((existingValue = defaultAccessor.get.apply(this, arguments)) != null) { return existingValue; } asyncDeliver = false; newValue = void 0; if ((_ref = (_base = this._batman).promises) == null) { _base.promises = {}; } if ((_ref1 = (_base1 = this._batman.promises)[key]) == null) { _base1[key] = (function() { var deliver, returnValue; deliver = function(err, result) { if (asyncDeliver) { _this.set(key, result); } return newValue = result; }; returnValue = fetcher.call(_this, deliver, key); if (newValue == null) { newValue = returnValue; } return true; })(); } asyncDeliver = true; return newValue; }, cache: true }; }; }; wrapSingleAccessor = function(core, wrapper) { var k, v; wrapper = (typeof wrapper === "function" ? wrapper(core) : void 0) || wrapper; for (k in core) { v = core[k]; if (!(k in wrapper)) { wrapper[k] = v; } } return wrapper; }; ObjectFunctions = { _defineAccessor: function() { var accessor, key, keys, _base, _i, _j, _len, _ref, _results; keys = 2 <= arguments.length ? __slice.call(arguments, 0, _i = arguments.length - 1) : (_i = 0, []), accessor = arguments[_i++]; if (!(accessor != null)) { return Batman.Property.defaultAccessorForBase(this); } else if (keys.length === 0 && ((_ref = Batman.typeOf(accessor)) !== 'Object' && _ref !== 'Function')) { return Batman.Property.accessorForBaseAndKey(this, accessor); } else if (typeof accessor.promise === 'function') { return this._defineWrapAccessor.apply(this, __slice.call(keys).concat([promiseWrapper(accessor.promise)])); } Batman.initializeObject(this); if (keys.length === 0) { return this._batman.defaultAccessor = getAccessorObject(this, accessor); } else { (_base = this._batman).keyAccessors || (_base.keyAccessors = new Batman.SimpleHash); _results = []; for (_j = 0, _len = keys.length; _j < _len; _j++) { key = keys[_j]; _results.push(this._batman.keyAccessors.set(key, getAccessorObject(this, accessor))); } return _results; } }, _defineWrapAccessor: function() { var key, keys, wrapper, _i, _j, _len, _results; keys = 2 <= arguments.length ? __slice.call(arguments, 0, _i = arguments.length - 1) : (_i = 0, []), wrapper = arguments[_i++]; Batman.initializeObject(this); if (keys.length === 0) { return this._defineAccessor(wrapSingleAccessor(this._defineAccessor(), wrapper)); } else { _results = []; for (_j = 0, _len = keys.length; _j < _len; _j++) { key = keys[_j]; _results.push(this._defineAccessor(key, wrapSingleAccessor(this._defineAccessor(key), wrapper))); } return _results; } }, _resetPromises: function() { var key; if (this._batman.promises == null) { return; } for (key in this._batman.promises) { this._resetPromise(key); } }, _resetPromise: function(key) { this.unset(key); this.property(key).cached = false; delete this._batman.promises[key]; } }; BatmanObject = (function(_super) { var counter; __extends(BatmanObject, _super); Batman.initializeObject(BatmanObject); Batman.initializeObject(BatmanObject.prototype); Batman.mixin(BatmanObject.prototype, ObjectFunctions, Batman.EventEmitter, Batman.Observable); Batman.mixin(BatmanObject, ObjectFunctions, Batman.EventEmitter, Batman.Observable); BatmanObject.classMixin = function() { return Batman.mixin.apply(Batman, [this].concat(__slice.call(arguments))); }; BatmanObject.mixin = function() { return this.classMixin.apply(this.prototype, arguments); }; BatmanObject.prototype.mixin = BatmanObject.classMixin; BatmanObject.classAccessor = BatmanObject._defineAccessor; BatmanObject.accessor = function() { var _ref; return (_ref = this.prototype)._defineAccessor.apply(_ref, arguments); }; BatmanObject.prototype.accessor = BatmanObject._defineAccessor; BatmanObject.wrapClassAccessor = BatmanObject._defineWrapAccessor; BatmanObject.wrapAccessor = function() { var _ref; return (_ref = this.prototype)._defineWrapAccessor.apply(_ref, arguments); }; BatmanObject.prototype.wrapAccessor = BatmanObject._defineWrapAccessor; BatmanObject.observeAll = function() { return this.prototype.observe.apply(this.prototype, arguments); }; BatmanObject.singleton = function(singletonMethodName) { if (singletonMethodName == null) { singletonMethodName = "sharedInstance"; } return this.classAccessor(singletonMethodName, { get: function() { var _name; return this[_name = "_" + singletonMethodName] || (this[_name] = new this); } }); }; BatmanObject.accessor('_batmanID', function() { return this._batmanID(); }); function BatmanObject() { var mixins; mixins = 1 <= arguments.length ? __slice.call(arguments, 0) : []; this._batman = new Batman._Batman(this); this.mixin.apply(this, mixins); } counter = 0; BatmanObject.prototype._batmanID = function() { var _base, _ref; this._batman.check(this); if ((_ref = (_base = this._batman).id) == null) { _base.id = counter++; } return this._batman.id; }; BatmanObject.prototype.hashKey = function() { var _base; if (typeof this.isEqual === 'function') { return; } return (_base = this._batman).hashKey || (_base.hashKey = ""); }; BatmanObject.prototype.toJSON = function() { var key, obj, value; obj = {}; for (key in this) { if (!__hasProp.call(this, key)) continue; value = this[key]; if (key !== "_batman" && key !== "hashKey" && key !== "_batmanID") { obj[key] = (value != null ? value.toJSON : void 0) ? value.toJSON() : value; } } return obj; }; return BatmanObject; })(Object); Batman.Object = BatmanObject; }).call(this); (function() { var __bind = function(fn, me) { return function() { return fn.apply(me, arguments); }; }, __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Batman.Renderer = (function(_super) { var bindingRegexp, bindingSortOrder, bindingSortPositions, k, name, pos, _i, _j, _len, _len1, _ref; __extends(Renderer, _super); Renderer.prototype.deferEvery = 50; function Renderer(node, context, view) { this.node = node; this.context = context; this.view = view; this.resume = __bind(this.resume, this); this.start = __bind(this.start, this); Renderer.__super__.constructor.call(this); if (!(this.context instanceof Batman.RenderContext)) { Batman.developer.error("Must pass a RenderContext to a renderer for rendering"); } this.immediate = Batman.setImmediate(this.start); } Renderer.prototype.start = function() { this.startTime = new Date; this.prevent('parsed'); this.prevent('rendered'); return this.parseNode(this.node); }; Renderer.prototype.resume = function() { this.startTime = new Date; return this.parseNode(this.resumeNode); }; Renderer.prototype.finish = function() { this.startTime = null; this.prevent('stopped'); this.allowAndFire('parsed'); return this.allowAndFire('rendered'); }; Renderer.prototype.stop = function() { Batman.clearImmediate(this.immediate); return this.fire('stopped'); }; _ref = ['parsed', 'rendered', 'stopped']; for (_i = 0, _len = _ref.length; _i < _len; _i++) { k = _ref[_i]; Renderer.prototype.event(k).oneShot = true; } bindingRegexp = /^data\-(.*)/; bindingSortOrder = ["view", "renderif", "foreach", "formfor", "context", "bind", "source", "target"]; bindingSortPositions = {}; for (pos = _j = 0, _len1 = bindingSortOrder.length; _j < _len1; pos = ++_j) { name = bindingSortOrder[pos]; bindingSortPositions[name] = pos; } Renderer.prototype._sortBindings = function(a, b) { var aindex, bindex; aindex = bindingSortPositions[a[0]]; bindex = bindingSortPositions[b[0]]; if (aindex == null) { aindex = bindingSortOrder.length; } if (bindex == null) { bindex = bindingSortOrder.length; } if (aindex > bindex) { return 1; } else if (bindex > aindex) { return -1; } else if (a[0] > b[0]) { return 1; } else if (b[0] > a[0]) { return -1; } else { return 0; } }; Renderer.prototype.parseNode = function(node) { var attr, attribute, binding, bindingDefinition, bindings, names, nextNode, oldContext, reader, skipChildren, value, _k, _l, _len2, _len3, _ref1, _ref2, _ref3, _ref4, _this = this; if (this.deferEvery && (new Date - this.startTime) > this.deferEvery) { this.resumeNode = node; this.timeout = Batman.setImmediate(this.resume); return; } if (node.getAttribute && node.attributes) { bindings = []; _ref1 = node.attributes; for (_k = 0, _len2 = _ref1.length; _k < _len2; _k++) { attribute = _ref1[_k]; name = (_ref2 = attribute.nodeName.match(bindingRegexp)) != null ? _ref2[1] : void 0; if (!name) { continue; } bindings.push((names = name.split('-')).length > 1 ? [names[0], names.slice(1, names.length + 1 || 9e9).join('-'), attribute.value] : [name, void 0, attribute.value]); } _ref3 = bindings.sort(this._sortBindings); for (_l = 0, _len3 = _ref3.length; _l < _len3; _l++) { _ref4 = _ref3[_l], name = _ref4[0], attr = _ref4[1], value = _ref4[2]; binding = attr ? (reader = Batman.DOM.attrReaders[name]) ? (bindingDefinition = new Batman.DOM.AttrReaderBindingDefinition(node, attr, value, this.context, this), reader(bindingDefinition)) : void 0 : (reader = Batman.DOM.readers[name]) ? (bindingDefinition = new Batman.DOM.ReaderBindingDefinition(node, value, this.context, this), reader(bindingDefinition)) : void 0; if (binding instanceof Batman.RenderContext) { oldContext = this.context; this.context = binding; Batman.DOM.onParseExit(node, function() { return _this.context = oldContext; }); } else if (binding != null ? binding.skipChildren : void 0) { skipChildren = true; break; } } } if ((nextNode = this.nextNode(node, skipChildren))) { return this.parseNode(nextNode); } else { return this.finish(); } }; Renderer.prototype.nextNode = function(node, skipChildren) { var children, nextParent, parentSibling, sibling, _ref1, _ref2; if (!skipChildren) { children = node.childNodes; if (children != null ? children.length : void 0) { return children[0]; } } sibling = node.nextSibling; if ((_ref1 = Batman.DOM.onParseExit(node)) != null) { _ref1.forEach(function(callback) { return callback(); }); } Batman.DOM.forgetParseExit(node); if (this.node === node) { return; } if (sibling) { return sibling; } nextParent = node; while (nextParent = nextParent.parentNode) { parentSibling = nextParent.nextSibling; if ((_ref2 = Batman.DOM.onParseExit(nextParent)) != null) { _ref2.forEach(function(callback) { return callback(); }); } Batman.DOM.forgetParseExit(nextParent); if (this.node === nextParent) { return; } if (parentSibling) { return parentSibling; } } }; return Renderer; })(Batman.Object); }).call(this); (function() { var __bind = function(fn, me) { return function() { return fn.apply(me, arguments); }; }, __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Batman.DOM.AbstractBinding = (function(_super) { var get_dot_rx, get_rx, keypath_rx, onlyAll, onlyData, onlyNode; __extends(AbstractBinding, _super); keypath_rx = /(^|,)\s*(?:(true|false)|("[^"]*")|(\{[^\}]*\})|(([0-9]+[a-zA-Z\_]|[a-zA-Z])[\w\-\.]*[\?\!]?))\s*(?=$|,)/g; get_dot_rx = /(?:\]\.)(.+?)(?=[\[\.]|\s*\||$)/; get_rx = /(?!^\s*)\[(.*?)\]/g; AbstractBinding.accessor('filteredValue', { get: function() { var renderContext, result, self, unfilteredValue; unfilteredValue = this.get('unfilteredValue'); self = this; renderContext = this.get('renderContext'); if (this.filterFunctions.length > 0) { Batman.developer.currentFilterStack = renderContext; result = this.filterFunctions.reduce(function(value, fn, i) { var args; args = self.filterArguments[i].map(function(argument) { if (argument._keypath) { return self.renderContext.get(argument._keypath); } else { return argument; } }); args.unshift(value); while (args.length < (fn.length - 1)) { args.push(void 0); } args.push(self); return fn.apply(renderContext, args); }, unfilteredValue); Batman.developer.currentFilterStack = null; return result; } else { return unfilteredValue; } }, set: function(_, newValue) { return this.set('unfilteredValue', newValue); } }); AbstractBinding.accessor('unfilteredValue', { get: function() { var k; if (k = this.get('key')) { return Batman.RenderContext.deProxy(Batman.getPath(this, ['keyContext', k])); } else { return this.get('value'); } }, set: function(_, value) { var k, keyContext, prop; if (k = this.get('key')) { keyContext = this.get('keyContext'); if (keyContext && keyContext !== Batman.container) { prop = Batman.Property.forBaseAndKey(keyContext, k); return prop.setValue(value); } } else { return this.set('value', value); } } }); AbstractBinding.accessor('keyContext', function() { return this.renderContext.contextForKey(this.key); }); onlyAll = Batman.BindingDefinitionOnlyObserve.All; onlyData = Batman.BindingDefinitionOnlyObserve.Data; onlyNode = Batman.BindingDefinitionOnlyObserve.Node; AbstractBinding.prototype.bindImmediately = true; AbstractBinding.prototype.shouldSet = true; AbstractBinding.prototype.isInputBinding = false; AbstractBinding.prototype.escapeValue = true; AbstractBinding.prototype.onlyObserve = onlyAll; AbstractBinding.prototype.skipParseFilter = false; function AbstractBinding(definition) { this._fireDataChange = __bind(this._fireDataChange, this); this.node = definition.node, this.keyPath = definition.keyPath, this.renderContext = definition.context, this.renderer = definition.renderer; if (definition.onlyObserve) { this.onlyObserve = definition.onlyObserve; } if (definition.skipParseFilter != null) { this.skipParseFilter = definition.skipParseFilter; } if (!this.skipParseFilter) { this.parseFilter(); } if (this.bindImmediately) { this.bind(); } } AbstractBinding.prototype.isTwoWay = function() { return (this.key != null) && this.filterFunctions.length === 0; }; AbstractBinding.prototype.bind = function() { var _ref, _ref1; if (this.node && ((_ref = this.onlyObserve) === onlyAll || _ref === onlyNode) && Batman.DOM.nodeIsEditable(this.node)) { Batman.DOM.events.change(this.node, this._fireNodeChange.bind(this)); if (this.onlyObserve === onlyNode) { this._fireNodeChange(); } } if ((_ref1 = this.onlyObserve) === onlyAll || _ref1 === onlyData) { this.observeAndFire('filteredValue', this._fireDataChange); } if (this.node) { return Batman.DOM.trackBinding(this, this.node); } }; AbstractBinding.prototype._fireNodeChange = function(event) { var val; this.shouldSet = false; val = this.value || this.get('keyContext'); if (typeof this.nodeChange === "function") { this.nodeChange(this.node, val, event); } this.fire('nodeChange', this.node, val); return this.shouldSet = true; }; AbstractBinding.prototype._fireDataChange = function(value) { if (this.shouldSet) { if (typeof this.dataChange === "function") { this.dataChange(value, this.node); } return this.fire('dataChange', value, this.node); } }; AbstractBinding.prototype.die = function() { var _ref; this.forget(); if ((_ref = this._batman.properties) != null) { _ref.forEach(function(key, property) { return property.die(); }); } this.fire('die'); this.node = null; this.keyPath = null; this.renderContext = null; this.renderer = null; this.dead = true; return true; }; AbstractBinding.prototype.parseFilter = function() { var args, filter, filterName, filterString, filters, key, keyPath, orig, split; this.filterFunctions = []; this.filterArguments = []; keyPath = this.keyPath; while (get_dot_rx.test(keyPath)) { keyPath = keyPath.replace(get_dot_rx, "]['$1']"); } filters = keyPath.replace(get_rx, " | get $1 ").replace(/'/g, '"').split(/(?!")\s+\|\s+(?!")/); try { key = this.parseSegment(orig = filters.shift())[0]; } catch (e) { Batman.developer.warn(e); Batman.developer.error("Error! Couldn't parse keypath in \"" + orig + "\". Parsing error above."); } if (key && key._keypath) { this.key = key._keypath; } else { this.value = key; } if (filters.length) { while (filterString = filters.shift()) { split = filterString.indexOf(' '); if (split === -1) { split = filterString.length; } filterName = filterString.substr(0, split); args = filterString.substr(split); if (!(filter = Batman.Filters[filterName])) { return Batman.developer.error("Unrecognized filter '" + filterName + "' in key \"" + this.keyPath + "\"!"); } this.filterFunctions.push(filter); try { this.filterArguments.push(this.parseSegment(args)); } catch (e) { Batman.developer.error("Bad filter arguments \"" + args + "\"!"); } } return true; } }; AbstractBinding.prototype.parseSegment = function(segment) { segment = segment.replace(keypath_rx, function(match, start, bool, string, object, keypath, offset) { var replacement; if (start == null) { start = ''; } replacement = keypath ? '{"_keypath": "' + keypath + '"}' : bool || string || object; return start + replacement; }); return JSON.parse("[" + segment + "]"); }; return AbstractBinding; })(Batman.Object); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Batman.DOM.ViewBinding = (function(_super) { __extends(ViewBinding, _super); ViewBinding.prototype.skipChildren = true; ViewBinding.prototype.onlyObserve = Batman.BindingDefinitionOnlyObserve.Data; function ViewBinding() { ViewBinding.__super__.constructor.apply(this, arguments); this.renderer.prevent('rendered'); this.node.removeAttribute('data-view'); } ViewBinding.prototype.dataChange = function(viewClassOrInstance) { var _ref, _this = this; if (viewClassOrInstance == null) { return; } if (viewClassOrInstance.isView) { this.view = viewClassOrInstance; this.view.set('context', this.renderContext); this.view.set('node', this.node); } else { this.view = new viewClassOrInstance({ node: this.node, context: this.renderContext, parentView: this.renderer.view }); } this.view.on('ready', function() { return _this.renderer.allowAndFire('rendered'); }); this.forget(); return (_ref = this._batman.properties) != null ? _ref.forEach(function(key, property) { return property.die(); }) : void 0; }; ViewBinding.prototype.die = function() { this.view = null; return ViewBinding.__super__.die.apply(this, arguments); }; return ViewBinding; })(Batman.DOM.AbstractBinding); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Batman.DOM.ViewArgumentBinding = (function(_super) { __extends(ViewArgumentBinding, _super); function ViewArgumentBinding() { return ViewArgumentBinding.__super__.constructor.apply(this, arguments); } ViewArgumentBinding.prototype.onlyObserve = Batman.BindingDefinitionOnlyObserve.None; return ViewArgumentBinding; })(Batman.DOM.AbstractBinding); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Batman.DOM.ValueBinding = (function(_super) { __extends(ValueBinding, _super); function ValueBinding(definition) { var _ref; this.isInputBinding = (_ref = definition.node.nodeName.toLowerCase()) === 'input' || _ref === 'textarea'; ValueBinding.__super__.constructor.apply(this, arguments); } ValueBinding.prototype.nodeChange = function(node, context) { if (this.isTwoWay()) { return this.set('filteredValue', this.node.value); } }; ValueBinding.prototype.dataChange = function(value, node) { return Batman.DOM.valueForNode(this.node, value, this.escapeValue); }; return ValueBinding; })(Batman.DOM.AbstractBinding); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Batman.DOM.ShowHideBinding = (function(_super) { __extends(ShowHideBinding, _super); ShowHideBinding.prototype.onlyObserve = Batman.BindingDefinitionOnlyObserve.Data; function ShowHideBinding(definition) { var display; display = definition.node.style.display; if (!display || display === 'none') { display = ''; } this.originalDisplay = display; this.invert = definition.invert; ShowHideBinding.__super__.constructor.apply(this, arguments); } ShowHideBinding.prototype.dataChange = function(value) { var hide, view, _ref; view = Batman._data(this.node, 'view'); if ( !! value === !this.invert) { if (view != null) { view.fire('beforeAppear', this.node); } if ((_ref = Batman.data(this.node, 'show')) != null) { _ref.call(this.node); } this.node.style.display = this.originalDisplay; return view != null ? view.fire('appear', this.node) : void 0; } else { if (view != null) { view.fire('beforeDisappear', this.node); } if (typeof(hide = Batman.data(this.node, 'hide')) === 'function') { hide.call(this.node); } else { Batman.DOM.setStyleProperty(this.node, 'display', 'none', 'important'); } return view != null ? view.fire('disappear', this.node) : void 0; } }; return ShowHideBinding; })(Batman.DOM.AbstractBinding); }).call(this); (function() { var __bind = function(fn, me) { return function() { return fn.apply(me, arguments); }; }, __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Batman.DOM.SelectBinding = (function(_super) { __extends(SelectBinding, _super); SelectBinding.prototype.isInputBinding = true; SelectBinding.prototype.canSetImplicitly = true; function SelectBinding() { this.updateOptionBindings = __bind(this.updateOptionBindings, this); this.nodeChange = __bind(this.nodeChange, this); this.dataChange = __bind(this.dataChange, this); this.childBindingAdded = __bind(this.childBindingAdded, this); this.selectedBindings = new Batman.SimpleSet; SelectBinding.__super__.constructor.apply(this, arguments); } SelectBinding.prototype.childBindingAdded = function(binding) { var dataChangeHandler, _this = this; if (binding instanceof Batman.DOM.CheckedBinding) { binding.on('dataChange', dataChangeHandler = function() { return _this.nodeChange(); }); binding.on('die', function() { binding.forget('dataChange', dataChangeHandler); return _this.selectedBindings.remove(binding); }); this.selectedBindings.add(binding); } else if (binding instanceof Batman.DOM.IteratorBinding) { binding.on('nodeAdded', dataChangeHandler = function() { return _this._fireDataChange(_this.get('filteredValue')); }); binding.on('nodeRemoved', dataChangeHandler); binding.on('die', function() { binding.forget('nodeAdded', dataChangeHandler); return binding.forget('nodeRemoved', dataChangeHandler); }); } else { return; } return this._fireDataChange(this.get('filteredValue')); }; SelectBinding.prototype.lastKeyContext = null; SelectBinding.prototype.dataChange = function(newValue) { var child, matches, valueToChild, _i, _len, _name, _ref, _this = this; this.lastKeyContext || (this.lastKeyContext = this.get('keyContext')); if (this.lastKeyContext !== this.get('keyContext')) { this.canSetImplicitly = true; this.lastKeyContext = this.get('keyContext'); } if (newValue != null ? newValue.forEach : void 0) { valueToChild = {}; _ref = this.node.children; for (_i = 0, _len = _ref.length; _i < _len; _i++) { child = _ref[_i]; child.selected = false; matches = valueToChild[_name = child.value] || (valueToChild[_name] = []); matches.push(child); } newValue.forEach(function(value) { var children, node, _j, _len1, _results; if (children = valueToChild[value]) { _results = []; for (_j = 0, _len1 = children.length; _j < _len1; _j++) { node = children[_j]; _results.push(node.selected = true); } return _results; } }); } else { if (!(newValue != null) && this.canSetImplicitly) { if (this.node.value) { this.canSetImplicitly = false; this.set('unfilteredValue', this.node.value); } } else { this.canSetImplicitly = false; Batman.DOM.valueForNode(this.node, newValue, this.escapeValue); } } this.updateOptionBindings(); }; SelectBinding.prototype.nodeChange = function() { var c, selections; if (this.isTwoWay()) { selections = this.node.multiple ? (function() { var _i, _len, _ref, _results; _ref = this.node.children; _results = []; for (_i = 0, _len = _ref.length; _i < _len; _i++) { c = _ref[_i]; if (c.selected) { _results.push(c.value); } } return _results; }).call(this) : this.node.value; if (typeof selections === Array && selections.length === 1) { selections = selections[0]; } this.set('unfilteredValue', selections); this.updateOptionBindings(); } }; SelectBinding.prototype.updateOptionBindings = function() { return this.selectedBindings.forEach(function(binding) { return binding._fireNodeChange(); }); }; return SelectBinding; })(Batman.DOM.AbstractBinding); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Batman.DOM.RouteBinding = (function(_super) { __extends(RouteBinding, _super); function RouteBinding() { return RouteBinding.__super__.constructor.apply(this, arguments); } RouteBinding.prototype.onAnchorTag = false; RouteBinding.prototype.onlyObserve = Batman.BindingDefinitionOnlyObserve.Data; RouteBinding.accessor('dispatcher', function() { return this.renderContext.get('dispatcher') || Batman.App.get('current.dispatcher'); }); RouteBinding.prototype.bind = function() { var _this = this; if (this.node.nodeName.toUpperCase() === 'A') { this.onAnchorTag = true; } RouteBinding.__super__.bind.apply(this, arguments); return Batman.DOM.events.click(this.node, function(node, event) { var params; if (event.__batmanActionTaken) { return; } event.__batmanActionTaken = true; params = _this.pathFromValue(_this.get('filteredValue')); if (params != null) { return Batman.redirect(params); } }); }; RouteBinding.prototype.dataChange = function(value) { var path; if (value) { path = this.pathFromValue(value); } if (this.onAnchorTag) { if (path && Batman.navigator) { path = Batman.navigator.linkTo(path); } else { path = "#"; } return this.node.href = path; } }; RouteBinding.prototype.pathFromValue = function(value) { var _ref; if (value) { if (value.isNamedRouteQuery) { return value.get('path'); } else { return (_ref = this.get('dispatcher')) != null ? _ref.pathFromParams(value) : void 0; } } }; return RouteBinding; })(Batman.DOM.AbstractBinding); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Batman.DOM.RadioBinding = (function(_super) { __extends(RadioBinding, _super); function RadioBinding() { return RadioBinding.__super__.constructor.apply(this, arguments); } RadioBinding.accessor('parsedNodeValue', function() { return Batman.DOM.attrReaders._parseAttribute(this.node.value); }); RadioBinding.prototype.firstBind = true; RadioBinding.prototype.dataChange = function(value) { var boundValue; boundValue = this.get('filteredValue'); if (boundValue != null) { this.node.checked = boundValue === Batman.DOM.attrReaders._parseAttribute(this.node.value); } else { if (this.firstBind && this.node.checked) { this.set('filteredValue', this.get('parsedNodeValue')); } } return this.firstBind = false; }; RadioBinding.prototype.nodeChange = function(node) { if (this.isTwoWay()) { return this.set('filteredValue', this.get('parsedNodeValue')); } }; return RadioBinding; })(Batman.DOM.AbstractBinding); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Batman.DOM.MixinBinding = (function(_super) { __extends(MixinBinding, _super); function MixinBinding() { return MixinBinding.__super__.constructor.apply(this, arguments); } MixinBinding.prototype.onlyObserve = Batman.BindingDefinitionOnlyObserve.Data; MixinBinding.prototype.dataChange = function(value) { if (value != null) { return Batman.mixin(this.node, value); } }; return MixinBinding; })(Batman.DOM.AbstractBinding); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Batman.DOM.FileBinding = (function(_super) { __extends(FileBinding, _super); function FileBinding() { return FileBinding.__super__.constructor.apply(this, arguments); } FileBinding.prototype.isInputBinding = true; FileBinding.prototype.nodeChange = function(node, subContext) { if (!this.isTwoWay()) { return; } if (node.hasAttribute('multiple')) { return this.set('filteredValue', Array.prototype.slice.call(node.files)); } else { return this.set('filteredValue', node.files[0]); } }; return FileBinding; })(Batman.DOM.AbstractBinding); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Batman.DOM.DeferredRenderingBinding = (function(_super) { __extends(DeferredRenderingBinding, _super); DeferredRenderingBinding.prototype.rendered = false; DeferredRenderingBinding.prototype.skipChildren = true; function DeferredRenderingBinding() { DeferredRenderingBinding.__super__.constructor.apply(this, arguments); this.node.removeAttribute("data-renderif"); } DeferredRenderingBinding.prototype.nodeChange = function() {}; DeferredRenderingBinding.prototype.dataChange = function(value) { if (value && !this.rendered) { return this.render(); } }; DeferredRenderingBinding.prototype.render = function() { new Batman.Renderer(this.node, this.renderContext, this.renderer.view); return this.rendered = true; }; return DeferredRenderingBinding; })(Batman.DOM.AbstractBinding); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Batman.DOM.AbstractAttributeBinding = (function(_super) { __extends(AbstractAttributeBinding, _super); function AbstractAttributeBinding(definition) { this.attributeName = definition.attr; AbstractAttributeBinding.__super__.constructor.apply(this, arguments); } return AbstractAttributeBinding; })(Batman.DOM.AbstractBinding); }).call(this); (function() { var __bind = function(fn, me) { return function() { return fn.apply(me, arguments); }; }, __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Batman.DOM.FormBinding = (function(_super) { __extends(FormBinding, _super); FormBinding.current = null; FormBinding.prototype.errorClass = 'error'; FormBinding.prototype.defaultErrorsListSelector = 'div.errors'; FormBinding.prototype.onlyObserve = Batman.BindingDefinitionOnlyObserve.None; FormBinding.accessor('errorsListSelector', function() { return this.get('node').getAttribute('data-errors-list') || this.defaultErrorsListSelector; }); function FormBinding() { this.childBindingAdded = __bind(this.childBindingAdded, this); FormBinding.__super__.constructor.apply(this, arguments); this.contextName = this.attributeName; delete this.attributeName; Batman.DOM.events.submit(this.get('node'), function(node, e) { return Batman.DOM.preventDefault(e); }); this.setupErrorsList(); } FormBinding.prototype.childBindingAdded = function(binding) { var definition, field, index, node; if (binding.isInputBinding && Batman.isChildOf(this.get('node'), binding.get('node'))) { if (~ (index = binding.get('key').indexOf(this.contextName))) { node = binding.get('node'); field = binding.get('key').slice(index + this.contextName.length + 1); definition = new Batman.DOM.AttrReaderBindingDefinition(node, this.errorClass, this.get('keyPath') + (" | get 'errors." + field + ".length'"), this.renderContext, this.renderer); return new Batman.DOM.AddClassBinding(definition); } } }; FormBinding.prototype.setupErrorsList = function() { if (this.errorsListNode = Batman.DOM.querySelector(this.get('node'), this.get('errorsListSelector'))) { Batman.DOM.setInnerHTML(this.errorsListNode, this.errorsListHTML()); if (!this.errorsListNode.getAttribute('data-showif')) { return this.errorsListNode.setAttribute('data-showif', "" + this.contextName + ".errors.length"); } } }; FormBinding.prototype.errorsListHTML = function() { return "
    \n
  • \n
"; }; return FormBinding; })(Batman.DOM.AbstractAttributeBinding); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Batman.DOM.EventBinding = (function(_super) { __extends(EventBinding, _super); EventBinding.prototype.onlyObserve = Batman.BindingDefinitionOnlyObserve.None; function EventBinding() { var attacher, callback, confirmText, _this = this; EventBinding.__super__.constructor.apply(this, arguments); if (confirmText = this.node.getAttribute('data-confirm')) { Batman.developer.deprecated("data-confirm"); } callback = function() { var _ref; if (confirmText && !confirm(confirmText)) { return; } return (_ref = _this.get('filteredValue')) != null ? _ref.apply(_this.get('callbackContext'), arguments) : void 0; }; if (attacher = Batman.DOM.events[this.attributeName]) { attacher(this.node, callback, this.renderContext); } else { Batman.DOM.events.other(this.node, this.attributeName, callback, this.renderContext); } } EventBinding.accessor('callbackContext', function() { var contextKeySegments; contextKeySegments = this.key.split('.'); contextKeySegments.pop(); if (contextKeySegments.length > 0) { return this.get('keyContext').get(contextKeySegments.join('.')); } else { return this.get('keyContext'); } }); EventBinding.wrapAccessor('unfilteredValue', function(core) { return { get: function() { var functionKey, k, keyContext, keys; if (k = this.get('key')) { keys = k.split('.'); if (keys.length > 1) { functionKey = keys.pop(); keyContext = Batman.getPath(this, ['keyContext'].concat(keys)); keyContext = Batman.RenderContext.deProxy(keyContext); if (keyContext != null) { return keyContext[functionKey]; } } } return core.get.apply(this, arguments); } }; }); return EventBinding; })(Batman.DOM.AbstractAttributeBinding); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Batman.DOM.NodeAttributeBinding = (function(_super) { __extends(NodeAttributeBinding, _super); function NodeAttributeBinding() { return NodeAttributeBinding.__super__.constructor.apply(this, arguments); } NodeAttributeBinding.prototype.dataChange = function(value) { if (value == null) { value = ""; } return this.node[this.attributeName] = value; }; NodeAttributeBinding.prototype.nodeChange = function(node) { if (this.isTwoWay()) { return this.set('filteredValue', Batman.DOM.attrReaders._parseAttribute(node[this.attributeName])); } }; return NodeAttributeBinding; })(Batman.DOM.AbstractAttributeBinding); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Batman.DOM.CheckedBinding = (function(_super) { __extends(CheckedBinding, _super); function CheckedBinding() { return CheckedBinding.__super__.constructor.apply(this, arguments); } CheckedBinding.prototype.isInputBinding = true; CheckedBinding.prototype.dataChange = function(value) { return this.node[this.attributeName] = !! value; }; return CheckedBinding; })(Batman.DOM.NodeAttributeBinding); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Batman.DOM.AttributeBinding = (function(_super) { __extends(AttributeBinding, _super); function AttributeBinding() { return AttributeBinding.__super__.constructor.apply(this, arguments); } AttributeBinding.prototype.onlyObserve = Batman.BindingDefinitionOnlyObserve.Data; AttributeBinding.prototype.dataChange = function(value) { return this.node.setAttribute(this.attributeName, value); }; AttributeBinding.prototype.nodeChange = function(node) { if (this.isTwoWay()) { return this.set('filteredValue', Batman.DOM.attrReaders._parseAttribute(node.getAttribute(this.attributeName))); } }; return AttributeBinding; })(Batman.DOM.AbstractAttributeBinding); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Batman.DOM.AddClassBinding = (function(_super) { __extends(AddClassBinding, _super); AddClassBinding.prototype.onlyObserve = Batman.BindingDefinitionOnlyObserve.Data; function AddClassBinding(definition) { var name; this.invert = definition.invert; this.classes = (function() { var _i, _len, _ref, _results; _ref = definition.attr.split('|'); _results = []; for (_i = 0, _len = _ref.length; _i < _len; _i++) { name = _ref[_i]; _results.push({ name: name, pattern: new RegExp("(?:^|\\s)" + name + "(?:$|\\s)", 'i') }); } return _results; })(); AddClassBinding.__super__.constructor.apply(this, arguments); } AddClassBinding.prototype.dataChange = function(value) { var currentName, includesClassName, name, pattern, _i, _len, _ref, _ref1; currentName = this.node.className; _ref = this.classes; for (_i = 0, _len = _ref.length; _i < _len; _i++) { _ref1 = _ref[_i], name = _ref1.name, pattern = _ref1.pattern; includesClassName = pattern.test(currentName); if ( !! value === !this.invert) { if (!includesClassName) { this.node.className = "" + currentName + " " + name; } } else { if (includesClassName) { this.node.className = currentName.replace(pattern, ' '); } } } return true; }; return AddClassBinding; })(Batman.DOM.AbstractAttributeBinding); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Batman.DOM.AbstractCollectionBinding = (function(_super) { __extends(AbstractCollectionBinding, _super); function AbstractCollectionBinding() { return AbstractCollectionBinding.__super__.constructor.apply(this, arguments); } AbstractCollectionBinding.prototype.bindCollection = function(newCollection) { var _ref; if (newCollection instanceof Batman.Hash) { newCollection = newCollection.meta; } if (newCollection === this.collection) { return true; } else { this.unbindCollection(); this.collection = newCollection; if ((_ref = this.collection) != null ? _ref.isObservable : void 0) { this.collection.observeAndFire('toArray', this.handleArrayChanged); return true; } } return false; }; AbstractCollectionBinding.prototype.unbindCollection = function() { var _ref; if ((_ref = this.collection) != null ? _ref.isObservable : void 0) { return this.collection.forget('toArray', this.handleArrayChanged); } }; AbstractCollectionBinding.prototype.handleArrayChanged = function() {}; AbstractCollectionBinding.prototype.die = function() { this.unbindCollection(); return AbstractCollectionBinding.__super__.die.apply(this, arguments); }; return AbstractCollectionBinding; })(Batman.DOM.AbstractAttributeBinding); }).call(this); (function() { var __bind = function(fn, me) { return function() { return fn.apply(me, arguments); }; }, __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, __slice = [].slice; Batman.DOM.StyleBinding = (function(_super) { __extends(StyleBinding, _super); StyleBinding.prototype.onlyObserve = Batman.BindingDefinitionOnlyObserve.Data; function StyleBinding() { this.setStyle = __bind(this.setStyle, this); this.handleArrayChanged = __bind(this.handleArrayChanged, this); this.oldStyles = {}; this.styleBindings = {}; StyleBinding.__super__.constructor.apply(this, arguments); } StyleBinding.prototype.dataChange = function(value) { var colonSplitCSSValues, cssName, key, style, _i, _len, _ref, _ref1, _results; if (!value) { this.resetStyles(); return; } this.unbindCollection(); if (typeof value === 'string') { this.resetStyles(); _ref = value.split(';'); for (_i = 0, _len = _ref.length; _i < _len; _i++) { style = _ref[_i]; _ref1 = style.split(":"), cssName = _ref1[0], colonSplitCSSValues = 2 <= _ref1.length ? __slice.call(_ref1, 1) : []; this.setStyle(cssName, colonSplitCSSValues.join(":")); } return; } if (value instanceof Batman.Hash) { return this.bindCollection(value); } else { if (value instanceof Batman.Object) { value = value.toJSON(); } this.resetStyles(); _results = []; for (key in value) { if (!__hasProp.call(value, key)) continue; _results.push(this.bindSingleAttribute(key, "" + this.keyPath + "." + key)); } return _results; } }; StyleBinding.prototype.handleArrayChanged = function(array) { var _this = this; return this.collection.forEach(function(key, value) { return _this.bindSingleAttribute(key, "" + _this.keyPath + "." + key); }); }; StyleBinding.prototype.bindSingleAttribute = function(attr, keyPath) { var definition; definition = new Batman.DOM.AttrReaderBindingDefinition(this.node, attr, keyPath, this.renderContext, this.renderer); return this.styleBindings[attr] = new Batman.DOM.StyleBinding.SingleStyleBinding(definition, this); }; StyleBinding.prototype.setStyle = function(key, value) { key = Batman.helpers.camelize(key.trim(), true); if (this.oldStyles[key] == null) { this.oldStyles[key] = this.node.style[key] || ""; } if (value != null ? value.trim : void 0) { value = value.trim(); } if (value == null) { value = ""; } return this.node.style[key] = value; }; StyleBinding.prototype.resetStyles = function() { var cssName, cssValue, _ref, _results; _ref = this.oldStyles; _results = []; for (cssName in _ref) { if (!__hasProp.call(_ref, cssName)) continue; cssValue = _ref[cssName]; _results.push(this.setStyle(cssName, cssValue)); } return _results; }; StyleBinding.prototype.resetBindings = function() { var attribute, binding, _ref; _ref = this.styleBindings; for (attribute in _ref) { binding = _ref[attribute]; binding._fireDataChange(''); binding.die(); } return this.styleBindings = {}; }; StyleBinding.prototype.unbindCollection = function() { this.resetBindings(); return StyleBinding.__super__.unbindCollection.apply(this, arguments); }; StyleBinding.SingleStyleBinding = (function(_super1) { __extends(SingleStyleBinding, _super1); SingleStyleBinding.prototype.onlyObserve = Batman.BindingDefinitionOnlyObserve.Data; SingleStyleBinding.prototype.isTwoWay = function() { return false; }; function SingleStyleBinding(definition, parent) { this.parent = parent; SingleStyleBinding.__super__.constructor.call(this, definition); } SingleStyleBinding.prototype.dataChange = function(value) { return this.parent.setStyle(this.attributeName, value); }; return SingleStyleBinding; })(Batman.DOM.AbstractAttributeBinding); return StyleBinding; })(Batman.DOM.AbstractCollectionBinding); }).call(this); (function() { var __bind = function(fn, me) { return function() { return fn.apply(me, arguments); }; }, __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Batman.DOM.IteratorBinding = (function(_super) { __extends(IteratorBinding, _super); IteratorBinding.prototype.currentActionNumber = 0; IteratorBinding.prototype.queuedActionNumber = 0; IteratorBinding.prototype.bindImmediately = false; IteratorBinding.prototype.skipChildren = true; IteratorBinding.prototype.onlyObserve = Batman.BindingDefinitionOnlyObserve.Data; function IteratorBinding(definition) { this.handleArrayChanged = __bind(this.handleArrayChanged, this); var previousSiblingNode, sourceNode, _this = this; sourceNode = definition.node, this.iteratorName = definition.attr, this.key = definition.keyPath, this.parentRenderer = definition.renderer; this.nodeMap = new Batman.SimpleHash; this.rendererMap = new Batman.SimpleHash; this.prototypeNode = sourceNode.cloneNode(true); this.prototypeNode.removeAttribute("data-foreach-" + this.iteratorName); previousSiblingNode = sourceNode.nextSibling; this.startNode = document.createComment("start " + this.iteratorName + "-" + (this.get('_batmanID'))); this.endNode = document.createComment("end " + this.iteratorName + "-" + (this.get('_batmanID'))); this.endNode[Batman.expando] = sourceNode[Batman.expando]; if (Batman.canDeleteExpando) { delete sourceNode[Batman.expando]; } Batman.DOM.insertBefore(sourceNode.parentNode, this.startNode, previousSiblingNode); Batman.DOM.insertBefore(sourceNode.parentNode, this.endNode, previousSiblingNode); this.parentRenderer.prevent('rendered'); Batman.DOM.onParseExit(sourceNode.parentNode, function() { Batman.DOM.destroyNode(sourceNode); _this.bind(); return _this.parentRenderer.allowAndFire('rendered'); }); definition.node = this.endNode; IteratorBinding.__super__.constructor.apply(this, arguments); } IteratorBinding.prototype.parentNode = function() { return this.endNode.parentNode; }; IteratorBinding.prototype.dataChange = function(collection) { var items, _items; if (collection != null) { if (!this.bindCollection(collection)) { items = (collection != null ? collection.forEach : void 0) ? (_items = [], collection.forEach(function(item) { return _items.push(item); }), _items) : Object.keys(collection); return this.handleArrayChanged(items); } } else { return this.handleArrayChanged([]); } }; IteratorBinding.prototype.handleArrayChanged = function(newItems) { var existingNode, index, newItem, node, nodeAtIndex, parentNode, startIndex, unseenNodeMap, _i, _len, _this = this; parentNode = this.parentNode(); startIndex = this._getStartNodeIndex() + 1; unseenNodeMap = this.nodeMap.merge(); if (newItems) { for (index = _i = 0, _len = newItems.length; _i < _len; index = ++_i) { newItem = newItems[index]; nodeAtIndex = parentNode.childNodes[startIndex + index]; if ((nodeAtIndex != null) && this._itemForNode(nodeAtIndex) === newItem) { unseenNodeMap.unset(newItem); continue; } else { node = (existingNode = this.nodeMap.get(newItem)) ? (unseenNodeMap.unset(newItem), existingNode) : this._newNodeForItem(newItem); Batman.DOM.insertBefore(this.parentNode(), node, nodeAtIndex); } } } unseenNodeMap.forEach(function(item, node) { if (_this._nodesToBeRendered.has(node)) { _this._nodesToBeRemoved || (_this._nodesToBeRemoved = new Batman.SimpleSet); return _this._nodesToBeRemoved.add(node); } else { return _this._removeItem(item); } }); }; IteratorBinding.prototype._itemForNode = function(node) { return Batman._data(node, "" + this.iteratorName + "Item"); }; IteratorBinding.prototype._newNodeForItem = function(newItem) { var newNode, renderer, _this = this; newNode = this.prototypeNode.cloneNode(true); this._nodesToBeRendered || (this._nodesToBeRendered = new Batman.SimpleSet); this._nodesToBeRendered.add(newNode); Batman._data(newNode, "" + this.iteratorName + "Item", newItem); this.nodeMap.set(newItem, newNode); this.parentRenderer.prevent('rendered'); renderer = new Batman.Renderer(newNode, this.renderContext.descend(newItem, this.iteratorName), this.parentRenderer.view); renderer.once('rendered', function() { var _ref; _this._nodesToBeRendered.remove(newNode); if ((_ref = _this._nodesToBeRemoved) != null ? _ref.has(newNode) : void 0) { _this._nodesToBeRemoved.remove(newNode); _this._removeItem(newItem); } else { Batman.DOM.propagateBindingEvents(newNode); _this.fire('nodeAdded', newNode, newItem); } return _this.parentRenderer.allowAndFire('rendered'); }); return newNode; }; IteratorBinding.prototype._getStartNodeIndex = function() { var index, node, _i, _len, _ref; _ref = this.parentNode().childNodes; for (index = _i = 0, _len = _ref.length; _i < _len; index = ++_i) { node = _ref[index]; if (node === this.startNode) { return index; } } return 0; }; IteratorBinding.prototype._removeItem = function(item) { var node; node = this.nodeMap.unset(item); Batman.DOM.destroyNode(node); return this.fire('nodeRemoved', node, item); }; IteratorBinding.prototype.die = function() { var _ref; if (this._nodesToBeRendered && !this._nodesToBeRendered.isEmpty()) { this._nodesToBeRemoved || (this._nodesToBeRemoved = new Batman.SimpleSet); (_ref = this._nodesToBeRemoved).add.apply(_ref, this._nodesToBeRendered.toArray()); } return IteratorBinding.__super__.die.apply(this, arguments); }; return IteratorBinding; })(Batman.DOM.AbstractCollectionBinding); }).call(this); (function() { var __bind = function(fn, me) { return function() { return fn.apply(me, arguments); }; }, __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Batman.DOM.ClassBinding = (function(_super) { __extends(ClassBinding, _super); function ClassBinding() { this.handleArrayChanged = __bind(this.handleArrayChanged, this); return ClassBinding.__super__.constructor.apply(this, arguments); } ClassBinding.prototype.onlyObserve = Batman.BindingDefinitionOnlyObserve.Data; ClassBinding.prototype.dataChange = function(value) { if (value != null) { this.unbindCollection(); if (typeof value === 'string') { return this.node.className = value; } else { this.bindCollection(value); return this.updateFromCollection(); } } }; ClassBinding.prototype.updateFromCollection = function() { var array, k, v; if (this.collection) { array = this.collection.map ? this.collection.map(function(x) { return x; }) : (function() { var _ref, _results; _ref = this.collection; _results = []; for (k in _ref) { if (!__hasProp.call(_ref, k)) continue; v = _ref[k]; _results.push(k); } return _results; }).call(this); if (array.toArray != null) { array = array.toArray(); } return this.node.className = array.join(' '); } }; ClassBinding.prototype.handleArrayChanged = function() { return this.updateFromCollection(); }; return ClassBinding; })(Batman.DOM.AbstractCollectionBinding); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Batman.ValidationError = (function(_super) { __extends(ValidationError, _super); ValidationError.accessor('fullMessage', function() { return Batman.t('errors.format', { attribute: Batman.helpers.humanize(this.attribute), message: this.message }); }); function ValidationError(attribute, message) { ValidationError.__super__.constructor.call(this, { attribute: attribute, message: message }); } return ValidationError; })(Batman.Object); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, __slice = [].slice; Batman.StorageAdapter = (function(_super) { __extends(StorageAdapter, _super); StorageAdapter.StorageError = (function(_super1) { __extends(StorageError, _super1); StorageError.prototype.name = "StorageError"; function StorageError(message) { StorageError.__super__.constructor.apply(this, arguments); this.message = message; } return StorageError; })(Error); StorageAdapter.RecordExistsError = (function(_super1) { __extends(RecordExistsError, _super1); RecordExistsError.prototype.name = 'RecordExistsError'; function RecordExistsError(message) { RecordExistsError.__super__.constructor.call(this, message || "Can't create this record because it already exists in the store!"); } return RecordExistsError; })(StorageAdapter.StorageError); StorageAdapter.NotFoundError = (function(_super1) { __extends(NotFoundError, _super1); NotFoundError.prototype.name = 'NotFoundError'; function NotFoundError(message) { NotFoundError.__super__.constructor.call(this, message || "Record couldn't be found in storage!"); } return NotFoundError; })(StorageAdapter.StorageError); StorageAdapter.NotAllowedError = (function(_super1) { __extends(NotAllowedError, _super1); NotAllowedError.prototype.name = "NotAllowedError"; function NotAllowedError(message) { NotAllowedError.__super__.constructor.call(this, message || "Storage operation denied access to the operation!"); } return NotAllowedError; })(StorageAdapter.StorageError); StorageAdapter.NotAcceptableError = (function(_super1) { __extends(NotAcceptableError, _super1); NotAcceptableError.prototype.name = "NotAcceptableError"; function NotAcceptableError(message) { NotAcceptableError.__super__.constructor.call(this, message || "Storage operation permitted but the request was malformed!"); } return NotAcceptableError; })(StorageAdapter.StorageError); StorageAdapter.UnprocessableRecordError = (function(_super1) { __extends(UnprocessableRecordError, _super1); UnprocessableRecordError.prototype.name = "UnprocessableRecordError"; function UnprocessableRecordError(message) { UnprocessableRecordError.__super__.constructor.call(this, message || "Storage adapter could not process the record!"); } return UnprocessableRecordError; })(StorageAdapter.StorageError); StorageAdapter.InternalStorageError = (function(_super1) { __extends(InternalStorageError, _super1); InternalStorageError.prototype.name = "InternalStorageError"; function InternalStorageError(message) { InternalStorageError.__super__.constructor.call(this, message || "An error occured during the storage operation!"); } return InternalStorageError; })(StorageAdapter.StorageError); StorageAdapter.NotImplementedError = (function(_super1) { __extends(NotImplementedError, _super1); NotImplementedError.prototype.name = "NotImplementedError"; function NotImplementedError(message) { NotImplementedError.__super__.constructor.call(this, message || "This operation is not implemented by the storage adpater!"); } return NotImplementedError; })(StorageAdapter.StorageError); function StorageAdapter(model) { var constructor; StorageAdapter.__super__.constructor.call(this, { model: model }); constructor = this.constructor; if (constructor.ModelMixin) { Batman.extend(model, constructor.ModelMixin); } if (constructor.RecordMixin) { Batman.extend(model.prototype, constructor.RecordMixin); } } StorageAdapter.prototype.isStorageAdapter = true; StorageAdapter.prototype.storageKey = function(record) { var model; model = (record != null ? record.constructor : void 0) || this.model; return model.get('storageKey') || Batman.helpers.pluralize(Batman.helpers.underscore(model.get('resourceName'))); }; StorageAdapter.prototype.getRecordFromData = function(attributes, constructor) { var record; if (constructor == null) { constructor = this.model; } record = new constructor(); record._withoutDirtyTracking(function() { return this.fromJSON(attributes); }); return record; }; StorageAdapter.skipIfError = function(f) { return function(env, next) { if (env.error != null) { return next(); } else { return f.call(this, env, next); } }; }; StorageAdapter.prototype.before = function() { return this._addFilter.apply(this, ['before'].concat(__slice.call(arguments))); }; StorageAdapter.prototype.after = function() { return this._addFilter.apply(this, ['after'].concat(__slice.call(arguments))); }; StorageAdapter.prototype._inheritFilters = function() { var filtersByKey, filtersList, key, oldFilters, position, _results; if (!this._batman.check(this) || !this._batman.filters) { oldFilters = this._batman.getFirst('filters'); this._batman.filters = { before: {}, after: {} }; if (oldFilters != null) { _results = []; for (position in oldFilters) { filtersByKey = oldFilters[position]; _results.push((function() { var _results1; _results1 = []; for (key in filtersByKey) { filtersList = filtersByKey[key]; _results1.push(this._batman.filters[position][key] = filtersList.slice(0)); } return _results1; }).call(this)); } return _results; } } }; StorageAdapter.prototype._addFilter = function() { var filter, key, keys, position, _base, _i, _j, _len; position = arguments[0], keys = 3 <= arguments.length ? __slice.call(arguments, 1, _i = arguments.length - 1) : (_i = 1, []), filter = arguments[_i++]; this._inheritFilters(); for (_j = 0, _len = keys.length; _j < _len; _j++) { key = keys[_j]; (_base = this._batman.filters[position])[key] || (_base[key] = []); this._batman.filters[position][key].push(filter); } return true; }; StorageAdapter.prototype.runFilter = function(position, action, env, callback) { var actionFilters, allFilters, filters, next, _this = this; this._inheritFilters(); allFilters = this._batman.filters[position].all || []; actionFilters = this._batman.filters[position][action] || []; env.action = action; filters = position === 'before' ? actionFilters.concat(allFilters) : allFilters.concat(actionFilters); next = function(newEnv) { var nextFilter; if (newEnv != null) { env = newEnv; } if ((nextFilter = filters.shift()) != null) { return nextFilter.call(_this, env, next); } else { return callback.call(_this, env); } }; return next(); }; StorageAdapter.prototype.runBeforeFilter = function() { return this.runFilter.apply(this, ['before'].concat(__slice.call(arguments))); }; StorageAdapter.prototype.runAfterFilter = function(action, env, callback) { return this.runFilter('after', action, env, this.exportResult(callback)); }; StorageAdapter.prototype.exportResult = function(callback) { return function(env) { return callback(env.error, env.result, env); }; }; StorageAdapter.prototype._jsonToAttributes = function(json) { return JSON.parse(json); }; StorageAdapter.prototype.perform = function(key, subject, options, callback) { var env, next, _this = this; options || (options = {}); env = { options: options, subject: subject }; next = function(newEnv) { if (newEnv != null) { env = newEnv; } return _this.runAfterFilter(key, env, callback); }; this.runBeforeFilter(key, env, function(env) { return this[key](env, next); }); return void 0; }; return StorageAdapter; })(Batman.Object); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, __slice = [].slice, __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; Batman.RestStorage = (function(_super) { var key, _fn, _i, _len, _ref, _this = this; __extends(RestStorage, _super); RestStorage.CommunicationError = (function(_super1) { __extends(CommunicationError, _super1); CommunicationError.prototype.name = 'CommunicationError'; function CommunicationError(message) { CommunicationError.__super__.constructor.call(this, message || "A communication error has occurred!"); } return CommunicationError; })(RestStorage.StorageError); RestStorage.JSONContentType = 'application/json'; RestStorage.PostBodyContentType = 'application/x-www-form-urlencoded'; RestStorage.BaseMixin = { request: function(action, options, callback) { if (!callback) { callback = options; options = {}; } options.method || (options.method = 'GET'); options.action = action; return this._doStorageOperation(options.method.toLowerCase(), options, callback); } }; RestStorage.ModelMixin = Batman.extend({}, RestStorage.BaseMixin, { urlNestsUnder: function() { var key, keys, parents, _i, _len; keys = 1 <= arguments.length ? __slice.call(arguments, 0) : []; parents = {}; for (_i = 0, _len = keys.length; _i < _len; _i++) { key = keys[_i]; parents[key + '_id'] = Batman.helpers.pluralize(key); } this.url = function(options) { var childSegment, parentID, plural; childSegment = Batman.helpers.pluralize(this.get('resourceName').toLowerCase()); for (key in parents) { plural = parents[key]; parentID = options.data[key]; if (parentID) { delete options.data[key]; return "" + plural + "/" + parentID + "/" + childSegment; } } return childSegment; }; return this.prototype.url = function() { var childSegment, id, parentID, plural, url; childSegment = Batman.helpers.pluralize(this.constructor.get('resourceName').toLowerCase()); for (key in parents) { plural = parents[key]; parentID = this.get('dirtyKeys').get(key); if (parentID === void 0) { parentID = this.get(key); } if (parentID) { url = "" + plural + "/" + parentID + "/" + childSegment; break; } } url || (url = childSegment); if (id = this.get('id')) { url += '/' + id; } return url; }; } }); RestStorage.RecordMixin = Batman.extend({}, RestStorage.BaseMixin); RestStorage.prototype.defaultRequestOptions = { type: 'json' }; RestStorage.prototype._implicitActionNames = ['create', 'read', 'update', 'destroy', 'readAll']; RestStorage.prototype.serializeAsForm = true; function RestStorage() { RestStorage.__super__.constructor.apply(this, arguments); this.defaultRequestOptions = Batman.extend({}, this.defaultRequestOptions); } RestStorage.prototype.recordJsonNamespace = function(record) { return Batman.helpers.singularize(this.storageKey(record)); }; RestStorage.prototype.collectionJsonNamespace = function(constructor) { return Batman.helpers.pluralize(this.storageKey(constructor.prototype)); }; RestStorage.prototype._execWithOptions = function(object, key, options, context) { if (context == null) { context = object; } if (typeof object[key] === 'function') { return object[key].call(context, options); } else { return object[key]; } }; RestStorage.prototype._defaultCollectionUrl = function(model) { return "" + (this.storageKey(model.prototype)); }; RestStorage.prototype._addParams = function(url, options) { var _ref; if (options && options.action && !(_ref = options.action, __indexOf.call(this._implicitActionNames, _ref) >= 0)) { url += '/' + options.action.toLowerCase(); } return url; }; RestStorage.prototype._addUrlAffixes = function(url, subject, env) { var prefix, segments; segments = [url, this.urlSuffix(subject, env)]; if (url.charAt(0) !== '/') { prefix = this.urlPrefix(subject, env); if (prefix.charAt(prefix.length - 1) !== '/') { segments.unshift('/'); } segments.unshift(prefix); } return segments.join(''); }; RestStorage.prototype.urlPrefix = function(object, env) { return this._execWithOptions(object, 'urlPrefix', env.options) || ''; }; RestStorage.prototype.urlSuffix = function(object, env) { return this._execWithOptions(object, 'urlSuffix', env.options) || ''; }; RestStorage.prototype.urlForRecord = function(record, env) { var id, url, _ref; if ((_ref = env.options) != null ? _ref.recordUrl : void 0) { url = this._execWithOptions(env.options, 'recordUrl', env.options, record); } else if (record.url) { url = this._execWithOptions(record, 'url', env.options); } else { url = record.constructor.url ? this._execWithOptions(record.constructor, 'url', env.options) : this._defaultCollectionUrl(record.constructor); if (env.action !== 'create') { if ((id = record.get('id')) != null) { url = url + "/" + id; } else { throw new this.constructor.StorageError("Couldn't get/set record primary key on " + env.action + "!"); } } } return this._addUrlAffixes(this._addParams(url, env.options), record, env); }; RestStorage.prototype.urlForCollection = function(model, env) { var url, _ref; url = ((_ref = env.options) != null ? _ref.collectionUrl : void 0) ? this._execWithOptions(env.options, 'collectionUrl', env.options, env.options.urlContext) : model.url ? this._execWithOptions(model, 'url', env.options) : this._defaultCollectionUrl(model, env.options); return this._addUrlAffixes(this._addParams(url, env.options), model, env); }; RestStorage.prototype.request = function(env, next) { var options; options = Batman.extend(env.options, { autosend: false, success: function(data) { return env.data = data; }, error: function(error) { return env.error = error; }, loaded: function() { env.response = env.request.get('response'); return next(); } }); env.request = new Batman.Request(options); return env.request.send(); }; RestStorage.prototype.perform = function(key, record, options, callback) { options || (options = {}); Batman.extend(options, this.defaultRequestOptions); return RestStorage.__super__.perform.call(this, key, record, options, callback); }; RestStorage.prototype.before('all', RestStorage.skipIfError(function(env, next) { if (!env.options.url) { try { env.options.url = env.subject.prototype ? this.urlForCollection(env.subject, env) : this.urlForRecord(env.subject, env); } catch (error) { env.error = error; } } return next(); })); RestStorage.prototype.before('get', 'put', 'post', 'delete', RestStorage.skipIfError(function(env, next) { env.options.method = env.action.toUpperCase(); return next(); })); RestStorage.prototype.before('create', 'update', RestStorage.skipIfError(function(env, next) { var data, json, namespace; json = env.subject.toJSON(); if (namespace = this.recordJsonNamespace(env.subject)) { data = {}; data[namespace] = json; } else { data = json; } env.options.data = data; return next(); })); RestStorage.prototype.before('create', 'update', 'put', 'post', RestStorage.skipIfError(function(env, next) { if (this.serializeAsForm) { env.options.contentType = this.constructor.PostBodyContentType; } else { if (env.options.data != null) { env.options.data = JSON.stringify(env.options.data); env.options.contentType = this.constructor.JSONContentType; } } return next(); })); RestStorage.prototype.after('all', RestStorage.skipIfError(function(env, next) { var json; if (!(env.data != null)) { return next(); } if (typeof env.data === 'string') { if (env.data.length > 0) { try { json = this._jsonToAttributes(env.data); } catch (error) { env.error = error; return next(); } } } else if (typeof env.data === 'object') { json = env.data; } if (json != null) { env.json = json; } return next(); })); RestStorage.prototype.extractFromNamespace = function(data, namespace) { if (namespace && (data[namespace] != null)) { return data[namespace]; } else { return data; } }; RestStorage.prototype.after('create', 'read', 'update', RestStorage.skipIfError(function(env, next) { var json; if (env.json != null) { json = this.extractFromNamespace(env.json, this.recordJsonNamespace(env.subject)); env.subject._withoutDirtyTracking(function() { return this.fromJSON(json); }); } env.result = env.subject; return next(); })); RestStorage.prototype.after('readAll', RestStorage.skipIfError(function(env, next) { var jsonRecordAttributes, namespace; namespace = this.collectionJsonNamespace(env.subject); env.recordsAttributes = this.extractFromNamespace(env.json, namespace); if (Batman.typeOf(env.recordsAttributes) !== 'Array') { namespace = this.recordJsonNamespace(env.subject.prototype); env.recordsAttributes = [this.extractFromNamespace(env.json, namespace)]; } env.result = env.records = (function() { var _i, _len, _ref, _results; _ref = env.recordsAttributes; _results = []; for (_i = 0, _len = _ref.length; _i < _len; _i++) { jsonRecordAttributes = _ref[_i]; _results.push(this.getRecordFromData(jsonRecordAttributes, env.subject)); } return _results; }).call(this); return next(); })); RestStorage.prototype.after('get', 'put', 'post', 'delete', RestStorage.skipIfError(function(env, next) { var json, namespace; if (env.json != null) { json = env.json; namespace = env.subject.prototype ? this.collectionJsonNamespace(env.subject) : this.recordJsonNamespace(env.subject); env.result = namespace && (env.json[namespace] != null) ? env.json[namespace] : env.json; } return next(); })); RestStorage.HTTPMethods = { create: 'POST', update: 'PUT', read: 'GET', readAll: 'GET', destroy: 'DELETE' }; _ref = ['create', 'read', 'update', 'destroy', 'readAll', 'get', 'post', 'put', 'delete']; _fn = function(key) { return RestStorage.prototype[key] = RestStorage.skipIfError(function(env, next) { var _base; (_base = env.options).method || (_base.method = this.constructor.HTTPMethods[key]); return this.request(env, next); }); }; for (_i = 0, _len = _ref.length; _i < _len; _i++) { key = _ref[_i]; _fn(key); } RestStorage.prototype.after('all', function(env, next) { if (env.error) { env.error = this._errorFor(env.error, env); } return next(); }); RestStorage._statusCodeErrors = { '0': RestStorage.CommunicationError, '403': RestStorage.NotAllowedError, '404': RestStorage.NotFoundError, '406': RestStorage.NotAcceptableError, '409': RestStorage.RecordExistsError, '422': RestStorage.UnprocessableRecordError, '500': RestStorage.InternalStorageError, '501': RestStorage.NotImplementedError }; RestStorage.prototype._errorFor = function(error, env) { var errorClass, request; if (error instanceof Error || !(error.request != null)) { return error; } if (errorClass = this.constructor._statusCodeErrors[error.request.status]) { request = error.request; error = new errorClass; error.request = request; error.env = env; } return error; }; return RestStorage; }).call(this, Batman.StorageAdapter); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Batman.LocalStorage = (function(_super) { __extends(LocalStorage, _super); function LocalStorage() { if (typeof window.localStorage === 'undefined') { return null; } LocalStorage.__super__.constructor.apply(this, arguments); this.storage = localStorage; } LocalStorage.prototype.storageRegExpForRecord = function(record) { return new RegExp("^" + (this.storageKey(record)) + "(\\d+)$"); }; LocalStorage.prototype.nextIdForRecord = function(record) { var nextId, re; re = this.storageRegExpForRecord(record); nextId = 1; this._forAllStorageEntries(function(k, v) { var matches; if (matches = re.exec(k)) { return nextId = Math.max(nextId, parseInt(matches[1], 10) + 1); } }); return nextId; }; LocalStorage.prototype._forAllStorageEntries = function(iterator) { var i, key, _i, _ref; for (i = _i = 0, _ref = this.storage.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) { key = this.storage.key(i); iterator.call(this, key, this.storage.getItem(key)); } return true; }; LocalStorage.prototype._storageEntriesMatching = function(constructor, options) { var re, records; re = this.storageRegExpForRecord(constructor.prototype); records = []; this._forAllStorageEntries(function(storageKey, storageString) { var data, keyMatches; if (keyMatches = re.exec(storageKey)) { data = this._jsonToAttributes(storageString); data[constructor.primaryKey] = keyMatches[1]; if (this._dataMatches(options, data)) { return records.push(data); } } }); return records; }; LocalStorage.prototype._dataMatches = function(conditions, data) { var k, match, v; match = true; for (k in conditions) { v = conditions[k]; if (data[k] !== v) { match = false; break; } } return match; }; LocalStorage.prototype.before('read', 'create', 'update', 'destroy', LocalStorage.skipIfError(function(env, next) { var _this = this; if (env.action === 'create') { env.id = env.subject.get('id') || env.subject._withoutDirtyTracking(function() { return env.subject.set('id', _this.nextIdForRecord(env.subject)); }); } else { env.id = env.subject.get('id'); } if (env.id == null) { env.error = new this.constructor.StorageError("Couldn't get/set record primary key on " + env.action + "!"); } else { env.key = this.storageKey(env.subject) + env.id; } return next(); })); LocalStorage.prototype.before('create', 'update', LocalStorage.skipIfError(function(env, next) { env.recordAttributes = JSON.stringify(env.subject); return next(); })); LocalStorage.prototype.after('read', LocalStorage.skipIfError(function(env, next) { if (typeof env.recordAttributes === 'string') { try { env.recordAttributes = this._jsonToAttributes(env.recordAttributes); } catch (error) { env.error = error; return next(); } } env.subject._withoutDirtyTracking(function() { return this.fromJSON(env.recordAttributes); }); return next(); })); LocalStorage.prototype.after('read', 'create', 'update', 'destroy', LocalStorage.skipIfError(function(env, next) { env.result = env.subject; return next(); })); LocalStorage.prototype.after('readAll', LocalStorage.skipIfError(function(env, next) { var recordAttributes; env.result = env.records = (function() { var _i, _len, _ref, _results; _ref = env.recordsAttributes; _results = []; for (_i = 0, _len = _ref.length; _i < _len; _i++) { recordAttributes = _ref[_i]; _results.push(this.getRecordFromData(recordAttributes, env.subject)); } return _results; }).call(this); return next(); })); LocalStorage.prototype.read = LocalStorage.skipIfError(function(env, next) { env.recordAttributes = this.storage.getItem(env.key); if (!env.recordAttributes) { env.error = new this.constructor.NotFoundError(); } return next(); }); LocalStorage.prototype.create = LocalStorage.skipIfError(function(_arg, next) { var key, recordAttributes; key = _arg.key, recordAttributes = _arg.recordAttributes; if (this.storage.getItem(key)) { arguments[0].error = new this.constructor.RecordExistsError; } else { this.storage.setItem(key, recordAttributes); } return next(); }); LocalStorage.prototype.update = LocalStorage.skipIfError(function(_arg, next) { var key, recordAttributes; key = _arg.key, recordAttributes = _arg.recordAttributes; this.storage.setItem(key, recordAttributes); return next(); }); LocalStorage.prototype.destroy = LocalStorage.skipIfError(function(_arg, next) { var key; key = _arg.key; this.storage.removeItem(key); return next(); }); LocalStorage.prototype.readAll = LocalStorage.skipIfError(function(env, next) { try { arguments[0].recordsAttributes = this._storageEntriesMatching(env.subject, env.options.data); } catch (error) { arguments[0].error = error; } return next(); }); return LocalStorage; })(Batman.StorageAdapter); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Batman.SessionStorage = (function(_super) { __extends(SessionStorage, _super); function SessionStorage() { if (typeof window.sessionStorage === 'undefined') { return null; } SessionStorage.__super__.constructor.apply(this, arguments); this.storage = sessionStorage; } return SessionStorage; })(Batman.LocalStorage); }).call(this); (function() { Batman.Encoders = new Batman.Object; }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Batman.ParamsReplacer = (function(_super) { __extends(ParamsReplacer, _super); function ParamsReplacer(navigator, params) { this.navigator = navigator; this.params = params; } ParamsReplacer.prototype.redirect = function() { return this.navigator.replace(this.toObject()); }; ParamsReplacer.prototype.replace = function(params) { this.params.replace(params); return this.redirect(); }; ParamsReplacer.prototype.update = function(params) { this.params.update(params); return this.redirect(); }; ParamsReplacer.prototype.clear = function() { this.params.clear(); return this.redirect(); }; ParamsReplacer.prototype.toObject = function() { return this.params.toObject(); }; ParamsReplacer.accessor({ get: function(k) { return this.params.get(k); }, set: function(k, v) { var oldValue, result; oldValue = this.params.get(k); result = this.params.set(k, v); if (oldValue !== v) { this.redirect(); } return result; }, unset: function(k) { var hadKey, result; hadKey = this.params.hasKey(k); result = this.params.unset(k); if (hadKey) { this.redirect(); } return result; } }); return ParamsReplacer; })(Batman.Object); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Batman.ParamsPusher = (function(_super) { __extends(ParamsPusher, _super); function ParamsPusher() { return ParamsPusher.__super__.constructor.apply(this, arguments); } ParamsPusher.prototype.redirect = function() { return this.navigator.push(this.toObject()); }; return ParamsPusher; })(Batman.ParamsReplacer); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Batman.NamedRouteQuery = (function(_super) { __extends(NamedRouteQuery, _super); NamedRouteQuery.prototype.isNamedRouteQuery = true; function NamedRouteQuery(routeMap, args) { var key; if (args == null) { args = []; } NamedRouteQuery.__super__.constructor.call(this, { routeMap: routeMap, args: args }); for (key in this.get('routeMap').childrenByName) { this[key] = this._queryAccess.bind(this, key); } } NamedRouteQuery.accessor('route', function() { var collectionRoute, memberRoute, route, _i, _len, _ref, _ref1; _ref = this.get('routeMap'), memberRoute = _ref.memberRoute, collectionRoute = _ref.collectionRoute; _ref1 = [memberRoute, collectionRoute]; for (_i = 0, _len = _ref1.length; _i < _len; _i++) { route = _ref1[_i]; if (route != null) { if (route.namedArguments.length === this.get('args').length) { return route; } } } return collectionRoute || memberRoute; }); NamedRouteQuery.accessor('path', function() { return this.path(); }); NamedRouteQuery.accessor('routeMap', 'args', 'cardinality', 'hashValue', Batman.Property.defaultAccessor); NamedRouteQuery.accessor({ get: function(key) { if (key == null) { return; } if (typeof key === 'string') { return this.nextQueryForName(key); } else { return this.nextQueryWithArgument(key); } }, cache: false }); NamedRouteQuery.accessor('withHash', function() { var _this = this; return new Batman.Accessible(function(hashValue) { return _this.withHash(hashValue); }); }); NamedRouteQuery.prototype.withHash = function(hashValue) { var clone; clone = this.clone(); clone.set('hashValue', hashValue); return clone; }; NamedRouteQuery.prototype.nextQueryForName = function(key) { var map; if (map = this.get('routeMap').childrenByName[key]) { return new Batman.NamedRouteQuery(map, this.args); } else { return Batman.developer.error("Couldn't find a route for the name " + key + "!"); } }; NamedRouteQuery.prototype.nextQueryWithArgument = function(arg) { var args; args = this.args.slice(0); args.push(arg); return this.clone(args); }; NamedRouteQuery.prototype.path = function() { var argumentName, argumentValue, index, namedArguments, params, _i, _len; params = {}; namedArguments = this.get('route.namedArguments'); for (index = _i = 0, _len = namedArguments.length; _i < _len; index = ++_i) { argumentName = namedArguments[index]; if ((argumentValue = this.get('args')[index]) != null) { params[argumentName] = this._toParam(argumentValue); } } if (this.get('hashValue') != null) { params['#'] = this.get('hashValue'); } return this.get('route').pathFromParams(params); }; NamedRouteQuery.prototype.toString = function() { return this.path(); }; NamedRouteQuery.prototype.clone = function(args) { if (args == null) { args = this.args; } return new Batman.NamedRouteQuery(this.routeMap, args); }; NamedRouteQuery.prototype._toParam = function(arg) { if (arg instanceof Batman.AssociationProxy) { arg = arg.get('target'); } if ((arg != null ? arg.toParam : void 0) != null) { return arg.toParam(); } else { return arg; } }; NamedRouteQuery.prototype._queryAccess = function(key, arg) { var query; query = this.nextQueryForName(key); if (arg != null) { query = query.nextQueryWithArgument(arg); } return query; }; return NamedRouteQuery; })(Batman.Object); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Batman.Dispatcher = (function(_super) { var ControllerDirectory; __extends(Dispatcher, _super); Dispatcher.canInferRoute = function(argument) { return argument instanceof Batman.Model || argument instanceof Batman.AssociationProxy || argument.prototype instanceof Batman.Model; }; Dispatcher.paramsFromArgument = function(argument) { var resourceNameFromModel; resourceNameFromModel = function(model) { return Batman.helpers.camelize(Batman.helpers.pluralize(model.get('resourceName')), true); }; if (!this.canInferRoute(argument)) { return argument; } if (argument instanceof Batman.Model || argument instanceof Batman.AssociationProxy) { if (argument.isProxy) { argument = argument.get('target'); } if (argument != null) { return { controller: resourceNameFromModel(argument.constructor), action: 'show', id: argument.get('id') }; } else { return {}; } } else if (argument.prototype instanceof Batman.Model) { return { controller: resourceNameFromModel(argument), action: 'index' }; } else { return argument; } }; ControllerDirectory = (function(_super1) { __extends(ControllerDirectory, _super1); function ControllerDirectory() { return ControllerDirectory.__super__.constructor.apply(this, arguments); } ControllerDirectory.accessor('__app', Batman.Property.defaultAccessor); ControllerDirectory.accessor(function(key) { return this.get("__app." + (Batman.helpers.capitalize(key)) + "Controller.sharedController"); }); return ControllerDirectory; })(Batman.Object); Dispatcher.accessor('controllers', function() { return new ControllerDirectory({ __app: this.get('app') }); }); function Dispatcher(app, routeMap) { Dispatcher.__super__.constructor.call(this, { app: app, routeMap: routeMap }); } Dispatcher.prototype.routeForParams = function(params) { params = this.constructor.paramsFromArgument(params); return this.get('routeMap').routeForParams(params); }; Dispatcher.prototype.pathFromParams = function(params) { var _ref; if (typeof params === 'string') { return params; } params = this.constructor.paramsFromArgument(params); return (_ref = this.routeForParams(params)) != null ? _ref.pathFromParams(params) : void 0; }; Dispatcher.prototype.dispatch = function(params) { var error, inferredParams, path, route, _ref, _ref1; inferredParams = this.constructor.paramsFromArgument(params); route = this.routeForParams(inferredParams); if (route) { _ref = route.pathAndParamsFromArgument(inferredParams), path = _ref[0], params = _ref[1]; this.set('app.currentRoute', route); this.set('app.currentURL', path); this.get('app.currentParams').replace(params || {}); route.dispatch(params); } else { if (Batman.typeOf(params) === 'Object' && !this.constructor.canInferRoute(params)) { return this.get('app.currentParams').replace(params); } else { this.get('app.currentParams').clear(); } error = { type: '404', isPrevented: false, preventDefault: function() { return this.isPrevented = true; } }; if ((_ref1 = Batman.currentApp) != null) { _ref1.fire('error', error); } if (error.isPrevented) { return params; } if (params !== '/404') { return Batman.redirect('/404'); } } return path; }; return Dispatcher; }).call(this, Batman.Object); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Batman.Route = (function(_super) { __extends(Route, _super); Route.regexps = { namedParam: /:([\w\d]+)/g, splatParam: /\*([\w\d]+)/g, queryParam: '(?:\\?.+)?', namedOrSplat: /[:|\*]([\w\d]+)/g, namePrefix: '[:|\*]', escapeRegExp: /[-[\]{}+?.,\\^$|#\s]/g, openOptParam: /\(/g, closeOptParam: /\)/g }; Route.prototype.optionKeys = ['member', 'collection']; Route.prototype.testKeys = ['controller', 'action']; Route.prototype.isRoute = true; function Route(templatePath, baseParams) { var k, matches, namedArguments, pattern, properties, regexp, regexps, _i, _len, _ref; regexps = this.constructor.regexps; if (templatePath.indexOf('/') !== 0) { templatePath = "/" + templatePath; } pattern = templatePath.replace(regexps.escapeRegExp, '\\$&'); regexp = RegExp("^" + (pattern.replace(regexps.openOptParam, '(?:').replace(regexps.closeOptParam, ')?').replace(regexps.namedParam, '([^\/]+)').replace(regexps.splatParam, '(.*?)')) + regexps.queryParam + "$"); regexps.namedOrSplat.lastIndex = 0; namedArguments = ((function() { var _results; _results = []; while (matches = regexps.namedOrSplat.exec(pattern)) { _results.push(matches[1]); } return _results; })()); properties = { templatePath: templatePath, pattern: pattern, regexp: regexp, namedArguments: namedArguments, baseParams: baseParams }; _ref = this.optionKeys; for (_i = 0, _len = _ref.length; _i < _len; _i++) { k = _ref[_i]; properties[k] = baseParams[k]; delete baseParams[k]; } Route.__super__.constructor.call(this, properties); } Route.prototype.paramsFromPath = function(pathAndQuery) { var index, match, matches, name, namedArguments, params, uri, _i, _len; uri = new Batman.URI(pathAndQuery); namedArguments = this.get('namedArguments'); params = Batman.extend({ path: uri.path }, this.get('baseParams')); matches = this.get('regexp').exec(uri.path).slice(1); for (index = _i = 0, _len = matches.length; _i < _len; index = ++_i) { match = matches[index]; name = namedArguments[index]; params[name] = match; } return Batman.extend(params, uri.queryParams); }; Route.prototype.pathFromParams = function(argumentParams) { var hash, key, name, newPath, params, path, query, regexp, regexps, _i, _j, _len, _len1, _ref, _ref1; params = Batman.extend({}, argumentParams); path = this.get('templatePath'); regexps = this.constructor.regexps; _ref = this.get('namedArguments'); for (_i = 0, _len = _ref.length; _i < _len; _i++) { name = _ref[_i]; regexp = RegExp("" + regexps.namePrefix + name); newPath = path.replace(regexp, (params[name] != null ? params[name] : '')); if (newPath !== path) { delete params[name]; path = newPath; } } path = path.replace(regexps.openOptParam, '').replace(regexps.closeOptParam, '').replace(/([^\/])\/+$/, '$1'); _ref1 = this.testKeys; for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { key = _ref1[_j]; delete params[key]; } if (params['#']) { hash = params['#']; delete params['#']; } query = Batman.URI.queryFromParams(params); if (query) { path += "?" + query; } if (hash) { path += "#" + hash; } return path; }; Route.prototype.test = function(pathOrParams) { var key, path, value, _i, _len, _ref; if (typeof pathOrParams === 'string') { path = pathOrParams; } else if (pathOrParams.path != null) { path = pathOrParams.path; } else { path = this.pathFromParams(pathOrParams); _ref = this.testKeys; for (_i = 0, _len = _ref.length; _i < _len; _i++) { key = _ref[_i]; if ((value = this.get(key)) != null) { if (pathOrParams[key] !== value) { return false; } } } } return this.get('regexp').test(path); }; Route.prototype.pathAndParamsFromArgument = function(pathOrParams) { var params, path; if (typeof pathOrParams === 'string') { params = this.paramsFromPath(pathOrParams); path = pathOrParams; } else { params = pathOrParams; path = this.pathFromParams(pathOrParams); } return [path, params]; }; Route.prototype.dispatch = function(params) { if (!this.test(params)) { return false; } return this.get('callback')(params); }; Route.prototype.callback = function() { throw new Batman.DevelopmentError("Override callback in a Route subclass"); }; return Route; })(Batman.Object); }).call(this); (function() { var __bind = function(fn, me) { return function() { return fn.apply(me, arguments); }; }, __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Batman.ControllerActionRoute = (function(_super) { __extends(ControllerActionRoute, _super); ControllerActionRoute.prototype.optionKeys = ['member', 'collection', 'app', 'controller', 'action']; function ControllerActionRoute(templatePath, options) { this.callback = __bind(this.callback, this); var action, controller, _ref; if (options.signature) { _ref = options.signature.split('#'), controller = _ref[0], action = _ref[1]; action || (action = 'index'); options.controller = controller; options.action = action; delete options.signature; } ControllerActionRoute.__super__.constructor.call(this, templatePath, options); } ControllerActionRoute.prototype.callback = function(params) { var controller; controller = this.get("app.dispatcher.controllers." + (this.get('controller'))); return controller.dispatch(this.get('action'), params); }; return ControllerActionRoute; })(Batman.Route); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Batman.CallbackActionRoute = (function(_super) { __extends(CallbackActionRoute, _super); function CallbackActionRoute() { return CallbackActionRoute.__super__.constructor.apply(this, arguments); } CallbackActionRoute.prototype.optionKeys = ['member', 'collection', 'callback', 'app']; CallbackActionRoute.prototype.controller = false; CallbackActionRoute.prototype.action = false; return CallbackActionRoute; })(Batman.Route); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, __slice = [].slice; Batman.Hash = (function(_super) { var k, _fn, _i, _j, _len, _len1, _ref, _ref1, _this = this; __extends(Hash, _super); Hash.Metadata = (function(_super1) { __extends(Metadata, _super1); Batman.extend(Metadata.prototype, Batman.Enumerable); function Metadata(hash) { this.hash = hash; } Metadata.accessor('length', function() { this.hash.registerAsMutableSource(); return this.hash.length; }); Metadata.accessor('isEmpty', 'keys', 'toArray', function(key) { this.hash.registerAsMutableSource(); return this.hash[key](); }); Metadata.prototype.forEach = function() { var _ref; return (_ref = this.hash).forEach.apply(_ref, arguments); }; return Metadata; })(Batman.Object); function Hash() { this.meta = new this.constructor.Metadata(this); Batman.SimpleHash.apply(this, arguments); Hash.__super__.constructor.apply(this, arguments); } Batman.extend(Hash.prototype, Batman.Enumerable); Hash.prototype.propertyClass = Batman.Property; Hash.defaultAccessor = { get: Batman.SimpleHash.prototype.get, set: Hash.mutation(function(key, value) { var result; result = Batman.SimpleHash.prototype.set.call(this, key, value); this.fire('itemsWereAdded', key); return result; }), unset: Hash.mutation(function(key) { var result; result = Batman.SimpleHash.prototype.unset.call(this, key); if (result != null) { this.fire('itemsWereRemoved', key); } return result; }), cache: false }; Hash.accessor(Hash.defaultAccessor); Hash.prototype._preventMutationEvents = function(block) { this.prevent('change'); this.prevent('itemsWereAdded'); this.prevent('itemsWereRemoved'); try { return block.call(this); } finally { this.allow('change'); this.allow('itemsWereAdded'); this.allow('itemsWereRemoved'); } }; Hash.prototype.clear = Hash.mutation(function() { var keys, result; keys = this.keys(); this._preventMutationEvents(function() { var _this = this; return this.forEach(function(k) { return _this.unset(k); }); }); result = Batman.SimpleHash.prototype.clear.call(this); this.fire.apply(this, ['itemsWereRemoved'].concat(__slice.call(keys))); return result; }); Hash.prototype.update = Hash.mutation(function(object) { var addedKeys; addedKeys = []; this._preventMutationEvents(function() { var _this = this; return Batman.forEach(object, function(k, v) { if (!_this.hasKey(k)) { addedKeys.push(k); } return _this.set(k, v); }); }); if (addedKeys.length > 0) { return this.fire.apply(this, ['itemsWereAdded'].concat(__slice.call(addedKeys))); } }); Hash.prototype.replace = Hash.mutation(function(object) { var addedKeys, removedKeys; addedKeys = []; removedKeys = []; this._preventMutationEvents(function() { var _this = this; this.forEach(function(k, _) { if (!Batman.objectHasKey(object, k)) { _this.unset(k); return removedKeys.push(k); } }); return Batman.forEach(object, function(k, v) { if (!_this.hasKey(k)) { addedKeys.push(k); } return _this.set(k, v); }); }); if (addedKeys.length > 0) { this.fire.apply(this, ['itemsWereAdded'].concat(__slice.call(addedKeys))); } if (removedKeys.length > 0) { return this.fire.apply(this, ['itemsWereRemoved'].concat(__slice.call(removedKeys))); } }); _ref = ['equality', 'hashKeyFor', 'objectKey', 'prefixedKey', 'unprefixedKey']; for (_i = 0, _len = _ref.length; _i < _len; _i++) { k = _ref[_i]; Hash.prototype[k] = Batman.SimpleHash.prototype[k]; } _ref1 = ['hasKey', 'forEach', 'isEmpty', 'keys', 'toArray', 'merge', 'toJSON', 'toObject']; _fn = function(k) { return Hash.prototype[k] = function() { this.registerAsMutableSource(); return Batman.SimpleHash.prototype[k].apply(this, arguments); }; }; for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { k = _ref1[_j]; _fn(k); } return Hash; }).call(this, Batman.Object); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Batman.RenderCache = (function(_super) { __extends(RenderCache, _super); RenderCache.prototype.maximumLength = 4; function RenderCache() { RenderCache.__super__.constructor.apply(this, arguments); this.keyQueue = []; } RenderCache.prototype.viewForOptions = function(options) { var _this = this; if (options.cache === false || options.viewClass.prototype.cache === false) { return this._newViewFromOptions(options); } return this.getOrSet(options, function() { return _this._newViewFromOptions(Batman.extend({}, options)); }); }; RenderCache.prototype._newViewFromOptions = function(options) { return new options.viewClass(options); }; RenderCache.wrapAccessor(function(core) { return { cache: false, get: function(key) { var result; result = core.get.call(this, key); if (result) { this._addOrBubbleKey(key); } return result; }, set: function(key, value) { var result; result = core.set.apply(this, arguments); result.set('cached', true); this._addOrBubbleKey(key); this._evictExpiredKeys(); return result; }, unset: function(key) { var result; result = core.unset.apply(this, arguments); result.set('cached', false); this._removeKeyFromQueue(key); return result; } }; }); RenderCache.prototype.equality = function(incomingOptions, storageOptions) { var key; if (Object.keys(incomingOptions).length !== Object.keys(storageOptions).length) { return false; } for (key in incomingOptions) { if (!(key === 'view')) { if (incomingOptions[key] !== storageOptions[key]) { return false; } } } return true; }; RenderCache.prototype.reset = function() { var key, _i, _len, _ref, _results; _ref = this.keyQueue.slice(0); _results = []; for (_i = 0, _len = _ref.length; _i < _len; _i++) { key = _ref[_i]; _results.push(this.unset(key)); } return _results; }; RenderCache.prototype._addOrBubbleKey = function(key) { this._removeKeyFromQueue(key); return this.keyQueue.unshift(key); }; RenderCache.prototype._removeKeyFromQueue = function(key) { var index, queuedKey, _i, _len, _ref; _ref = this.keyQueue; for (index = _i = 0, _len = _ref.length; _i < _len; index = ++_i) { queuedKey = _ref[index]; if (this.equality(queuedKey, key)) { this.keyQueue.splice(index, 1); break; } } return key; }; RenderCache.prototype._evictExpiredKeys = function() { var currentKeys, i, key, _i, _ref, _ref1; if (this.length > this.maximumLength) { currentKeys = this.keyQueue.slice(0); for (i = _i = _ref = this.maximumLength, _ref1 = currentKeys.length; _ref <= _ref1 ? _i < _ref1 : _i > _ref1; i = _ref <= _ref1 ? ++_i : --_i) { key = currentKeys[i]; if (!this.get(key).isInDOM()) { this.unset(key); } } } }; return RenderCache; })(Batman.Hash); }).call(this); (function() { var __bind = function(fn, me) { return function() { return fn.apply(me, arguments); }; }, __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, __slice = [].slice, __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; Batman.Controller = (function(_super) { var _optionsFromFilterArguments; __extends(Controller, _super); Controller.singleton('sharedController'); Controller.wrapAccessor('routingKey', function(core) { return { get: function() { if (this.routingKey != null) { return this.routingKey; } else { if (Batman.config.minificationErrors) { Batman.developer.error("Please define `routingKey` on the prototype of " + (Batman.functionName(this.constructor)) + " in order for your controller to be minification safe."); } return Batman.functionName(this.constructor).replace(/Controller$/, ''); } } }; }); Controller.accessor('_renderContext', function() { return Batman.RenderContext.root().descend(this); }); _optionsFromFilterArguments = function(options, nameOrFunction) { if (!nameOrFunction) { nameOrFunction = options; options = {}; } else { if (typeof options === 'string') { options = { only: [options] }; } else { if (options.only && Batman.typeOf(options.only) !== 'Array') { options.only = [options.only]; } if (options.except && Batman.typeOf(options.except) !== 'Array') { options.except = [options.except]; } } } options.block = nameOrFunction; return options; }; Controller.beforeFilter = function() { var filters, options, _base; Batman.initializeObject(this); options = _optionsFromFilterArguments.apply(null, arguments); filters = (_base = this._batman).beforeFilters || (_base.beforeFilters = []); return filters.push(options); }; Controller.afterFilter = function() { var filters, options, _base; Batman.initializeObject(this); options = _optionsFromFilterArguments.apply(null, arguments); filters = (_base = this._batman).afterFilters || (_base.afterFilters = []); return filters.push(options); }; Controller.afterFilter(function(params) { if (this.autoScrollToHash && (params['#'] != null)) { return this.scrollToHash(params['#']); } }); Controller.catchError = function() { var currentHandlers, error, errors, handlers, options, _base, _i, _j, _len, _results; errors = 2 <= arguments.length ? __slice.call(arguments, 0, _i = arguments.length - 1) : (_i = 0, []), options = arguments[_i++]; Batman.initializeObject(this); (_base = this._batman).errorHandlers || (_base.errorHandlers = new Batman.SimpleHash); handlers = Batman.typeOf(options["with"]) === 'Array' ? options["with"] : [options["with"]]; _results = []; for (_j = 0, _len = errors.length; _j < _len; _j++) { error = errors[_j]; currentHandlers = this._batman.errorHandlers.get(error) || []; _results.push(this._batman.errorHandlers.set(error, currentHandlers.concat(handlers))); } return _results; }; Controller.prototype.errorHandler = function(callback) { var errorFrame, _ref, _this = this; errorFrame = (_ref = this._actionFrames) != null ? _ref[this._actionFrames.length - 1] : void 0; return function(err, result, env) { if (err) { if (errorFrame != null ? errorFrame.error : void 0) { return; } if (errorFrame != null) { errorFrame.error = err; } if (!_this.handleError(err)) { throw err; } } else { return typeof callback === "function" ? callback(result, env) : void 0; } }; }; Controller.prototype.handleError = function(error) { var handled, _ref, _this = this; handled = false; if ((_ref = this.constructor._batman.getAll('errorHandlers')) != null) { _ref.forEach(function(hash) { return hash.forEach(function(key, value) { var handler, _i, _len, _results; if (error instanceof key) { handled = true; _results = []; for (_i = 0, _len = value.length; _i < _len; _i++) { handler = value[_i]; _results.push(handler.call(_this, error)); } return _results; } }); }); } return handled; }; function Controller() { this.redirect = __bind(this.redirect, this); this.handleError = __bind(this.handleError, this); this.errorHandler = __bind(this.errorHandler, this); Controller.__super__.constructor.apply(this, arguments); this._resetActionFrames(); } Controller.prototype.renderCache = new Batman.RenderCache; Controller.prototype.defaultRenderYield = 'main'; Controller.prototype.autoScrollToHash = true; Controller.prototype.dispatch = function(action, params) { var redirectTo; if (params == null) { params = {}; } params.controller || (params.controller = this.get('routingKey')); params.action || (params.action = action); params.target || (params.target = this); this._resetActionFrames(); this.set('action', action); this.set('params', params); Batman.DOM.Yield.cycleAll(); this.executeAction(action, params); Batman.DOM.Yield.clearAllStale(); redirectTo = this._afterFilterRedirect; delete this._afterFilterRedirect; if (redirectTo) { return Batman.redirect(redirectTo); } }; Controller.prototype.executeAction = function(action, params) { var frame, oldRedirect, parentFrame, result, _ref, _ref1, _this = this; if (params == null) { params = this.get('params'); } Batman.developer.assert(this[action], "Error! Controller action " + (this.get('routingKey')) + "." + action + " couldn't be found!"); parentFrame = this._actionFrames[this._actionFrames.length - 1]; frame = new Batman.ControllerActionFrame({ parentFrame: parentFrame, action: action }, function() { var _ref; if (!_this._afterFilterRedirect) { _this._runFilters(action, params, 'afterFilters'); } _this._resetActionFrames(); return (_ref = Batman.navigator) != null ? _ref.redirect = oldRedirect : void 0; }); this._actionFrames.push(frame); frame.startOperation({ internal: true }); oldRedirect = (_ref = Batman.navigator) != null ? _ref.redirect : void 0; if ((_ref1 = Batman.navigator) != null) { _ref1.redirect = this.redirect; } this._runFilters(action, params, 'beforeFilters'); if (!this._afterFilterRedirect) { result = this[action](params); } if (!frame.operationOccurred) { this.render(); } frame.finishOperation(); return result; }; Controller.prototype.redirect = function(url) { var frame; frame = this._actionFrames[this._actionFrames.length - 1]; if (frame) { if (frame.operationOccurred) { Batman.developer.warn("Warning! Trying to redirect but an action has already been taken during " + (this.get('routingKey')) + "." + (frame.action || this.get('action'))); } frame.startAndFinishOperation(); if (this._afterFilterRedirect != null) { return Batman.developer.warn("Warning! Multiple actions trying to redirect!"); } else { return this._afterFilterRedirect = url; } } else { if (Batman.typeOf(url) === 'Object') { if (!url.controller) { url.controller = this; } } return Batman.redirect(url); } }; Controller.prototype.render = function(options) { var action, frame, view, _ref, _ref1, _this = this; if (options == null) { options = {}; } if (frame = (_ref = this._actionFrames) != null ? _ref[this._actionFrames.length - 1] : void 0) { frame.startOperation(); } if (options === false) { frame.finishOperation(); return; } action = (frame != null ? frame.action : void 0) || this.get('action'); if (options) { options.into || (options.into = this.defaultRenderYield); } if (!options.view) { options.viewClass || (options.viewClass = this._viewClassForAction(action)); options.context || (options.context = this.get('_renderContext')); options.source || (options.source = Batman.helpers.underscore(this.get('routingKey') + '/' + action)); view = this.renderCache.viewForOptions(options); } else { view = options.view; options.view = null; } if (view) { if ((_ref1 = Batman.currentApp) != null) { _ref1.prevent('ready'); } view.once('ready', function() { var _ref2; Batman.DOM.Yield.withName(options.into).replace(view.get('node')); if ((_ref2 = Batman.currentApp) != null) { _ref2.allowAndFire('ready'); } return frame != null ? frame.finishOperation() : void 0; }); } return view; }; Controller.prototype.scrollToHash = function(hash) { if (hash == null) { hash = this.get('params')['#']; } return Batman.DOM.scrollIntoView(hash); }; Controller.prototype._resetActionFrames = function() { return this._actionFrames = []; }; Controller.prototype._viewClassForAction = function(action) { var classPrefix, _ref; classPrefix = this.get('routingKey').replace('/', '_'); return ((_ref = Batman.currentApp) != null ? _ref[Batman.helpers.camelize("" + classPrefix + "_" + action + "_view")] : void 0) || Batman.View; }; Controller.prototype._runFilters = function(action, params, filters) { var block, options, _i, _len, _ref; if (filters = (_ref = this.constructor._batman) != null ? _ref.get(filters) : void 0) { for (_i = 0, _len = filters.length; _i < _len; _i++) { options = filters[_i]; if (options.only && __indexOf.call(options.only, action) < 0) { continue; } if (options.except && __indexOf.call(options.except, action) >= 0) { continue; } if (this._afterFilterRedirect) { return; } block = options.block; if (typeof block === 'function') { block.call(this, params); } else { if (typeof this[block] === "function") { this[block](params); } } } } }; return Controller; })(Batman.Object); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Batman.Set = (function(_super) { var k, _fn, _i, _j, _len, _len1, _ref, _ref1, _this = this; __extends(Set, _super); function Set() { Batman.SimpleSet.apply(this, arguments); } Batman.extend(Set.prototype, Batman.Enumerable); Set._applySetAccessors = function(klass) { var accessor, accessors, key, _results; accessors = { first: function() { return this.toArray()[0]; }, last: function() { return this.toArray()[this.length - 1]; }, isEmpty: function() { return this.isEmpty(); }, toArray: function() { return this.toArray(); }, length: function() { this.registerAsMutableSource(); return this.length; }, indexedBy: function() { var _this = this; return new Batman.TerminalAccessible(function(key) { return _this.indexedBy(key); }); }, indexedByUnique: function() { var _this = this; return new Batman.TerminalAccessible(function(key) { return _this.indexedByUnique(key); }); }, sortedBy: function() { var _this = this; return new Batman.TerminalAccessible(function(key) { return _this.sortedBy(key); }); }, sortedByDescending: function() { var _this = this; return new Batman.TerminalAccessible(function(key) { return _this.sortedBy(key, 'desc'); }); } }; _results = []; for (key in accessors) { accessor = accessors[key]; _results.push(klass.accessor(key, accessor)); } return _results; }; Set._applySetAccessors(Set); _ref = ['add', 'remove', 'clear', 'replace', 'indexedBy', 'indexedByUnique', 'sortedBy', 'equality', '_indexOfItem']; for (_i = 0, _len = _ref.length; _i < _len; _i++) { k = _ref[_i]; Set.prototype[k] = Batman.SimpleSet.prototype[k]; } _ref1 = ['find', 'merge', 'forEach', 'toArray', 'isEmpty', 'has']; _fn = function(k) { return Set.prototype[k] = function() { this.registerAsMutableSource(); return Batman.SimpleSet.prototype[k].apply(this, arguments); }; }; for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { k = _ref1[_j]; _fn(k); } Set.prototype.toJSON = Set.prototype.toArray; return Set; }).call(this, Batman.Object); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Batman.ErrorsSet = (function(_super) { __extends(ErrorsSet, _super); function ErrorsSet() { return ErrorsSet.__super__.constructor.apply(this, arguments); } ErrorsSet.accessor(function(key) { return this.indexedBy('attribute').get(key); }); ErrorsSet.prototype.add = function(key, error) { return ErrorsSet.__super__.add.call(this, new Batman.ValidationError(key, error)); }; return ErrorsSet; })(Batman.Set); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, __slice = [].slice; Batman.SetProxy = (function(_super) { var k, _fn, _i, _len, _ref, _this = this; __extends(SetProxy, _super); function SetProxy(base) { var _this = this; this.base = base; SetProxy.__super__.constructor.call(this); this.length = this.base.length; this.base.on('itemsWereAdded', function() { var items; items = 1 <= arguments.length ? __slice.call(arguments, 0) : []; _this.set('length', _this.base.length); return _this.fire.apply(_this, ['itemsWereAdded'].concat(__slice.call(items))); }); this.base.on('itemsWereRemoved', function() { var items; items = 1 <= arguments.length ? __slice.call(arguments, 0) : []; _this.set('length', _this.base.length); return _this.fire.apply(_this, ['itemsWereRemoved'].concat(__slice.call(items))); }); } Batman.extend(SetProxy.prototype, Batman.Enumerable); SetProxy.prototype.filter = function(f) { return this.reduce(function(accumulator, element) { if (f(element)) { accumulator.add(element); } return accumulator; }, new Batman.Set()); }; SetProxy.prototype.replace = function() { var length, result; length = this.property('length'); length.isolate(); result = this.base.replace.apply(this, arguments); length.expose(); return result; }; Batman.Set._applySetAccessors(SetProxy); _ref = ['add', 'remove', 'find', 'clear', 'has', 'merge', 'toArray', 'isEmpty', 'indexedBy', 'indexedByUnique', 'sortedBy']; _fn = function(k) { return SetProxy.prototype[k] = function() { var _ref1; return (_ref1 = this.base)[k].apply(_ref1, arguments); }; }; for (_i = 0, _len = _ref.length; _i < _len; _i++) { k = _ref[_i]; _fn(k); } SetProxy.accessor('length', { get: function() { this.registerAsMutableSource(); return this.length; }, set: function(_, v) { return this.length = v; } }); return SetProxy; }).call(this, Batman.Object); }).call(this); (function() { var __bind = function(fn, me) { return function() { return fn.apply(me, arguments); }; }, __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, __slice = [].slice; Batman.BinarySetOperation = (function(_super) { __extends(BinarySetOperation, _super); function BinarySetOperation(left, right) { this.left = left; this.right = right; this._setup = __bind(this._setup, this); BinarySetOperation.__super__.constructor.call(this); this._setup(this.left, this.right); this._setup(this.right, this.left); } BinarySetOperation.prototype._setup = function(set, opposite) { var _this = this; set.on('itemsWereAdded', function() { var items; items = 1 <= arguments.length ? __slice.call(arguments, 0) : []; return _this._itemsWereAddedToSource.apply(_this, [set, opposite].concat(__slice.call(items))); }); set.on('itemsWereRemoved', function() { var items; items = 1 <= arguments.length ? __slice.call(arguments, 0) : []; return _this._itemsWereRemovedFromSource.apply(_this, [set, opposite].concat(__slice.call(items))); }); return this._itemsWereAddedToSource.apply(this, [set, opposite].concat(__slice.call(set.toArray()))); }; BinarySetOperation.prototype.merge = function() { var merged, others, set, _i, _len; others = 1 <= arguments.length ? __slice.call(arguments, 0) : []; merged = new Batman.Set; others.unshift(this); for (_i = 0, _len = others.length; _i < _len; _i++) { set = others[_i]; set.forEach(function(v) { return merged.add(v); }); } return merged; }; BinarySetOperation.prototype.filter = Batman.SetProxy.prototype.filter; return BinarySetOperation; })(Batman.Set); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, __slice = [].slice; Batman.SetUnion = (function(_super) { __extends(SetUnion, _super); function SetUnion() { return SetUnion.__super__.constructor.apply(this, arguments); } SetUnion.prototype._itemsWereAddedToSource = function() { var items, opposite, source; source = arguments[0], opposite = arguments[1], items = 3 <= arguments.length ? __slice.call(arguments, 2) : []; return this.add.apply(this, items); }; SetUnion.prototype._itemsWereRemovedFromSource = function() { var item, items, itemsToRemove, opposite, source; source = arguments[0], opposite = arguments[1], items = 3 <= arguments.length ? __slice.call(arguments, 2) : []; itemsToRemove = (function() { var _i, _len, _results; _results = []; for (_i = 0, _len = items.length; _i < _len; _i++) { item = items[_i]; if (!opposite.has(item)) { _results.push(item); } } return _results; })(); return this.remove.apply(this, itemsToRemove); }; return SetUnion; })(Batman.BinarySetOperation); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, __slice = [].slice; Batman.SetIntersection = (function(_super) { __extends(SetIntersection, _super); function SetIntersection() { return SetIntersection.__super__.constructor.apply(this, arguments); } SetIntersection.prototype._itemsWereAddedToSource = function() { var item, items, itemsToAdd, opposite, source; source = arguments[0], opposite = arguments[1], items = 3 <= arguments.length ? __slice.call(arguments, 2) : []; itemsToAdd = (function() { var _i, _len, _results; _results = []; for (_i = 0, _len = items.length; _i < _len; _i++) { item = items[_i]; if (opposite.has(item)) { _results.push(item); } } return _results; })(); if (itemsToAdd.length > 0) { return this.add.apply(this, itemsToAdd); } }; SetIntersection.prototype._itemsWereRemovedFromSource = function() { var items, opposite, source; source = arguments[0], opposite = arguments[1], items = 3 <= arguments.length ? __slice.call(arguments, 2) : []; return this.remove.apply(this, items); }; return SetIntersection; })(Batman.BinarySetOperation); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, __slice = [].slice; Batman.SetComplement = (function(_super) { __extends(SetComplement, _super); function SetComplement() { return SetComplement.__super__.constructor.apply(this, arguments); } SetComplement.prototype._itemsWereAddedToSource = function() { var item, items, itemsToAdd, itemsToRemove, opposite, source; source = arguments[0], opposite = arguments[1], items = 3 <= arguments.length ? __slice.call(arguments, 2) : []; if (source === this.left) { itemsToAdd = (function() { var _i, _len, _results; _results = []; for (_i = 0, _len = items.length; _i < _len; _i++) { item = items[_i]; if (!opposite.has(item)) { _results.push(item); } } return _results; })(); if (itemsToAdd.length > 0) { return this.add.apply(this, itemsToAdd); } } else { itemsToRemove = (function() { var _i, _len, _results; _results = []; for (_i = 0, _len = items.length; _i < _len; _i++) { item = items[_i]; if (opposite.has(item)) { _results.push(item); } } return _results; })(); if (itemsToRemove.length > 0) { return this.remove.apply(this, itemsToRemove); } } }; SetComplement.prototype._itemsWereRemovedFromSource = function() { var item, items, itemsToAdd, opposite, source; source = arguments[0], opposite = arguments[1], items = 3 <= arguments.length ? __slice.call(arguments, 2) : []; if (source === this.left) { return this.remove.apply(this, items); } else { itemsToAdd = (function() { var _i, _len, _results; _results = []; for (_i = 0, _len = items.length; _i < _len; _i++) { item = items[_i]; if (opposite.has(item)) { _results.push(item); } } return _results; })(); if (itemsToAdd.length > 0) { return this.add.apply(this, itemsToAdd); } } }; SetComplement.prototype._addComplement = function(items, opposite) { var item, itemsToAdd; itemsToAdd = (function() { var _i, _len, _results; _results = []; for (_i = 0, _len = items.length; _i < _len; _i++) { item = items[_i]; if (opposite.has(item)) { _results.push(item); } } return _results; })(); if (itemsToAdd.length > 0) { return this.add.apply(this, itemsToAdd); } }; return SetComplement; })(Batman.BinarySetOperation); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, __slice = [].slice; Batman.StateMachine = (function(_super) { __extends(StateMachine, _super); StateMachine.InvalidTransitionError = function(message) { this.message = message != null ? message : ""; }; StateMachine.InvalidTransitionError.prototype = new Error; StateMachine.transitions = function(table) { var definePredicate, fromState, k, object, predicateKeys, toState, transitions, v, _fn, _ref, _this = this; for (k in table) { v = table[k]; if (!(v.from && v.to)) { continue; } object = {}; if (v.from.forEach) { v.from.forEach(function(fromKey) { return object[fromKey] = v.to; }); } else { object[v.from] = v.to; } table[k] = object; } this.prototype.transitionTable = Batman.extend({}, this.prototype.transitionTable, table); predicateKeys = []; definePredicate = function(state) { var key; key = "is" + (Batman.helpers.capitalize(state)); if (_this.prototype[key] != null) { return; } predicateKeys.push(key); return _this.prototype[key] = function() { return this.get('state') === state; }; }; _ref = this.prototype.transitionTable; _fn = function(k) { return _this.prototype[k] = function() { return this.startTransition(k); }; }; for (k in _ref) { transitions = _ref[k]; if (!(!this.prototype[k])) { continue; } _fn(k); for (fromState in transitions) { toState = transitions[fromState]; definePredicate(fromState); definePredicate(toState); } } if (predicateKeys.length) { this.accessor.apply(this, __slice.call(predicateKeys).concat([function(key) { return this[key](); }])); } return this; }; function StateMachine(startState) { this.nextEvents = []; this.set('_state', startState); } StateMachine.accessor('state', function() { return this.get('_state'); }); StateMachine.prototype.isTransitioning = false; StateMachine.prototype.transitionTable = {}; StateMachine.prototype.onTransition = function(from, into, callback) { return this.on("" + from + "->" + into, callback); }; StateMachine.prototype.onEnter = function(into, callback) { return this.on("enter " + into, callback); }; StateMachine.prototype.onExit = function(from, callback) { return this.on("exit " + from, callback); }; StateMachine.prototype.startTransition = Batman.Property.wrapTrackingPrevention(function(event) { var nextState, previousState; if (this.isTransitioning) { this.nextEvents.push(event); return; } previousState = this.get('state'); nextState = this.nextStateForEvent(event); if (!nextState) { return false; } this.isTransitioning = true; this.fire("exit " + previousState); this.set('_state', nextState); this.fire("" + previousState + "->" + nextState); this.fire("enter " + nextState); this.fire(event); this.isTransitioning = false; if (this.nextEvents.length > 0) { this.startTransition(this.nextEvents.shift()); } return true; }); StateMachine.prototype.canStartTransition = function(event, fromState) { if (fromState == null) { fromState = this.get('state'); } return !!this.nextStateForEvent(event, fromState); }; StateMachine.prototype.nextStateForEvent = function(event, fromState) { var _ref; if (fromState == null) { fromState = this.get('state'); } return (_ref = this.transitionTable[event]) != null ? _ref[fromState] : void 0; }; return StateMachine; })(Batman.Object); Batman.DelegatingStateMachine = (function(_super) { __extends(DelegatingStateMachine, _super); function DelegatingStateMachine(startState, base) { this.base = base; DelegatingStateMachine.__super__.constructor.call(this, startState); } DelegatingStateMachine.prototype.fire = function() { var result, _ref; result = DelegatingStateMachine.__super__.fire.apply(this, arguments); (_ref = this.base).fire.apply(_ref, arguments); return result; }; return DelegatingStateMachine; })(Batman.StateMachine); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, __slice = [].slice; Batman.Model = (function(_super) { var functionName, _i, _j, _len, _len1, _ref, _ref1; __extends(Model, _super); Model.storageKey = null; Model.primaryKey = 'id'; Model.persist = function() { var mechanism, options; mechanism = arguments[0], options = 2 <= arguments.length ? __slice.call(arguments, 1) : []; Batman.initializeObject(this.prototype); mechanism = mechanism.isStorageAdapter ? mechanism : new mechanism(this); if (options.length > 0) { Batman.mixin.apply(Batman, [mechanism].concat(__slice.call(options))); } this.prototype._batman.storage = mechanism; return mechanism; }; Model.storageAdapter = function() { Batman.initializeObject(this.prototype); return this.prototype._batman.storage; }; Model.encode = function() { var encoder, encoderForKey, encoderOrLastKey, key, keys, _base, _i, _j, _len; keys = 2 <= arguments.length ? __slice.call(arguments, 0, _i = arguments.length - 1) : (_i = 0, []), encoderOrLastKey = arguments[_i++]; Batman.initializeObject(this.prototype); (_base = this.prototype._batman).encoders || (_base.encoders = new Batman.SimpleHash); encoder = {}; switch (Batman.typeOf(encoderOrLastKey)) { case 'String': keys.push(encoderOrLastKey); break; case 'Function': encoder.encode = encoderOrLastKey; break; default: encoder = encoderOrLastKey; } for (_j = 0, _len = keys.length; _j < _len; _j++) { key = keys[_j]; encoderForKey = Batman.extend({ as: key }, this.defaultEncoder, encoder); this.prototype._batman.encoders.set(key, encoderForKey); } }; Model.defaultEncoder = { encode: function(x) { return x; }, decode: function(x) { return x; } }; Model.observeAndFire('primaryKey', function(newPrimaryKey, oldPrimaryKey) { this.encode(oldPrimaryKey, { encode: false, decode: false }); return this.encode(newPrimaryKey, { encode: false, decode: this.defaultEncoder.decode }); }); Model.validate = function() { var keys, matches, optionsOrFunction, validatorClass, validators, _base, _i, _j, _len, _ref, _results; keys = 2 <= arguments.length ? __slice.call(arguments, 0, _i = arguments.length - 1) : (_i = 0, []), optionsOrFunction = arguments[_i++]; Batman.initializeObject(this.prototype); validators = (_base = this.prototype._batman).validators || (_base.validators = []); if (typeof optionsOrFunction === 'function') { return validators.push({ keys: keys, callback: optionsOrFunction }); } else { _ref = Batman.Validators; _results = []; for (_j = 0, _len = _ref.length; _j < _len; _j++) { validatorClass = _ref[_j]; if ((matches = validatorClass.matches(optionsOrFunction))) { _results.push(validators.push({ keys: keys, validator: new validatorClass(matches) })); } else { _results.push(void 0); } } return _results; } }; Model.classAccessor('resourceName', { get: function() { if (this.resourceName != null) { return this.resourceName; } else { if (Batman.config.minificationErrors) { Batman.developer.error("Please define " + (Batman.functionName(this)) + ".resourceName in order for your model to be minification safe."); } return Batman.helpers.underscore(Batman.functionName(this)); } } }); Model.classAccessor('all', { get: function() { this._batman.check(this); if (this.prototype.hasStorage() && !this._batman.allLoadTriggered) { this.load(); this._batman.allLoadTriggered = true; } return this.get('loaded'); }, set: function(k, v) { return this.set('loaded', v); } }); Model.classAccessor('loaded', { get: function() { return this._loaded || (this._loaded = new Batman.Set); }, set: function(k, v) { return this._loaded = v; } }); Model.classAccessor('first', function() { return this.get('all').toArray()[0]; }); Model.classAccessor('last', function() { var x; x = this.get('all').toArray(); return x[x.length - 1]; }); Model.clear = function() { var result, _ref; Batman.initializeObject(this); result = this.get('loaded').clear(); if ((_ref = this._batman.get('associations')) != null) { _ref.reset(); } this._resetPromises(); return result; }; Model.find = function(id, callback) { return this.findWithOptions(id, void 0, callback); }; Model.findWithOptions = function(id, options, callback) { var record; if (options == null) { options = {}; } Batman.developer.assert(callback, "Must call find with a callback!"); record = new this(); record._withoutDirtyTracking(function() { return this.set('id', id); }); record.loadWithOptions(options, callback); return record; }; Model.load = function(options, callback) { var _ref; if ((_ref = typeof options) === 'function' || _ref === 'undefined') { callback = options; options = {}; } else { options = { data: options }; } return this.loadWithOptions(options, callback); }; Model.loadWithOptions = function(options, callback) { var _this = this; this.fire('loading', options); return this._doStorageOperation('readAll', options, function(err, records, env) { var mappedRecords; if (err != null) { _this.fire('error', err); return typeof callback === "function" ? callback(err, []) : void 0; } else { mappedRecords = _this._mapIdentities(records); _this.fire('loaded', mappedRecords, env); return typeof callback === "function" ? callback(err, mappedRecords, env) : void 0; } }); }; Model.create = function(attrs, callback) { var obj, _ref; if (!callback) { _ref = [{}, attrs], attrs = _ref[0], callback = _ref[1]; } obj = new this(attrs); obj.save(callback); return obj; }; Model.findOrCreate = function(attrs, callback) { var foundRecord, record; record = new this(attrs); if (record.isNew()) { record.save(callback); } else { foundRecord = this._mapIdentity(record); callback(void 0, foundRecord); } return record; }; Model.createFromJSON = function(json) { var record; record = new this; record._withoutDirtyTracking(function() { return this.fromJSON(json); }); return this._mapIdentity(record); }; Model._mapIdentity = function(record) { return this._mapIdentities([record])[0]; }; Model._mapIdentities = function(records) { var existing, id, index, newRecords, record, _i, _len, _ref, _ref1; newRecords = []; for (index = _i = 0, _len = records.length; _i < _len; index = ++_i) { record = records[index]; if (!((id = record.get('id')) != null)) { continue; } else if (existing = (_ref = this.get('loaded.indexedBy.id').get(id)) != null ? _ref.toArray()[0] : void 0) { existing._withoutDirtyTracking(function() { var _ref1; return this.updateAttributes(((_ref1 = record.get('attributes')) != null ? _ref1.toObject() : void 0) || {}); }); records[index] = existing; } else { newRecords.push(record); } } if (newRecords.length) { (_ref1 = this.get('loaded')).add.apply(_ref1, newRecords); } return records; }; Model._doStorageOperation = function(operation, options, callback) { var adapter; Batman.developer.assert(this.prototype.hasStorage(), "Can't " + operation + " model " + (Batman.functionName(this.constructor)) + " without any storage adapters!"); adapter = this.prototype._batman.get('storage'); return adapter.perform(operation, this, options, callback); }; _ref = ['find', 'load', 'create']; for (_i = 0, _len = _ref.length; _i < _len; _i++) { functionName = _ref[_i]; Model[functionName] = Batman.Property.wrapTrackingPrevention(Model[functionName]); } Model.InstanceLifecycleStateMachine = (function(_super1) { __extends(InstanceLifecycleStateMachine, _super1); function InstanceLifecycleStateMachine() { return InstanceLifecycleStateMachine.__super__.constructor.apply(this, arguments); } InstanceLifecycleStateMachine.transitions({ load: { from: ['dirty', 'clean'], to: 'loading' }, create: { from: ['dirty', 'clean'], to: 'creating' }, save: { from: ['dirty', 'clean'], to: 'saving' }, destroy: { from: ['dirty', 'clean'], to: 'destroying' }, failedValidation: { from: ['saving', 'creating'], to: 'dirty' }, loaded: { loading: 'clean' }, created: { creating: 'clean' }, saved: { saving: 'clean' }, destroyed: { destroying: 'destroyed' }, set: { from: ['dirty', 'clean'], to: 'dirty' }, error: { from: ['saving', 'creating', 'loading', 'destroying'], to: 'error' } }); return InstanceLifecycleStateMachine; })(Batman.DelegatingStateMachine); function Model(idOrAttributes) { if (idOrAttributes == null) { idOrAttributes = {}; } Batman.developer.assert(this instanceof Batman.Object, "constructors must be called with new"); if (Batman.typeOf(idOrAttributes) === 'Object') { Model.__super__.constructor.call(this, idOrAttributes); } else { Model.__super__.constructor.call(this); this.set('id', idOrAttributes); } } Model.accessor('lifecycle', function() { return this.lifecycle || (this.lifecycle = new Batman.Model.InstanceLifecycleStateMachine('clean', this)); }); Model.accessor('attributes', function() { return this.attributes || (this.attributes = new Batman.Hash); }); Model.accessor('dirtyKeys', function() { return this.dirtyKeys || (this.dirtyKeys = new Batman.Hash); }); Model.accessor('_dirtiedKeys', function() { return this._dirtiedKeys || (this._dirtiedKeys = new Batman.SimpleSet); }); Model.accessor('errors', function() { return this.errors || (this.errors = new Batman.ErrorsSet); }); Model.accessor('isNew', function() { return this.isNew(); }); Model.accessor('isDirty', function() { return this.isDirty(); }); Model.accessor(Model.defaultAccessor = { get: function(k) { return Batman.getPath(this, ['attributes', k]); }, set: function(k, v) { if (this._willSet(k)) { return this.get('attributes').set(k, v); } else { return this.get(k); } }, unset: function(k) { return this.get('attributes').unset(k); } }); Model.wrapAccessor('id', function(core) { return { get: function() { var primaryKey; primaryKey = this.constructor.primaryKey; if (primaryKey === 'id') { return core.get.apply(this, arguments); } else { return this.get(primaryKey); } }, set: function(key, value) { var parsedValue, primaryKey; if ((typeof value === "string") && (value.match(/[^0-9]/) === null) && (("" + (parsedValue = parseInt(value, 10))) === value)) { value = parsedValue; } primaryKey = this.constructor.primaryKey; if (primaryKey === 'id') { this._willSet(key); return core.set.apply(this, arguments); } else { return this.set(primaryKey, value); } } }; }); Model.prototype.isNew = function() { return typeof this.get('id') === 'undefined'; }; Model.prototype.isDirty = function() { return this.get('lifecycle.state') === 'dirty'; }; Model.prototype.updateAttributes = function(attrs) { this.mixin(attrs); return this; }; Model.prototype.toString = function() { return "" + (this.constructor.get('resourceName')) + ": " + (this.get('id')); }; Model.prototype.toParam = function() { return this.get('id'); }; Model.prototype.toJSON = function() { var encoders, obj, _this = this; obj = {}; encoders = this._batman.get('encoders'); if (!(!encoders || encoders.isEmpty())) { encoders.forEach(function(key, encoder) { var encodedVal, val; if (encoder.encode) { val = _this.get(key); if (typeof val !== 'undefined') { encodedVal = encoder.encode(val, key, obj, _this); if (typeof encodedVal !== 'undefined') { return obj[encoder.as] = encodedVal; } } } }); } return obj; }; Model.prototype.fromJSON = function(data) { var encoders, key, obj, value, _this = this; obj = {}; encoders = this._batman.get('encoders'); if (!encoders || encoders.isEmpty() || !encoders.some(function(key, encoder) { return encoder.decode != null; })) { for (key in data) { value = data[key]; obj[key] = value; } } else { encoders.forEach(function(key, encoder) { if (encoder.decode && typeof data[encoder.as] !== 'undefined') { return obj[key] = encoder.decode(data[encoder.as], encoder.as, data, obj, _this); } }); } if (this.constructor.primaryKey !== 'id') { obj.id = data[this.constructor.primaryKey]; } Batman.developer["do"](function() { if ((!encoders) || encoders.length <= 1) { return Batman.developer.warn("Warning: Model " + (Batman.functionName(_this.constructor)) + " has suspiciously few decoders!"); } }); return this.mixin(obj); }; Model.prototype.hasStorage = function() { return this._batman.get('storage') != null; }; Model.prototype.load = function(options, callback) { var _ref1; if (!callback) { _ref1 = [{}, options], options = _ref1[0], callback = _ref1[1]; } else { options = { data: options }; } return this.loadWithOptions(options, callback); }; Model.prototype.loadWithOptions = function(options, callback) { var callbackQueue, hasOptions, _ref1, _this = this; hasOptions = Object.keys(options).length !== 0; if ((_ref1 = this.get('lifecycle.state')) === 'destroying' || _ref1 === 'destroyed') { if (typeof callback === "function") { callback(new Error("Can't load a destroyed record!")); } return; } if (this.get('lifecycle').load()) { callbackQueue = []; if (callback != null) { callbackQueue.push(callback); } if (!hasOptions) { this._currentLoad = callbackQueue; } return this._doStorageOperation('read', options, function(err, record, env) { var _j, _len1; if (!err) { _this.get('lifecycle').loaded(); record = _this.constructor._mapIdentity(record); } else { _this.get('lifecycle').error(); } if (!hasOptions) { _this._currentLoad = null; } for (_j = 0, _len1 = callbackQueue.length; _j < _len1; _j++) { callback = callbackQueue[_j]; callback(err, record, env); } }); } else { if (this.get('lifecycle.state') === 'loading' && !hasOptions) { if (callback != null) { return this._currentLoad.push(callback); } } else { return typeof callback === "function" ? callback(new Batman.StateMachine.InvalidTransitionError("Can't load while in state " + (this.get('lifecycle.state')))) : void 0; } } }; Model.prototype.save = function(options, callback) { var endState, isNew, startState, storageOperation, _ref1, _ref2, _this = this; if (!callback) { _ref1 = [{}, options], options = _ref1[0], callback = _ref1[1]; } isNew = this.isNew(); _ref2 = isNew ? ['create', 'create', 'created'] : ['save', 'update', 'saved'], startState = _ref2[0], storageOperation = _ref2[1], endState = _ref2[2]; if (this.get('lifecycle').startTransition(startState)) { return this.validate(function(error, errors) { var associations; if (error || errors.length) { _this.get('lifecycle').failedValidation(); return typeof callback === "function" ? callback(error || errors, _this) : void 0; } associations = _this.constructor._batman.get('associations'); _this._withoutDirtyTracking(function() { var _ref3, _this = this; return associations != null ? (_ref3 = associations.getByType('belongsTo')) != null ? _ref3.forEach(function(association, label) { return association.apply(_this); }) : void 0 : void 0; }); return _this._doStorageOperation(storageOperation, { data: options }, function(err, record, env) { if (!err) { _this.get('dirtyKeys').clear(); _this.get('_dirtiedKeys').clear(); if (associations) { record._withoutDirtyTracking(function() { var _ref3, _ref4; if ((_ref3 = associations.getByType('hasOne')) != null) { _ref3.forEach(function(association, label) { return association.apply(err, record); }); } return (_ref4 = associations.getByType('hasMany')) != null ? _ref4.forEach(function(association, label) { return association.apply(err, record); }) : void 0; }); } record = _this.constructor._mapIdentity(record); _this.get('lifecycle').startTransition(endState); } else { if (err instanceof Batman.ErrorsSet) { _this.get('lifecycle').failedValidation(); } else { _this.get('lifecycle').error(); } } return typeof callback === "function" ? callback(err, record || _this, env) : void 0; }); }); } else { return typeof callback === "function" ? callback(new Batman.StateMachine.InvalidTransitionError("Can't save while in state " + (this.get('lifecycle.state')))) : void 0; } }; Model.prototype.destroy = function(options, callback) { var _ref1, _this = this; if (!callback) { _ref1 = [{}, options], options = _ref1[0], callback = _ref1[1]; } if (this.get('lifecycle').destroy()) { return this._doStorageOperation('destroy', { data: options }, function(err, record, env) { if (!err) { _this.constructor.get('loaded').remove(_this); _this.get('lifecycle').destroyed(); } else { _this.get('lifecycle').error(); } return typeof callback === "function" ? callback(err, record, env) : void 0; }); } else { return typeof callback === "function" ? callback(new Batman.StateMachine.InvalidTransitionError("Can't destroy while in state " + (this.get('lifecycle.state')))) : void 0; } }; Model.prototype.validate = function(callback) { var args, count, errors, finishedValidation, key, validator, validators, _j, _k, _len1, _len2, _ref1; errors = this.get('errors'); errors.clear(); validators = this._batman.get('validators') || []; if (!validators || validators.length === 0) { if (typeof callback === "function") { callback(void 0, errors); } return true; } count = validators.reduce((function(acc, validator) { return acc + validator.keys.length; }), 0); finishedValidation = function() { if (--count === 0) { return typeof callback === "function" ? callback(void 0, errors) : void 0; } }; for (_j = 0, _len1 = validators.length; _j < _len1; _j++) { validator = validators[_j]; _ref1 = validator.keys; for (_k = 0, _len2 = _ref1.length; _k < _len2; _k++) { key = _ref1[_k]; args = [errors, this, key, finishedValidation]; try { if (validator.validator) { validator.validator.validateEach.apply(validator.validator, args); } else { validator.callback.apply(validator, args); } } catch (e) { if (typeof callback === "function") { callback(e, errors); } } } } }; Model.prototype.associationProxy = function(association) { var proxies, _base, _name; Batman.initializeObject(this); proxies = (_base = this._batman).associationProxies || (_base.associationProxies = {}); proxies[_name = association.label] || (proxies[_name] = new association.proxyClass(association, this)); return proxies[association.label]; }; Model.prototype._willSet = function(key) { if (this._pauseDirtyTracking) { return true; } if (this.get('lifecycle').startTransition('set')) { if (!this.get('_dirtiedKeys').has(key)) { this.set("dirtyKeys." + key, this.get(key)); this.get('_dirtiedKeys').add(key); } return true; } else { return false; } }; Model.prototype._doStorageOperation = function(operation, options, callback) { var adapter, _this = this; Batman.developer.assert(this.hasStorage(), "Can't " + operation + " model " + (Batman.functionName(this.constructor)) + " without any storage adapters!"); adapter = this._batman.get('storage'); return adapter.perform(operation, this, options, function() { return callback.apply(null, arguments); }); }; Model.prototype._withoutDirtyTracking = function(block) { var result; this._pauseDirtyTracking = true; result = block.call(this); this._pauseDirtyTracking = false; return result; }; _ref1 = ['load', 'save', 'validate', 'destroy']; for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { functionName = _ref1[_j]; Model.prototype[functionName] = Batman.Property.wrapTrackingPrevention(Model.prototype[functionName]); } return Model; }).call(this, Batman.Object); }).call(this); (function() { var k, _fn, _i, _len, _ref, _this = this; _ref = Batman.AssociationCurator.availableAssociations; _fn = function(k) { return Batman.Model[k] = function(label, scope) { var collection, _base; Batman.initializeObject(this); collection = (_base = this._batman).associations || (_base.associations = new Batman.AssociationCurator(this)); return collection.add(new Batman["" + (Batman.helpers.capitalize(k)) + "Association"](this, label, scope)); }; }; for (_i = 0, _len = _ref.length; _i < _len; _i++) { k = _ref[_i]; _fn(k); } }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Batman.Proxy = (function(_super) { __extends(Proxy, _super); Proxy.prototype.isProxy = true; function Proxy(target) { Proxy.__super__.constructor.call(this); if (target != null) { this.set('target', target); } } Proxy.accessor('target', Batman.Property.defaultAccessor); Proxy.accessor({ get: function(key) { var _ref; return (_ref = this.get('target')) != null ? _ref.get(key) : void 0; }, set: function(key, value) { var _ref; return (_ref = this.get('target')) != null ? _ref.set(key, value) : void 0; }, unset: function(key) { var _ref; return (_ref = this.get('target')) != null ? _ref.unset(key) : void 0; } }); return Proxy; })(Batman.Object); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Batman.AssociationProxy = (function(_super) { __extends(AssociationProxy, _super); AssociationProxy.prototype.loaded = false; function AssociationProxy(association, model) { this.association = association; this.model = model; AssociationProxy.__super__.constructor.call(this); } AssociationProxy.prototype.toJSON = function() { var target; target = this.get('target'); if (target != null) { return this.get('target').toJSON(); } }; AssociationProxy.prototype.load = function(callback) { var _this = this; this.fetch(function(err, proxiedRecord) { if (!err) { _this._setTarget(proxiedRecord); } return typeof callback === "function" ? callback(err, proxiedRecord) : void 0; }); return this.get('target'); }; AssociationProxy.prototype.loadFromLocal = function() { var target; if (!this._canLoad()) { return; } if (target = this.fetchFromLocal()) { this._setTarget(target); } return target; }; AssociationProxy.prototype.fetch = function(callback) { var record; if (!this._canLoad()) { return callback(void 0, void 0); } record = this.fetchFromLocal(); if (record) { return callback(void 0, record); } else { return this.fetchFromRemote(callback); } }; AssociationProxy.accessor('loaded', Batman.Property.defaultAccessor); AssociationProxy.accessor('target', { get: function() { return this.fetchFromLocal(); }, set: function(_, v) { return v; } }); AssociationProxy.prototype._canLoad = function() { return (this.get('foreignValue') || this.get('primaryValue')) != null; }; AssociationProxy.prototype._setTarget = function(target) { this.set('target', target); this.set('loaded', true); return this.fire('loaded', target); }; return AssociationProxy; })(Batman.Proxy); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Batman.HasOneProxy = (function(_super) { __extends(HasOneProxy, _super); function HasOneProxy() { return HasOneProxy.__super__.constructor.apply(this, arguments); } HasOneProxy.accessor('primaryValue', function() { return this.model.get(this.association.primaryKey); }); HasOneProxy.prototype.fetchFromLocal = function() { return this.association.setIndex().get(this.get('primaryValue')); }; HasOneProxy.prototype.fetchFromRemote = function(callback) { var loadOptions, _this = this; loadOptions = { data: {} }; loadOptions.data[this.association.foreignKey] = this.get('primaryValue'); if (this.association.options.url) { loadOptions.collectionUrl = this.association.options.url; loadOptions.urlContext = this.model; } return this.association.getRelatedModel().loadWithOptions(loadOptions, function(error, loadedRecords) { if (error) { throw error; } if (!loadedRecords || loadedRecords.length <= 0) { return callback(new Error("Couldn't find related record!"), void 0); } else { return callback(void 0, loadedRecords[0]); } }); }; return HasOneProxy; })(Batman.AssociationProxy); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Batman.BelongsToProxy = (function(_super) { __extends(BelongsToProxy, _super); function BelongsToProxy() { return BelongsToProxy.__super__.constructor.apply(this, arguments); } BelongsToProxy.accessor('foreignValue', function() { return this.model.get(this.association.foreignKey); }); BelongsToProxy.prototype.fetchFromLocal = function() { return this.association.setIndex().get(this.get('foreignValue')); }; BelongsToProxy.prototype.fetchFromRemote = function(callback) { var loadOptions, _this = this; loadOptions = {}; if (this.association.options.url) { loadOptions.recordUrl = this.association.options.url; } return this.association.getRelatedModel().findWithOptions(this.get('foreignValue'), loadOptions, function(error, loadedRecord) { if (error) { throw error; } return callback(void 0, loadedRecord); }); }; return BelongsToProxy; })(Batman.AssociationProxy); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Batman.PolymorphicBelongsToProxy = (function(_super) { __extends(PolymorphicBelongsToProxy, _super); function PolymorphicBelongsToProxy() { return PolymorphicBelongsToProxy.__super__.constructor.apply(this, arguments); } PolymorphicBelongsToProxy.accessor('foreignTypeValue', function() { return this.model.get(this.association.foreignTypeKey); }); PolymorphicBelongsToProxy.prototype.fetchFromLocal = function() { return this.association.setIndexForType(this.get('foreignTypeValue')).get(this.get('foreignValue')); }; PolymorphicBelongsToProxy.prototype.fetchFromRemote = function(callback) { var loadOptions, _this = this; loadOptions = {}; if (this.association.options.url) { loadOptions.recordUrl = this.association.options.url; } return this.association.getRelatedModelForType(this.get('foreignTypeValue')).findWithOptions(this.get('foreignValue'), loadOptions, function(error, loadedRecord) { if (error) { throw error; } return callback(void 0, loadedRecord); }); }; return PolymorphicBelongsToProxy; })(Batman.BelongsToProxy); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Batman.Accessible = (function(_super) { __extends(Accessible, _super); function Accessible() { this.accessor.apply(this, arguments); } return Accessible; })(Batman.Object); Batman.TerminalAccessible = (function(_super) { __extends(TerminalAccessible, _super); function TerminalAccessible() { return TerminalAccessible.__super__.constructor.apply(this, arguments); } TerminalAccessible.prototype.propertyClass = Batman.Property; return TerminalAccessible; })(Batman.Accessible); }).call(this); (function() { Batman.mixins = new Batman.Object; }).call(this); (function() { Batman.URI = (function() { /* # URI parsing */ var attributes, childKeyMatchers, decodeQueryComponent, encodeComponent, encodeQueryComponent, keyVal, nameParser, normalizeParams, plus, queryFromParams, r20, strictParser; strictParser = /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/; attributes = ["source", "protocol", "authority", "userInfo", "user", "password", "hostname", "port", "relative", "path", "directory", "file", "query", "hash"]; function URI(str) { var i, matches; matches = strictParser.exec(str); i = 14; while (i--) { this[attributes[i]] = matches[i] || ''; } this.queryParams = this.constructor.paramsFromQuery(this.query); delete this.authority; delete this.userInfo; delete this.relative; delete this.directory; delete this.file; delete this.query; } URI.prototype.queryString = function() { return this.constructor.queryFromParams(this.queryParams); }; URI.prototype.toString = function() { return [this.protocol ? "" + this.protocol + ":" : void 0, this.authority() ? "//" : void 0, this.authority(), this.relative()].join(""); }; URI.prototype.userInfo = function() { return [this.user, this.password ? ":" + this.password : void 0].join(""); }; URI.prototype.authority = function() { return [this.userInfo(), this.user || this.password ? "@" : void 0, this.hostname, this.port ? ":" + this.port : void 0].join(""); }; URI.prototype.relative = function() { var query; query = this.queryString(); return [this.path, query ? "?" + query : void 0, this.hash ? "#" + this.hash : void 0].join(""); }; URI.prototype.directory = function() { var splitPath; splitPath = this.path.split('/'); if (splitPath.length > 1) { return splitPath.slice(0, splitPath.length - 1).join('/') + "/"; } else { return ""; } }; URI.prototype.file = function() { var splitPath; splitPath = this.path.split("/"); return splitPath[splitPath.length - 1]; }; /* # query parsing */ URI.paramsFromQuery = function(query) { var matches, params, segment, _i, _len, _ref; params = {}; _ref = query.split('&'); for (_i = 0, _len = _ref.length; _i < _len; _i++) { segment = _ref[_i]; if (matches = segment.match(keyVal)) { normalizeParams(params, decodeQueryComponent(matches[1]), decodeQueryComponent(matches[2])); } else { normalizeParams(params, decodeQueryComponent(segment), null); } } return params; }; URI.decodeQueryComponent = decodeQueryComponent = function(str) { return decodeURIComponent(str.replace(plus, '%20')); }; nameParser = /^[\[\]]*([^\[\]]+)\]*(.*)/; childKeyMatchers = [/^\[\]\[([^\[\]]+)\]$/, /^\[\](.+)$/]; plus = /\+/g; r20 = /%20/g; keyVal = /^([^=]*)=(.*)/; normalizeParams = function(params, name, v) { var after, childKey, k, last, matches, _ref, _ref1, _ref2; if (matches = name.match(nameParser)) { k = matches[1]; after = matches[2]; } else { return; } if (after === '') { params[k] = v; } else if (after === '[]') { if ((_ref = params[k]) == null) { params[k] = []; } if (Batman.typeOf(params[k]) !== 'Array') { throw new Error("expected Array (got " + (Batman.typeOf(params[k])) + ") for param \"" + k + "\""); } params[k].push(v); } else if (matches = after.match(childKeyMatchers[0]) || after.match(childKeyMatchers[1])) { childKey = matches[1]; if ((_ref1 = params[k]) == null) { params[k] = []; } if (Batman.typeOf(params[k]) !== 'Array') { throw new Error("expected Array (got " + (Batman.typeOf(params[k])) + ") for param \"" + k + "\""); } last = params[k][params[k].length - 1]; if (Batman.typeOf(last) === 'Object' && !(childKey in last)) { normalizeParams(last, childKey, v); } else { params[k].push(normalizeParams({}, childKey, v)); } } else { if ((_ref2 = params[k]) == null) { params[k] = {}; } if (Batman.typeOf(params[k]) !== 'Object') { throw new Error("expected Object (got " + (Batman.typeOf(params[k])) + ") for param \"" + k + "\""); } params[k] = normalizeParams(params[k], after, v); } return params; }; /* # query building */ URI.queryFromParams = queryFromParams = function(value, prefix) { var arrayResults, k, v, valueType; if (value == null) { return prefix; } valueType = Batman.typeOf(value); if (!((prefix != null) || valueType === 'Object')) { throw new Error("value must be an Object"); } switch (valueType) { case 'Array': return ((function() { var _i, _len; arrayResults = []; if (value.length === 0) { arrayResults.push(queryFromParams(null, "" + prefix + "[]")); } else { for (_i = 0, _len = value.length; _i < _len; _i++) { v = value[_i]; arrayResults.push(queryFromParams(v, "" + prefix + "[]")); } } return arrayResults; })()).join("&"); case 'Object': return ((function() { var _results; _results = []; for (k in value) { v = value[k]; _results.push(queryFromParams(v, prefix ? "" + prefix + "[" + (encodeQueryComponent(k)) + "]" : encodeQueryComponent(k))); } return _results; })()).join("&"); default: if (prefix != null) { return "" + prefix + "=" + (encodeQueryComponent(value)); } else { return encodeQueryComponent(value); } } }; URI.encodeComponent = encodeComponent = function(str) { if (str != null) { return encodeURIComponent(str); } else { return ''; } }; URI.encodeQueryComponent = encodeQueryComponent = function(str) { return encodeComponent(str).replace(r20, '+'); }; return URI; })(); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Batman.Request = (function(_super) { var dataHasFileUploads; __extends(Request, _super); Request.objectToFormData = function(data) { var formData, key, pairForList, val, _i, _len, _ref, _ref1; pairForList = function(key, object, first) { var k, list, v; if (first == null) { first = false; } if (object instanceof Batman.container.File) { return [[key, object]]; } return list = (function() { switch (Batman.typeOf(object)) { case 'Object': list = (function() { var _results; _results = []; for (k in object) { v = object[k]; _results.push(pairForList((first ? k : "" + key + "[" + k + "]"), v)); } return _results; })(); return list.reduce(function(acc, list) { return acc.concat(list); }, []); case 'Array': return object.reduce(function(acc, element) { return acc.concat(pairForList("" + key + "[]", element)); }, []); default: return [[key, object != null ? object : ""]]; } })(); }; formData = new Batman.container.FormData(); _ref = pairForList("", data, true); for (_i = 0, _len = _ref.length; _i < _len; _i++) { _ref1 = _ref[_i], key = _ref1[0], val = _ref1[1]; formData.append(key, val); } return formData; }; Request.dataHasFileUploads = dataHasFileUploads = function(data) { var k, type, v, _i, _len; if ((typeof File !== "undefined" && File !== null) && data instanceof File) { return true; } type = Batman.typeOf(data); switch (type) { case 'Object': for (k in data) { v = data[k]; if (dataHasFileUploads(v)) { return true; } } break; case 'Array': for (_i = 0, _len = data.length; _i < _len; _i++) { v = data[_i]; if (dataHasFileUploads(v)) { return true; } } } return false; }; Request.wrapAccessor('method', function(core) { return { set: function(k, val) { return core.set.call(this, k, val != null ? typeof val.toUpperCase === "function" ? val.toUpperCase() : void 0 : void 0); } }; }); Request.prototype.method = 'GET'; Request.prototype.hasFileUploads = function() { return dataHasFileUploads(this.data); }; Request.prototype.contentType = 'application/x-www-form-urlencoded'; Request.prototype.autosend = true; function Request(options) { var handler, handlers, k, _ref; handlers = {}; for (k in options) { handler = options[k]; if (!(k === 'success' || k === 'error' || k === 'loading' || k === 'loaded')) { continue; } handlers[k] = handler; delete options[k]; } Request.__super__.constructor.call(this, options); for (k in handlers) { handler = handlers[k]; this.on(k, handler); } if (((_ref = this.get('url')) != null ? _ref.length : void 0) > 0) { if (this.autosend) { this.send(); } } else { this.observe('url', function(url) { if (url != null) { return this.send(); } }); } } Request.prototype.send = function() { return Batman.developer.error("Please source a dependency file for a request implementation"); }; return Request; })(Batman.Object); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, __slice = [].slice; Batman.SetObserver = (function(_super) { __extends(SetObserver, _super); function SetObserver(base) { var _this = this; this.base = base; this._itemObservers = new Batman.SimpleHash; this._setObservers = new Batman.SimpleHash; this._setObservers.set("itemsWereAdded", function() { return _this.fire.apply(_this, ['itemsWereAdded'].concat(__slice.call(arguments))); }); this._setObservers.set("itemsWereRemoved", function() { return _this.fire.apply(_this, ['itemsWereRemoved'].concat(__slice.call(arguments))); }); this.on('itemsWereAdded', this.startObservingItems.bind(this)); this.on('itemsWereRemoved', this.stopObservingItems.bind(this)); } SetObserver.prototype.observedItemKeys = []; SetObserver.prototype.observerForItemAndKey = function(item, key) {}; SetObserver.prototype._getOrSetObserverForItemAndKey = function(item, key) { var _this = this; return this._itemObservers.getOrSet(item, function() { var observersByKey; observersByKey = new Batman.SimpleHash; return observersByKey.getOrSet(key, function() { return _this.observerForItemAndKey(item, key); }); }); }; SetObserver.prototype.startObserving = function() { this._manageItemObservers("observe"); return this._manageSetObservers("addHandler"); }; SetObserver.prototype.stopObserving = function() { this._manageItemObservers("forget"); return this._manageSetObservers("removeHandler"); }; SetObserver.prototype.startObservingItems = function() { var item, items, _i, _len, _results; items = 1 <= arguments.length ? __slice.call(arguments, 0) : []; _results = []; for (_i = 0, _len = items.length; _i < _len; _i++) { item = items[_i]; _results.push(this._manageObserversForItem(item, "observe")); } return _results; }; SetObserver.prototype.stopObservingItems = function() { var item, items, _i, _len, _results; items = 1 <= arguments.length ? __slice.call(arguments, 0) : []; _results = []; for (_i = 0, _len = items.length; _i < _len; _i++) { item = items[_i]; _results.push(this._manageObserversForItem(item, "forget")); } return _results; }; SetObserver.prototype._manageObserversForItem = function(item, method) { var key, _i, _len, _ref; if (!item.isObservable) { return; } _ref = this.observedItemKeys; for (_i = 0, _len = _ref.length; _i < _len; _i++) { key = _ref[_i]; item[method](key, this._getOrSetObserverForItemAndKey(item, key)); } if (method === "forget") { return this._itemObservers.unset(item); } }; SetObserver.prototype._manageItemObservers = function(method) { var _this = this; return this.base.forEach(function(item) { return _this._manageObserversForItem(item, method); }); }; SetObserver.prototype._manageSetObservers = function(method) { var _this = this; if (!this.base.isObservable) { return; } return this._setObservers.forEach(function(key, observer) { return _this.base.event(key)[method](observer); }); }; return SetObserver; })(Batman.Object); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Batman.SetSort = (function(_super) { __extends(SetSort, _super); function SetSort(base, key, order) { var boundReIndex, _this = this; this.key = key; if (order == null) { order = "asc"; } SetSort.__super__.constructor.call(this, base); this.descending = order.toLowerCase() === "desc"; if (this.base.isObservable) { this._setObserver = new Batman.SetObserver(this.base); this._setObserver.observedItemKeys = [this.key]; boundReIndex = function() { return _this._reIndex(); }; this._setObserver.observerForItemAndKey = function() { return boundReIndex; }; this._setObserver.on('itemsWereAdded', boundReIndex); this._setObserver.on('itemsWereRemoved', boundReIndex); this.startObserving(); } this._reIndex(); } SetSort.prototype.startObserving = function() { var _ref; return (_ref = this._setObserver) != null ? _ref.startObserving() : void 0; }; SetSort.prototype.stopObserving = function() { var _ref; return (_ref = this._setObserver) != null ? _ref.stopObserving() : void 0; }; SetSort.prototype.toArray = function() { return this.get('_storage'); }; SetSort.prototype.forEach = function(iterator, ctx) { var e, i, _i, _len, _ref, _results; _ref = this.get('_storage'); _results = []; for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) { e = _ref[i]; _results.push(iterator.call(ctx, e, i, this)); } return _results; }; SetSort.prototype.find = function(block) { var item, _i, _len, _ref; this.base.registerAsMutableSource(); _ref = this.get('_storage'); for (_i = 0, _len = _ref.length; _i < _len; _i++) { item = _ref[_i]; if (block(item)) { return item; } } }; SetSort.prototype.merge = function(other) { this.base.registerAsMutableSource(); return (function(func, args, ctor) { ctor.prototype = func.prototype; var child = new ctor, result = func.apply(child, args), t = typeof result; return t == "object" || t == "function" ? result || child : child; })(Batman.Set, this._storage, function() {}).merge(other).sortedBy(this.key, this.order); }; SetSort.prototype.compare = function(a, b) { if (a === b) { return 0; } if (a === void 0) { return 1; } if (b === void 0) { return -1; } if (a === null) { return 1; } if (b === null) { return -1; } if (a === false) { return 1; } if (b === false) { return -1; } if (a === true) { return 1; } if (b === true) { return -1; } if (a !== a) { if (b !== b) { return 0; } else { return 1; } } if (b !== b) { return -1; } if (a > b) { return 1; } if (a < b) { return -1; } return 0; }; SetSort.prototype._reIndex = function() { var newOrder, _ref, _this = this; newOrder = this.base.toArray().sort(function(a, b) { var multiple, valueA, valueB; valueA = Batman.get(a, _this.key); if (typeof valueA === 'function') { valueA = valueA.call(a); } if (valueA != null) { valueA = valueA.valueOf(); } valueB = Batman.get(b, _this.key); if (typeof valueB === 'function') { valueB = valueB.call(b); } if (valueB != null) { valueB = valueB.valueOf(); } multiple = _this.descending ? -1 : 1; return _this.compare.call(_this, valueA, valueB) * multiple; }); if ((_ref = this._setObserver) != null) { _ref.startObservingItems.apply(_ref, newOrder); } return this.set('_storage', newOrder); }; return SetSort; })(Batman.SetProxy); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Batman.AssociationSet = (function(_super) { __extends(AssociationSet, _super); function AssociationSet(foreignKeyValue, association) { var base; this.foreignKeyValue = foreignKeyValue; this.association = association; base = new Batman.Set; AssociationSet.__super__.constructor.call(this, base, '_batmanID'); } AssociationSet.prototype.loaded = false; AssociationSet.prototype.load = function(callback) { var _this = this; if (this.foreignKeyValue == null) { return callback(void 0, this); } return this.association.getRelatedModel().loadWithOptions(this._getLoadOptions(), function(err, records) { if (!err) { _this.markAsLoaded(); } return callback(err, _this); }); }; AssociationSet.prototype._getLoadOptions = function() { var loadOptions; loadOptions = { data: {} }; loadOptions.data[this.association.foreignKey] = this.foreignKeyValue; if (this.association.options.url) { loadOptions.collectionUrl = this.association.options.url; loadOptions.urlContext = this.association.parentSetIndex().get(this.foreignKeyValue); } return loadOptions; }; AssociationSet.accessor('loaded', Batman.Property.defaultAccessor); AssociationSet.prototype.markAsLoaded = function() { this.set('loaded', true); return this.fire('loaded'); }; return AssociationSet; })(Batman.SetSort); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Batman.PolymorphicAssociationSet = (function(_super) { __extends(PolymorphicAssociationSet, _super); function PolymorphicAssociationSet(foreignKeyValue, foreignTypeKeyValue, association) { this.foreignKeyValue = foreignKeyValue; this.foreignTypeKeyValue = foreignTypeKeyValue; this.association = association; PolymorphicAssociationSet.__super__.constructor.call(this, this.foreignKeyValue, this.association); } PolymorphicAssociationSet.prototype._getLoadOptions = function() { var loadOptions; loadOptions = { data: {} }; loadOptions.data[this.association.foreignKey] = this.foreignKeyValue; loadOptions.data[this.association.foreignTypeKey] = this.foreignTypeKeyValue; if (this.association.options.url) { loadOptions.collectionUrl = this.association.options.url; loadOptions.urlContext = this.association.parentSetIndex().get(this.foreignKeyValue); } return loadOptions; }; return PolymorphicAssociationSet; })(Batman.AssociationSet); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, __slice = [].slice; Batman.SetIndex = (function(_super) { __extends(SetIndex, _super); SetIndex.accessor('toArray', function() { return this.toArray(); }); Batman.extend(SetIndex.prototype, Batman.Enumerable); SetIndex.prototype.propertyClass = Batman.Property; function SetIndex(base, key) { var _this = this; this.base = base; this.key = key; SetIndex.__super__.constructor.call(this); this._storage = new Batman.Hash; if (this.base.isEventEmitter) { this._setObserver = new Batman.SetObserver(this.base); this._setObserver.observedItemKeys = [this.key]; this._setObserver.observerForItemAndKey = this.observerForItemAndKey.bind(this); this._setObserver.on('itemsWereAdded', function() { var item, items, _i, _len, _results; items = 1 <= arguments.length ? __slice.call(arguments, 0) : []; _results = []; for (_i = 0, _len = items.length; _i < _len; _i++) { item = items[_i]; _results.push(_this._addItem(item)); } return _results; }); this._setObserver.on('itemsWereRemoved', function() { var item, items, _i, _len, _results; items = 1 <= arguments.length ? __slice.call(arguments, 0) : []; _results = []; for (_i = 0, _len = items.length; _i < _len; _i++) { item = items[_i]; _results.push(_this._removeItem(item)); } return _results; }); } this.base.forEach(this._addItem.bind(this)); this.startObserving(); } SetIndex.accessor(function(key) { return this._resultSetForKey(key); }); SetIndex.prototype.startObserving = function() { var _ref; return (_ref = this._setObserver) != null ? _ref.startObserving() : void 0; }; SetIndex.prototype.stopObserving = function() { var _ref; return (_ref = this._setObserver) != null ? _ref.stopObserving() : void 0; }; SetIndex.prototype.observerForItemAndKey = function(item, key) { var _this = this; return function(newValue, oldValue) { _this._removeItemFromKey(item, oldValue); return _this._addItemToKey(item, newValue); }; }; SetIndex.prototype.forEach = function(iterator, ctx) { var _this = this; return this._storage.forEach(function(key, set) { if (set.get('length') > 0) { return iterator.call(ctx, key, set, _this); } }); }; SetIndex.prototype.toArray = function() { var results; results = []; this._storage.forEach(function(key, set) { if (set.get('length') > 0) { return results.push(key); } }); return results; }; SetIndex.prototype._addItem = function(item) { return this._addItemToKey(item, this._keyForItem(item)); }; SetIndex.prototype._addItemToKey = function(item, key) { return this._resultSetForKey(key).add(item); }; SetIndex.prototype._removeItem = function(item) { return this._removeItemFromKey(item, this._keyForItem(item)); }; SetIndex.prototype._removeItemFromKey = function(item, key) { return this._resultSetForKey(key).remove(item); }; SetIndex.prototype._resultSetForKey = function(key) { return this._storage.getOrSet(key, function() { return new Batman.Set; }); }; SetIndex.prototype._keyForItem = function(item) { return Batman.Keypath.forBaseAndKey(item, this.key).getValue(); }; return SetIndex; })(Batman.Object); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Batman.PolymorphicAssociationSetIndex = (function(_super) { __extends(PolymorphicAssociationSetIndex, _super); function PolymorphicAssociationSetIndex(association, type, key) { this.association = association; this.type = type; PolymorphicAssociationSetIndex.__super__.constructor.call(this, this.association.getRelatedModel().get('loaded'), key); } PolymorphicAssociationSetIndex.prototype._resultSetForKey = function(key) { return this.association.setForKey(key); }; PolymorphicAssociationSetIndex.prototype._addItem = function(item) { if (this.association.modelType() !== item.get(this.association.foreignTypeKey)) { return; } return PolymorphicAssociationSetIndex.__super__._addItem.apply(this, arguments); }; PolymorphicAssociationSetIndex.prototype._removeItem = function(item) { if (this.association.modelType() !== item.get(this.association.foreignTypeKey)) { return; } return PolymorphicAssociationSetIndex.__super__._removeItem.apply(this, arguments); }; return PolymorphicAssociationSetIndex; })(Batman.SetIndex); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Batman.AssociationSetIndex = (function(_super) { __extends(AssociationSetIndex, _super); function AssociationSetIndex(association, key) { this.association = association; AssociationSetIndex.__super__.constructor.call(this, this.association.getRelatedModel().get('loaded'), key); } AssociationSetIndex.prototype._resultSetForKey = function(key) { return this.association.setForKey(key); }; AssociationSetIndex.prototype.forEach = function(iterator, ctx) { var _this = this; return this.association.proxies.forEach(function(record, set) { var key; key = _this.association.indexValueForRecord(record); if (set.get('length') > 0) { return iterator.call(ctx, key, set, _this); } }); }; AssociationSetIndex.prototype.toArray = function() { var results; results = []; this.forEach(function(key) { return results.push(key); }); return results; }; return AssociationSetIndex; })(Batman.SetIndex); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Batman.UniqueSetIndex = (function(_super) { __extends(UniqueSetIndex, _super); function UniqueSetIndex() { this._uniqueIndex = new Batman.Hash; UniqueSetIndex.__super__.constructor.apply(this, arguments); } UniqueSetIndex.accessor(function(key) { return this._uniqueIndex.get(key); }); UniqueSetIndex.prototype._addItemToKey = function(item, key) { this._resultSetForKey(key).add(item); if (!this._uniqueIndex.hasKey(key)) { return this._uniqueIndex.set(key, item); } }; UniqueSetIndex.prototype._removeItemFromKey = function(item, key) { var resultSet; resultSet = this._resultSetForKey(key); UniqueSetIndex.__super__._removeItemFromKey.apply(this, arguments); if (resultSet.isEmpty()) { return this._uniqueIndex.unset(key); } else { return this._uniqueIndex.set(key, resultSet.toArray()[0]); } }; return UniqueSetIndex; })(Batman.SetIndex); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Batman.UniqueAssociationSetIndex = (function(_super) { __extends(UniqueAssociationSetIndex, _super); function UniqueAssociationSetIndex(association, key) { this.association = association; UniqueAssociationSetIndex.__super__.constructor.call(this, this.association.getRelatedModel().get('loaded'), key); } return UniqueAssociationSetIndex; })(Batman.UniqueSetIndex); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Batman.PolymorphicUniqueAssociationSetIndex = (function(_super) { __extends(PolymorphicUniqueAssociationSetIndex, _super); function PolymorphicUniqueAssociationSetIndex(association, type, key) { this.association = association; this.type = type; PolymorphicUniqueAssociationSetIndex.__super__.constructor.call(this, this.association.getRelatedModelForType(type).get('loaded'), key); } return PolymorphicUniqueAssociationSetIndex; })(Batman.UniqueSetIndex); }).call(this); (function() { var __bind = function(fn, me) { return function() { return fn.apply(me, arguments); }; }, __slice = [].slice; Batman.Navigator = (function() { Navigator.defaultClass = function() { if (Batman.config.usePushState && Batman.PushStateNavigator.isSupported()) { return Batman.PushStateNavigator; } else { return Batman.HashbangNavigator; } }; Navigator.forApp = function(app) { return new(this.defaultClass())(app); }; function Navigator(app) { this.app = app; this.handleCurrentLocation = __bind(this.handleCurrentLocation, this); } Navigator.prototype.start = function() { var _this = this; if (typeof window === 'undefined') { return; } if (this.started) { return; } this.started = true; this.startWatching(); Batman.currentApp.prevent('ready'); return Batman.setImmediate(function() { if (_this.started && Batman.currentApp) { _this.handleCurrentLocation(); return Batman.currentApp.allowAndFire('ready'); } }); }; Navigator.prototype.stop = function() { this.stopWatching(); return this.started = false; }; Navigator.prototype.handleLocation = function(location) { var path; path = this.pathFromLocation(location); if (path === this.cachedPath) { return; } return this.dispatch(path); }; Navigator.prototype.handleCurrentLocation = function() { return this.handleLocation(window.location); }; Navigator.prototype.dispatch = function(params) { this.cachedPath = this.app.get('dispatcher').dispatch(params); if (this._lastRedirect) { this.cachedPath = this._lastRedirect; } return this.cachedPath; }; Navigator.prototype.push = function(params) { var path, pathFromParams, _base; pathFromParams = typeof(_base = this.app.get('dispatcher')).pathFromParams === "function" ? _base.pathFromParams(params) : void 0; if (pathFromParams) { this._lastRedirect = pathFromParams; } path = this.dispatch(params); if (!this._lastRedirect || this._lastRedirect === path) { this.pushState(null, '', path); } return path; }; Navigator.prototype.replace = function(params) { var path, pathFromParams, _base; pathFromParams = typeof(_base = this.app.get('dispatcher')).pathFromParams === "function" ? _base.pathFromParams(params) : void 0; if (pathFromParams) { this._lastRedirect = pathFromParams; } path = this.dispatch(params); if (!this._lastRedirect || this._lastRedirect === path) { this.replaceState(null, '', path); } return path; }; Navigator.prototype.redirect = Navigator.prototype.push; Navigator.prototype.normalizePath = function() { var i, seg, segments; segments = 1 <= arguments.length ? __slice.call(arguments, 0) : []; segments = (function() { var _i, _len, _results; _results = []; for (i = _i = 0, _len = segments.length; _i < _len; i = ++_i) { seg = segments[i]; _results.push(("" + seg).replace(/^(?!\/)/, '/').replace(/\/+$/, '')); } return _results; })(); return segments.join('') || '/'; }; Navigator.normalizePath = Navigator.prototype.normalizePath; return Navigator; })(); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Batman.PushStateNavigator = (function(_super) { __extends(PushStateNavigator, _super); function PushStateNavigator() { return PushStateNavigator.__super__.constructor.apply(this, arguments); } PushStateNavigator.isSupported = function() { var _ref; return (typeof window !== "undefined" && window !== null ? (_ref = window.history) != null ? _ref.pushState : void 0 : void 0) != null; }; PushStateNavigator.prototype.startWatching = function() { return Batman.DOM.addEventListener(window, 'popstate', this.handleCurrentLocation); }; PushStateNavigator.prototype.stopWatching = function() { return Batman.DOM.removeEventListener(window, 'popstate', this.handleCurrentLocation); }; PushStateNavigator.prototype.pushState = function(stateObject, title, path) { if (path !== this.pathFromLocation(window.location)) { return window.history.pushState(stateObject, title, this.linkTo(path)); } }; PushStateNavigator.prototype.replaceState = function(stateObject, title, path) { if (path !== this.pathFromLocation(window.location)) { return window.history.replaceState(stateObject, title, this.linkTo(path)); } }; PushStateNavigator.prototype.linkTo = function(url) { return this.normalizePath(Batman.config.pathPrefix, url); }; PushStateNavigator.prototype.pathFromLocation = function(location) { var fullPath, prefixPattern; fullPath = "" + (location.pathname || '') + (location.search || ''); prefixPattern = new RegExp("^" + (this.normalizePath(Batman.config.pathPrefix))); return this.normalizePath(fullPath.replace(prefixPattern, '')); }; PushStateNavigator.prototype.handleLocation = function(location) { var hashbangPath, path; path = this.pathFromLocation(location); if (path === '/' && (hashbangPath = Batman.HashbangNavigator.prototype.pathFromLocation(location)) !== '/') { return this.replace(hashbangPath); } else { return PushStateNavigator.__super__.handleLocation.apply(this, arguments); } }; return PushStateNavigator; })(Batman.Navigator); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Batman.HashbangNavigator = (function(_super) { __extends(HashbangNavigator, _super); function HashbangNavigator() { return HashbangNavigator.__super__.constructor.apply(this, arguments); } HashbangNavigator.prototype.HASH_PREFIX = '#!'; if ((typeof window !== "undefined" && window !== null) && 'onhashchange' in window) { HashbangNavigator.prototype.startWatching = function() { return Batman.DOM.addEventListener(window, 'hashchange', this.handleCurrentLocation); }; HashbangNavigator.prototype.stopWatching = function() { return Batman.DOM.removeEventListener(window, 'hashchange', this.handleCurrentLocation); }; } else { HashbangNavigator.prototype.startWatching = function() { return this.interval = setInterval(this.handleCurrentLocation, 100); }; HashbangNavigator.prototype.stopWatching = function() { return this.interval = clearInterval(this.interval); }; } HashbangNavigator.prototype.pushState = function(stateObject, title, path) { return window.location.hash = this.linkTo(path); }; HashbangNavigator.prototype.replaceState = function(stateObject, title, path) { var loc; loc = window.location; return loc.replace("" + loc.pathname + loc.search + (this.linkTo(path))); }; HashbangNavigator.prototype.linkTo = function(url) { return this.HASH_PREFIX + url; }; HashbangNavigator.prototype.pathFromLocation = function(location) { var hash; hash = location.hash; if ((hash != null ? hash.substr(0, 2) : void 0) === this.HASH_PREFIX) { return this.normalizePath(hash.substr(2)); } else { return '/'; } }; HashbangNavigator.prototype.handleLocation = function(location) { var realPath; if (!Batman.config.usePushState) { return HashbangNavigator.__super__.handleLocation.apply(this, arguments); } realPath = Batman.PushStateNavigator.prototype.pathFromLocation(location); if (realPath === '/') { return HashbangNavigator.__super__.handleLocation.apply(this, arguments); } else { return location.replace(this.normalizePath("" + Batman.config.pathPrefix + (this.linkTo(realPath)))); } }; return HashbangNavigator; })(Batman.Navigator); }).call(this); (function() { Batman.RouteMap = (function() { RouteMap.prototype.memberRoute = null; RouteMap.prototype.collectionRoute = null; function RouteMap() { this.childrenByOrder = []; this.childrenByName = {}; } RouteMap.prototype.routeForParams = function(params) { var route, _i, _len, _ref; _ref = this.childrenByOrder; for (_i = 0, _len = _ref.length; _i < _len; _i++) { route = _ref[_i]; if (route.test(params)) { return route; } } return void 0; }; RouteMap.prototype.addRoute = function(name, route) { var base, names, _this = this; this.childrenByOrder.push(route); if (name.length > 0 && (names = name.split('.')).length > 0) { base = names.shift(); if (!this.childrenByName[base]) { this.childrenByName[base] = new Batman.RouteMap; } this.childrenByName[base].addRoute(names.join('.'), route); } else { if (route.get('member')) { Batman.developer["do"](function() { if (_this.memberRoute) { return Batman.developer.error("Member route with name " + name + " already exists!"); } }); this.memberRoute = route; } else { Batman.developer["do"](function() { if (_this.collectionRoute) { return Batman.developer.error("Collection route with name " + name + " already exists!"); } }); this.collectionRoute = route; } } return true; }; return RouteMap; })(); }).call(this); (function() { var __slice = [].slice; Batman.RouteMapBuilder = (function() { RouteMapBuilder.BUILDER_FUNCTIONS = ['resources', 'member', 'collection', 'route', 'root']; RouteMapBuilder.ROUTES = { index: { cardinality: 'collection', path: function(resource) { return resource; }, name: function(resource) { return resource; } }, "new": { cardinality: 'collection', path: function(resource) { return "" + resource + "/new"; }, name: function(resource) { return "" + resource + ".new"; } }, show: { cardinality: 'member', path: function(resource) { return "" + resource + "/:id"; }, name: function(resource) { return resource; } }, edit: { cardinality: 'member', path: function(resource) { return "" + resource + "/:id/edit"; }, name: function(resource) { return "" + resource + ".edit"; } }, collection: { cardinality: 'collection', path: function(resource, name) { return "" + resource + "/" + name; }, name: function(resource, name) { return "" + resource + "." + name; } }, member: { cardinality: 'member', path: function(resource, name) { return "" + resource + "/:id/" + name; }, name: function(resource, name) { return "" + resource + "." + name; } } }; function RouteMapBuilder(app, routeMap, parent, baseOptions) { this.app = app; this.routeMap = routeMap; this.parent = parent; this.baseOptions = baseOptions != null ? baseOptions : {}; if (this.parent) { this.rootPath = this.parent._nestingPath(); this.rootName = this.parent._nestingName(); } else { this.rootPath = ''; this.rootName = ''; } } RouteMapBuilder.prototype.resources = function() { var action, actions, arg, args, as, callback, childBuilder, controller, included, k, options, path, resourceName, resourceNames, resourceRoot, routeOptions, routeTemplate, v, _i, _j, _k, _len, _len1, _len2, _ref, _ref1; args = 1 <= arguments.length ? __slice.call(arguments, 0) : []; resourceNames = (function() { var _i, _len, _results; _results = []; for (_i = 0, _len = args.length; _i < _len; _i++) { arg = args[_i]; if (typeof arg === 'string') { _results.push(arg); } } return _results; })(); if (typeof args[args.length - 1] === 'function') { callback = args.pop(); } if (typeof args[args.length - 1] === 'object') { options = args.pop(); } else { options = {}; } actions = { index: true, "new": true, show: true, edit: true }; if (options.except) { _ref = options.except; for (_i = 0, _len = _ref.length; _i < _len; _i++) { k = _ref[_i]; actions[k] = false; } delete options.except; } else if (options.only) { for (k in actions) { v = actions[k]; actions[k] = false; } _ref1 = options.only; for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { k = _ref1[_j]; actions[k] = true; } delete options.only; } for (_k = 0, _len2 = resourceNames.length; _k < _len2; _k++) { resourceName = resourceNames[_k]; resourceRoot = Batman.helpers.pluralize(resourceName); controller = Batman.helpers.camelize(resourceRoot, true); childBuilder = this._childBuilder({ controller: controller }); if (callback != null) { callback.call(childBuilder); } for (action in actions) { included = actions[action]; if (!(included)) { continue; } routeTemplate = this.constructor.ROUTES[action]; as = routeTemplate.name(resourceRoot); path = routeTemplate.path(resourceRoot); routeOptions = Batman.extend({ controller: controller, action: action, path: path, as: as }, options); childBuilder[routeTemplate.cardinality](action, routeOptions); } } return true; }; RouteMapBuilder.prototype.member = function() { return this._addRoutesWithCardinality.apply(this, ['member'].concat(__slice.call(arguments))); }; RouteMapBuilder.prototype.collection = function() { return this._addRoutesWithCardinality.apply(this, ['collection'].concat(__slice.call(arguments))); }; RouteMapBuilder.prototype.root = function(signature, options) { return this.route('/', signature, options); }; RouteMapBuilder.prototype.route = function(path, signature, options, callback) { if (!callback) { if (typeof options === 'function') { callback = options; options = void 0; } else if (typeof signature === 'function') { callback = signature; signature = void 0; } } if (!options) { if (typeof signature === 'string') { options = { signature: signature }; } else { options = signature; } options || (options = {}); } else { if (signature) { options.signature = signature; } } if (callback) { options.callback = callback; } options.as || (options.as = this._nameFromPath(path)); options.path = path; return this._addRoute(options); }; RouteMapBuilder.prototype._addRoutesWithCardinality = function() { var cardinality, name, names, options, resourceRoot, routeOptions, routeTemplate, _i, _j, _len; cardinality = arguments[0], names = 3 <= arguments.length ? __slice.call(arguments, 1, _i = arguments.length - 1) : (_i = 1, []), options = arguments[_i++]; if (typeof options === 'string') { names.push(options); options = {}; } options = Batman.extend({}, this.baseOptions, options); options[cardinality] = true; routeTemplate = this.constructor.ROUTES[cardinality]; resourceRoot = Batman.helpers.underscore(options.controller); for (_j = 0, _len = names.length; _j < _len; _j++) { name = names[_j]; routeOptions = Batman.extend({ action: name }, options); if (routeOptions.path == null) { routeOptions.path = routeTemplate.path(resourceRoot, name); } if (routeOptions.as == null) { routeOptions.as = routeTemplate.name(resourceRoot, name); } this._addRoute(routeOptions); } return true; }; RouteMapBuilder.prototype._addRoute = function(options) { var klass, name, path, route; if (options == null) { options = {}; } path = this.rootPath + options.path; name = this.rootName + Batman.helpers.camelize(options.as, true); delete options.as; delete options.path; klass = options.callback ? Batman.CallbackActionRoute : Batman.ControllerActionRoute; options.app = this.app; route = new klass(path, options); return this.routeMap.addRoute(name, route); }; RouteMapBuilder.prototype._nameFromPath = function(path) { path = path.replace(Batman.Route.regexps.namedOrSplat, '').replace(/\/+/g, '.').replace(/(^\.)|(\.$)/g, ''); return path; }; RouteMapBuilder.prototype._nestingPath = function() { var nestingParam, nestingSegment; if (!this.parent) { return ""; } else { nestingParam = ":" + Batman.helpers.singularize(this.baseOptions.controller) + "Id"; nestingSegment = Batman.helpers.underscore(this.baseOptions.controller); return "" + (this.parent._nestingPath()) + nestingSegment + "/" + nestingParam + "/"; } }; RouteMapBuilder.prototype._nestingName = function() { if (!this.parent) { return ""; } else { return this.parent._nestingName() + this.baseOptions.controller + "."; } }; RouteMapBuilder.prototype._childBuilder = function(baseOptions) { if (baseOptions == null) { baseOptions = {}; } return new Batman.RouteMapBuilder(this.app, this.routeMap, this, baseOptions); }; return RouteMapBuilder; })(); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, __slice = [].slice; Batman.App = (function(_super) { var name, _fn, _i, _len, _ref, _this = this; __extends(App, _super); function App() { return App.__super__.constructor.apply(this, arguments); } App.classAccessor('currentParams', { get: function() { return new Batman.Hash; }, 'final': true }); App.classAccessor('paramsManager', { get: function() { var nav, params; if (!(nav = this.get('navigator'))) { return; } params = this.get('currentParams'); return params.replacer = new Batman.ParamsReplacer(nav, params); }, 'final': true }); App.classAccessor('paramsPusher', { get: function() { var nav, params; if (!(nav = this.get('navigator'))) { return; } params = this.get('currentParams'); return params.pusher = new Batman.ParamsPusher(nav, params); }, 'final': true }); App.classAccessor('routes', function() { return new Batman.NamedRouteQuery(this.get('routeMap')); }); App.classAccessor('routeMap', function() { return new Batman.RouteMap; }); App.classAccessor('routeMapBuilder', function() { return new Batman.RouteMapBuilder(this, this.get('routeMap')); }); App.classAccessor('dispatcher', function() { return new Batman.Dispatcher(this, this.get('routeMap')); }); App.classAccessor('controllers', function() { return this.get('dispatcher.controllers'); }); App.classAccessor('_renderContext', function() { return Batman.RenderContext.base.descend(this); }); App.requirePath = ''; Batman.developer["do"](function() { var requireDeprecated; requireDeprecated = "Please use whatever means you'd like to load your code before calling App.run."; App.require = function() { var base, name, names, path, _i, _len, _this = this; path = arguments[0], names = 2 <= arguments.length ? __slice.call(arguments, 1) : []; Batman.developer.deprecated("App.require", requireDeprecated); base = this.requirePath + path; for (_i = 0, _len = names.length; _i < _len; _i++) { name = names[_i]; this.prevent('run'); path = base + '/' + name + '.coffee'; new Batman.Request({ url: path, type: 'html', success: function(response) { CoffeeScript["eval"](response); _this.allow('run'); if (!_this.isPrevented('run')) { _this.fire('loaded'); } if (_this.wantsToRun) { return _this.run(); } } }); } return this; }; App.controller = function() { var names; names = 1 <= arguments.length ? __slice.call(arguments, 0) : []; Batman.developer.deprecated("App.controller", requireDeprecated); names = names.map(function(n) { return n + '_controller'; }); return this.require.apply(this, ['controllers'].concat(__slice.call(names))); }; App.model = function() { Batman.developer.deprecated("App.model", requireDeprecated); return this.require.apply(this, ['models'].concat(__slice.call(arguments))); }; return App.view = function() { Batman.developer.deprecated("App.view", requireDeprecated); return this.require.apply(this, ['views'].concat(__slice.call(arguments))); }; }); App.layout = void 0; App.shouldAllowEvent = {}; _ref = Batman.RouteMapBuilder.BUILDER_FUNCTIONS; _fn = function(name) { return App[name] = function() { var _ref1; return (_ref1 = this.get('routeMapBuilder'))[name].apply(_ref1, arguments); }; }; for (_i = 0, _len = _ref.length; _i < _len; _i++) { name = _ref[_i]; _fn(name); } App.event('ready').oneShot = true; App.event('run').oneShot = true; App.run = function() { var layout, layoutClass, _this = this; if (Batman.currentApp) { if (Batman.currentApp === this) { return; } Batman.currentApp.stop(); } if (this.hasRun) { return false; } if (this.isPrevented('run')) { this.wantsToRun = true; return false; } else { delete this.wantsToRun; } Batman.currentApp = this; Batman.App.set('current', this); if (this.get('dispatcher') == null) { this.set('dispatcher', new Batman.Dispatcher(this, this.get('routeMap'))); this.set('controllers', this.get('dispatcher.controllers')); } if (this.get('navigator') == null) { this.set('navigator', Batman.Navigator.forApp(this)); this.on('run', function() { Batman.navigator = _this.get('navigator'); if (Object.keys(_this.get('dispatcher').routeMap).length > 0) { return Batman.navigator.start(); } }); } this.observe('layout', function(layout) { return layout != null ? layout.on('ready', function() { return _this.fire('ready'); }) : void 0; }); layout = this.get('layout'); if (layout) { if (typeof layout === 'string') { layoutClass = this[Batman.helpers.camelize(layout) + 'View']; } } else { if (layout !== null) { layoutClass = Batman.View; } } if (layoutClass) { layout = this.set('layout', new layoutClass({ context: this, node: document })); } this.hasRun = true; this.fire('run'); return this; }; App.event('ready').oneShot = true; App.event('stop').oneShot = true; App.stop = function() { var _ref1; if ((_ref1 = this.navigator) != null) { _ref1.stop(); } Batman.navigator = null; this.hasRun = false; this.fire('stop'); return this; }; return App; }).call(this, Batman.Object); }).call(this); (function() { Batman.Association = (function() { Association.prototype.associationType = ''; Association.prototype.isPolymorphic = false; Association.prototype.defaultOptions = { saveInline: true, autoload: true, nestUrl: false }; function Association(model, label, options) { var defaultOptions, encoder, getAccessor, self; this.model = model; this.label = label; if (options == null) { options = {}; } defaultOptions = { namespace: Batman.currentApp, name: Batman.helpers.camelize(Batman.helpers.singularize(this.label)) }; this.options = Batman.extend(defaultOptions, this.defaultOptions, options); if (this.options.nestUrl) { if (!(this.model.urlNestsUnder != null)) { Batman.developer.error("You must persist the the model " + this.model.constructor.name + " to use the url helpers on an association"); } this.model.urlNestsUnder(Batman.helpers.underscore(this.getRelatedModel().get('resourceName'))); } if (this.options.extend != null) { Batman.extend(this, this.options.extend); } encoder = { encode: this.options.saveInline ? this.encoder() : false, decode: this.decoder() }; this.model.encode(this.label, encoder); self = this; getAccessor = function() { return self.getAccessor.call(this, self, this.model, this.label); }; this.model.accessor(this.label, { get: getAccessor, set: model.defaultAccessor.set, unset: model.defaultAccessor.unset }); } Association.prototype.getRelatedModel = function() { var className, relatedModel, scope; scope = this.options.namespace || Batman.currentApp; className = this.options.name; relatedModel = scope != null ? scope[className] : void 0; Batman.developer["do"](function() { if ((Batman.currentApp != null) && !relatedModel) { return Batman.developer.warn("Related model " + className + " hasn't loaded yet."); } }); return relatedModel; }; Association.prototype.getFromAttributes = function(record) { return record.get("attributes." + this.label); }; Association.prototype.setIntoAttributes = function(record, value) { return record.get('attributes').set(this.label, value); }; Association.prototype.inverse = function() { var inverse, relatedAssocs, _this = this; if (relatedAssocs = this.getRelatedModel()._batman.get('associations')) { if (this.options.inverseOf) { return relatedAssocs.getByLabel(this.options.inverseOf); } inverse = null; relatedAssocs.forEach(function(label, assoc) { if (assoc.getRelatedModel() === _this.model) { return inverse = assoc; } }); return inverse; } }; Association.prototype.reset = function() { delete this.index; return true; }; return Association; })(); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Batman.PluralAssociation = (function(_super) { __extends(PluralAssociation, _super); PluralAssociation.prototype.proxyClass = Batman.AssociationSet; PluralAssociation.prototype.isSingular = false; function PluralAssociation() { PluralAssociation.__super__.constructor.apply(this, arguments); this._resetSetHashes(); } PluralAssociation.prototype.setForRecord = function(record) { var childModelSetIndex, indexValue, _this = this; indexValue = this.indexValueForRecord(record); childModelSetIndex = this.setIndex(); Batman.Property.withoutTracking(function() { return _this._setsByRecord.getOrSet(record, function() { var existingValueSet, newSet; if (indexValue != null) { existingValueSet = _this._setsByValue.get(indexValue); if (existingValueSet != null) { return existingValueSet; } } newSet = _this.proxyClassInstanceForKey(indexValue); if (indexValue != null) { _this._setsByValue.set(indexValue, newSet); } return newSet; }); }); if (indexValue != null) { return childModelSetIndex.get(indexValue); } else { return this._setsByRecord.get(record); } }; PluralAssociation.prototype.setForKey = Batman.Property.wrapTrackingPrevention(function(indexValue) { var foundSet, _this = this; foundSet = void 0; this._setsByRecord.forEach(function(record, set) { if (foundSet != null) { return; } if (_this.indexValueForRecord(record) === indexValue) { return foundSet = set; } }); if (foundSet != null) { foundSet.foreignKeyValue = indexValue; return foundSet; } return this._setsByValue.getOrSet(indexValue, function() { return _this.proxyClassInstanceForKey(indexValue); }); }); PluralAssociation.prototype.proxyClassInstanceForKey = function(indexValue) { return new this.proxyClass(indexValue, this); }; PluralAssociation.prototype.getAccessor = function(self, model, label) { var relatedRecords, setInAttributes, _this = this; if (!self.getRelatedModel()) { return; } if (setInAttributes = self.getFromAttributes(this)) { return setInAttributes; } else { relatedRecords = self.setForRecord(this); self.setIntoAttributes(this, relatedRecords); Batman.Property.withoutTracking(function() { if (self.options.autoload && !_this.isNew() && !relatedRecords.loaded) { return relatedRecords.load(function(error, records) { if (error) { throw error; } }); } }); return relatedRecords; } }; PluralAssociation.prototype.parentSetIndex = function() { this.parentIndex || (this.parentIndex = this.model.get('loaded').indexedByUnique(this.primaryKey)); return this.parentIndex; }; PluralAssociation.prototype.setIndex = function() { this.index || (this.index = new Batman.AssociationSetIndex(this, this[this.indexRelatedModelOn])); return this.index; }; PluralAssociation.prototype.indexValueForRecord = function(record) { return record.get(this.primaryKey); }; PluralAssociation.prototype.reset = function() { PluralAssociation.__super__.reset.apply(this, arguments); return this._resetSetHashes(); }; PluralAssociation.prototype._resetSetHashes = function() { this._setsByRecord = new Batman.SimpleHash; return this._setsByValue = new Batman.SimpleHash; }; return PluralAssociation; })(Batman.Association); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Batman.HasManyAssociation = (function(_super) { __extends(HasManyAssociation, _super); HasManyAssociation.prototype.associationType = 'hasMany'; HasManyAssociation.prototype.indexRelatedModelOn = 'foreignKey'; function HasManyAssociation(model, label, options) { if (options != null ? options.as : void 0) { return (function(func, args, ctor) { ctor.prototype = func.prototype; var child = new ctor, result = func.apply(child, args), t = typeof result; return t == "object" || t == "function" ? result || child : child; })(Batman.PolymorphicHasManyAssociation, arguments, function() {}); } HasManyAssociation.__super__.constructor.apply(this, arguments); this.primaryKey = this.options.primaryKey || "id"; this.foreignKey = this.options.foreignKey || ("" + (Batman.helpers.underscore(model.get('resourceName'))) + "_id"); } HasManyAssociation.prototype.apply = function(baseSaveError, base) { var relations, set, _this = this; if (!baseSaveError) { if (relations = this.getFromAttributes(base)) { relations.forEach(function(model) { return model.set(_this.foreignKey, base.get(_this.primaryKey)); }); } base.set(this.label, set = this.setForRecord(base)); if (base.lifecycle.get('state') === 'creating') { return set.markAsLoaded(); } } }; HasManyAssociation.prototype.encoder = function() { var association; association = this; return function(relationSet, _, __, record) { var jsonArray; if (relationSet != null) { jsonArray = []; relationSet.forEach(function(relation) { var relationJSON; relationJSON = relation.toJSON(); if (!association.inverse() || association.inverse().options.encodeForeignKey) { relationJSON[association.foreignKey] = record.get(association.primaryKey); } return jsonArray.push(relationJSON); }); } return jsonArray; }; }; HasManyAssociation.prototype.decoder = function() { var association; association = this; return function(data, key, _, __, parentRecord) { var existingRecord, existingRelations, jsonObject, newRelations, record, relatedModel, savedRecord, _i, _len; if (relatedModel = association.getRelatedModel()) { existingRelations = association.getFromAttributes(parentRecord) || association.setForRecord(parentRecord); newRelations = existingRelations.filter(function(relation) { return relation.isNew(); }).toArray(); for (_i = 0, _len = data.length; _i < _len; _i++) { jsonObject = data[_i]; record = new relatedModel(); record._withoutDirtyTracking(function() { return this.fromJSON(jsonObject); }); existingRecord = relatedModel.get('loaded').indexedByUnique('id').get(record.get('id')); if (existingRecord != null) { existingRecord._withoutDirtyTracking(function() { return this.fromJSON(jsonObject); }); record = existingRecord; } else { if (newRelations.length > 0) { savedRecord = newRelations.shift(); savedRecord._withoutDirtyTracking(function() { return this.fromJSON(jsonObject); }); record = savedRecord; } } record = relatedModel._mapIdentity(record); existingRelations.add(record); if (association.options.inverseOf) { record.set(association.options.inverseOf, parentRecord); } } existingRelations.markAsLoaded(); } else { Batman.developer.error("Can't decode model " + association.options.name + " because it hasn't been loaded yet!"); } return existingRelations; }; }; return HasManyAssociation; })(Batman.PluralAssociation); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Batman.PolymorphicHasManyAssociation = (function(_super) { __extends(PolymorphicHasManyAssociation, _super); PolymorphicHasManyAssociation.prototype.proxyClass = Batman.PolymorphicAssociationSet; PolymorphicHasManyAssociation.prototype.isPolymorphic = true; function PolymorphicHasManyAssociation(model, label, options) { options.inverseOf = this.foreignLabel = options.as; delete options.as; options.foreignKey || (options.foreignKey = "" + this.foreignLabel + "_id"); PolymorphicHasManyAssociation.__super__.constructor.call(this, model, label, options); this.foreignTypeKey = options.foreignTypeKey || ("" + this.foreignLabel + "_type"); this.model.encode(this.foreignTypeKey); } PolymorphicHasManyAssociation.prototype.apply = function(baseSaveError, base) { var relations, _this = this; if (!baseSaveError) { if (relations = this.getFromAttributes(base)) { PolymorphicHasManyAssociation.__super__.apply.apply(this, arguments); relations.forEach(function(model) { return model.set(_this.foreignTypeKey, _this.modelType()); }); } } return true; }; PolymorphicHasManyAssociation.prototype.proxyClassInstanceForKey = function(indexValue) { return new this.proxyClass(indexValue, this.modelType(), this); }; PolymorphicHasManyAssociation.prototype.getRelatedModelForType = function(type) { var relatedModel, scope; scope = this.options.namespace || Batman.currentApp; if (type) { relatedModel = scope != null ? scope[type] : void 0; relatedModel || (relatedModel = scope != null ? scope[Batman.helpers.camelize(type)] : void 0); } else { relatedModel = this.getRelatedModel(); } Batman.developer["do"](function() { if ((Batman.currentApp != null) && !relatedModel) { return Batman.developer.warn("Related model " + type + " for polymorphic association not found."); } }); return relatedModel; }; PolymorphicHasManyAssociation.prototype.modelType = function() { return this.model.get('resourceName'); }; PolymorphicHasManyAssociation.prototype.setIndex = function() { this.typeIndex || (this.typeIndex = new Batman.PolymorphicAssociationSetIndex(this, this.modelType(), this[this.indexRelatedModelOn])); return this.typeIndex; }; PolymorphicHasManyAssociation.prototype.encoder = function() { var association; association = this; return function(relationSet, _, __, record) { var jsonArray; if (relationSet != null) { jsonArray = []; relationSet.forEach(function(relation) { var relationJSON; relationJSON = relation.toJSON(); relationJSON[association.foreignKey] = record.get(association.primaryKey); relationJSON[association.foreignTypeKey] = association.modelType(); return jsonArray.push(relationJSON); }); } return jsonArray; }; }; PolymorphicHasManyAssociation.prototype.decoder = function() { var association; association = this; return function(data, key, _, __, parentRecord) { var existingRecord, existingRelations, jsonObject, newRelations, record, relatedModel, savedRecord, subType, type, _i, _len; if (relatedModel = association.getRelatedModel()) { existingRelations = association.getFromAttributes(parentRecord) || association.setForRecord(parentRecord); newRelations = existingRelations.filter(function(relation) { return relation.isNew(); }).toArray(); for (_i = 0, _len = data.length; _i < _len; _i++) { jsonObject = data[_i]; type = jsonObject[association.options.foreignTypeKey]; subType = association.getRelatedModelForType(type); record = new subType(); record._withoutDirtyTracking(function() { return this.fromJSON(jsonObject); }); existingRecord = relatedModel.get('loaded').indexedByUnique('id').get(record.get('id')); if (existingRecord != null) { existingRecord._withoutDirtyTracking(function() { return this.fromJSON(jsonObject); }); record = existingRecord; } else { if (newRelations.length > 0) { savedRecord = newRelations.shift(); savedRecord._withoutDirtyTracking(function() { return this.fromJSON(jsonObject); }); record = savedRecord; } } record = relatedModel._mapIdentity(record); existingRelations.add(record); if (association.options.inverseOf) { record.set(association.options.inverseOf, parentRecord); } } existingRelations.markAsLoaded(); } else { Batman.developer.error("Can't decode model " + association.options.name + " because it hasn't been loaded yet!"); } return existingRelations; }; }; return PolymorphicHasManyAssociation; })(Batman.HasManyAssociation); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Batman.SingularAssociation = (function(_super) { __extends(SingularAssociation, _super); function SingularAssociation() { return SingularAssociation.__super__.constructor.apply(this, arguments); } SingularAssociation.prototype.isSingular = true; SingularAssociation.prototype.getAccessor = function(self, model, label) { var parent, proxy, record, recordInAttributes, _ref; if (recordInAttributes = self.getFromAttributes(this)) { return recordInAttributes; } if (self.getRelatedModel()) { proxy = this.associationProxy(self); record = false; parent = this; if ((_ref = proxy._loadSetter) == null) { proxy._loadSetter = proxy.once('loaded', function(child) { return parent._withoutDirtyTracking(function() { return this.set(self.label, child); }); }); } if (!Batman.Property.withoutTracking(function() { return proxy.get('loaded'); })) { if (self.options.autoload) { Batman.Property.withoutTracking(function() { return proxy.load(); }); } else { record = proxy.loadFromLocal(); } } return record || proxy; } }; SingularAssociation.prototype.setIndex = function() { this.index || (this.index = new Batman.UniqueAssociationSetIndex(this, this[this.indexRelatedModelOn])); return this.index; }; return SingularAssociation; })(Batman.Association); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Batman.HasOneAssociation = (function(_super) { __extends(HasOneAssociation, _super); HasOneAssociation.prototype.associationType = 'hasOne'; HasOneAssociation.prototype.proxyClass = Batman.HasOneProxy; HasOneAssociation.prototype.indexRelatedModelOn = 'foreignKey'; function HasOneAssociation() { HasOneAssociation.__super__.constructor.apply(this, arguments); this.primaryKey = this.options.primaryKey || "id"; this.foreignKey = this.options.foreignKey || ("" + (Batman.helpers.underscore(this.model.get('resourceName'))) + "_id"); } HasOneAssociation.prototype.apply = function(baseSaveError, base) { var relation; if (relation = this.getFromAttributes(base)) { return relation.set(this.foreignKey, base.get(this.primaryKey)); } }; HasOneAssociation.prototype.encoder = function() { var association; association = this; return function(val, key, object, record) { var json; if (!association.options.saveInline) { return; } if (json = val.toJSON()) { json[association.foreignKey] = record.get(association.primaryKey); } return json; }; }; HasOneAssociation.prototype.decoder = function() { var association; association = this; return function(data, _, __, ___, parentRecord) { var record, relatedModel; if (!data) { return; } relatedModel = association.getRelatedModel(); record = relatedModel.createFromJSON(data); if (association.options.inverseOf) { record.set(association.options.inverseOf, parentRecord); } return record; }; }; return HasOneAssociation; })(Batman.SingularAssociation); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Batman.BelongsToAssociation = (function(_super) { __extends(BelongsToAssociation, _super); BelongsToAssociation.prototype.associationType = 'belongsTo'; BelongsToAssociation.prototype.proxyClass = Batman.BelongsToProxy; BelongsToAssociation.prototype.indexRelatedModelOn = 'primaryKey'; BelongsToAssociation.prototype.defaultOptions = { saveInline: false, autoload: true, encodeForeignKey: true }; function BelongsToAssociation(model, label, options) { if (options != null ? options.polymorphic : void 0) { delete options.polymorphic; return (function(func, args, ctor) { ctor.prototype = func.prototype; var child = new ctor, result = func.apply(child, args), t = typeof result; return t == "object" || t == "function" ? result || child : child; })(Batman.PolymorphicBelongsToAssociation, arguments, function() {}); } BelongsToAssociation.__super__.constructor.apply(this, arguments); this.foreignKey = this.options.foreignKey || ("" + this.label + "_id"); this.primaryKey = this.options.primaryKey || "id"; if (this.options.encodeForeignKey) { this.model.encode(this.foreignKey); } } BelongsToAssociation.prototype.encoder = function() { return function(val) { return val.toJSON(); }; }; BelongsToAssociation.prototype.decoder = function() { var association; association = this; return function(data, _, __, ___, childRecord) { var inverse, record, relatedModel; relatedModel = association.getRelatedModel(); record = relatedModel.createFromJSON(data); if (association.options.inverseOf) { if (inverse = association.inverse()) { if (inverse instanceof Batman.HasManyAssociation) { childRecord.set(association.foreignKey, record.get(association.primaryKey)); } else { record.set(inverse.label, childRecord); } } } childRecord.set(association.label, record); return record; }; }; BelongsToAssociation.prototype.apply = function(base) { var foreignValue, model; if (model = base.get(this.label)) { foreignValue = model.get(this.primaryKey); if (foreignValue !== void 0) { return base.set(this.foreignKey, foreignValue); } } }; return BelongsToAssociation; })(Batman.SingularAssociation); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Batman.PolymorphicBelongsToAssociation = (function(_super) { __extends(PolymorphicBelongsToAssociation, _super); PolymorphicBelongsToAssociation.prototype.isPolymorphic = true; PolymorphicBelongsToAssociation.prototype.proxyClass = Batman.PolymorphicBelongsToProxy; PolymorphicBelongsToAssociation.prototype.defaultOptions = Batman.mixin({}, Batman.BelongsToAssociation.prototype.defaultOptions, { encodeForeignTypeKey: true }); function PolymorphicBelongsToAssociation() { PolymorphicBelongsToAssociation.__super__.constructor.apply(this, arguments); this.foreignTypeKey = this.options.foreignTypeKey || ("" + this.label + "_type"); if (this.options.encodeForeignTypeKey) { this.model.encode(this.foreignTypeKey); } this.typeIndicies = {}; } PolymorphicBelongsToAssociation.prototype.getRelatedModel = false; PolymorphicBelongsToAssociation.prototype.setIndex = false; PolymorphicBelongsToAssociation.prototype.inverse = false; PolymorphicBelongsToAssociation.prototype.apply = function(base) { var foreignTypeValue, instanceOrProxy; PolymorphicBelongsToAssociation.__super__.apply.apply(this, arguments); if (instanceOrProxy = base.get(this.label)) { foreignTypeValue = instanceOrProxy instanceof Batman.PolymorphicBelongsToProxy ? instanceOrProxy.get('foreignTypeValue') : instanceOrProxy.constructor.get('resourceName'); return base.set(this.foreignTypeKey, foreignTypeValue); } }; PolymorphicBelongsToAssociation.prototype.getAccessor = function(self, model, label) { var proxy, recordInAttributes; if (recordInAttributes = self.getFromAttributes(this)) { return recordInAttributes; } if (self.getRelatedModelForType(this.get(self.foreignTypeKey))) { proxy = this.associationProxy(self); Batman.Property.withoutTracking(function() { if (!proxy.get('loaded') && self.options.autoload) { return proxy.load(); } }); return proxy; } }; PolymorphicBelongsToAssociation.prototype.url = function(recordOptions) { var ending, helper, id, inverse, root, type, _ref, _ref1; type = (_ref = recordOptions.data) != null ? _ref[this.foreignTypeKey] : void 0; if (type && (inverse = this.inverseForType(type))) { root = Batman.helpers.pluralize(type).toLowerCase(); id = (_ref1 = recordOptions.data) != null ? _ref1[this.foreignKey] : void 0; helper = inverse.isSingular ? "singularize" : "pluralize"; ending = Batman.helpers[helper](inverse.label); return "/" + root + "/" + id + "/" + ending; } }; PolymorphicBelongsToAssociation.prototype.getRelatedModelForType = function(type) { var relatedModel, scope; scope = this.options.namespace || Batman.currentApp; if (type) { relatedModel = scope != null ? scope[type] : void 0; relatedModel || (relatedModel = scope != null ? scope[Batman.helpers.camelize(type)] : void 0); } Batman.developer["do"](function() { if ((Batman.currentApp != null) && !relatedModel) { return Batman.developer.warn("Related model " + type + " for polymorphic association not found."); } }); return relatedModel; }; PolymorphicBelongsToAssociation.prototype.setIndexForType = function(type) { var _base; (_base = this.typeIndicies)[type] || (_base[type] = new Batman.PolymorphicUniqueAssociationSetIndex(this, type, this.primaryKey)); return this.typeIndicies[type]; }; PolymorphicBelongsToAssociation.prototype.inverseForType = function(type) { var inverse, relatedAssocs, _ref, _this = this; if (relatedAssocs = (_ref = this.getRelatedModelForType(type)) != null ? _ref._batman.get('associations') : void 0) { if (this.options.inverseOf) { return relatedAssocs.getByLabel(this.options.inverseOf); } inverse = null; relatedAssocs.forEach(function(label, assoc) { if (assoc.getRelatedModel() === _this.model) { return inverse = assoc; } }); return inverse; } }; PolymorphicBelongsToAssociation.prototype.decoder = function() { var association; association = this; return function(data, key, response, ___, childRecord) { var foreignTypeValue, inverse, record, relatedModel; foreignTypeValue = response[association.foreignTypeKey] || childRecord.get(association.foreignTypeKey); relatedModel = association.getRelatedModelForType(foreignTypeValue); record = relatedModel.createFromJSON(data); if (association.options.inverseOf) { if (inverse = association.inverseForType(foreignTypeValue)) { if (inverse instanceof Batman.PolymorphicHasManyAssociation) { childRecord.set(association.foreignKey, record.get(association.primaryKey)); childRecord.set(association.foreignTypeKey, foreignTypeValue); } else { record.set(inverse.label, childRecord); } } } childRecord.set(association.label, record); return record; }; }; return PolymorphicBelongsToAssociation; })(Batman.BelongsToAssociation); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, __slice = [].slice; Batman.Validator = (function(_super) { __extends(Validator, _super); Validator.triggers = function() { var triggers; triggers = 1 <= arguments.length ? __slice.call(arguments, 0) : []; if (this._triggers != null) { return this._triggers.concat(triggers); } else { return this._triggers = triggers; } }; Validator.options = function() { var options; options = 1 <= arguments.length ? __slice.call(arguments, 0) : []; if (this._options != null) { return this._options.concat(options); } else { return this._options = options; } }; Validator.matches = function(options) { var key, results, shouldReturn, value, _ref, _ref1; results = {}; shouldReturn = false; for (key in options) { value = options[key]; if (~ ((_ref = this._options) != null ? _ref.indexOf(key) : void 0)) { results[key] = value; } if (~ ((_ref1 = this._triggers) != null ? _ref1.indexOf(key) : void 0)) { results[key] = value; shouldReturn = true; } } if (shouldReturn) { return results; } }; function Validator() { var mixins, options; options = arguments[0], mixins = 2 <= arguments.length ? __slice.call(arguments, 1) : []; this.options = options; Validator.__super__.constructor.apply(this, mixins); } Validator.prototype.validate = function(record) { return Batman.developer.error("You must override validate in Batman.Validator subclasses."); }; Validator.prototype.format = function(key, messageKey, interpolations) { return Batman.t("errors.messages." + messageKey, interpolations); }; Validator.prototype.handleBlank = function(value) { if (this.options.allowBlank && !Batman.PresenceValidator.prototype.isPresent(value)) { return true; } }; return Validator; })(Batman.Object); }).call(this); (function() { Batman.Validators = []; Batman.extend(Batman.translate.messages, { errors: { format: "%{attribute} %{message}", messages: { too_short: "must be at least %{count} characters", too_long: "must be less than %{count} characters", wrong_length: "must be %{count} characters", blank: "can't be blank", not_numeric: "must be a number", greater_than: "must be greater than %{count}", greater_than_or_equal_to: "must be greater than or equal to %{count}", equal_to: "must be equal to %{count}", less_than: "must be less than %{count}", less_than_or_equal_to: "must be less than or equal to %{count}", not_matching: "is not valid", invalid_association: "is not valid" } } }); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Batman.RegExpValidator = (function(_super) { __extends(RegExpValidator, _super); RegExpValidator.triggers('regexp', 'pattern'); RegExpValidator.options('allowBlank'); function RegExpValidator(options) { var _ref; this.regexp = (_ref = options.regexp) != null ? _ref : options.pattern; RegExpValidator.__super__.constructor.apply(this, arguments); } RegExpValidator.prototype.validateEach = function(errors, record, key, callback) { var value; value = record.get(key); if (this.handleBlank(value)) { return callback(); } if (!(value != null) || value === '' || !this.regexp.test(value)) { errors.add(key, this.format(key, 'not_matching')); } return callback(); }; return RegExpValidator; })(Batman.Validator); Batman.Validators.push(Batman.RegExpValidator); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Batman.PresenceValidator = (function(_super) { __extends(PresenceValidator, _super); function PresenceValidator() { return PresenceValidator.__super__.constructor.apply(this, arguments); } PresenceValidator.triggers('presence'); PresenceValidator.prototype.validateEach = function(errors, record, key, callback) { var value; value = record.get(key); if (!this.isPresent(value)) { errors.add(key, this.format(key, 'blank')); } return callback(); }; PresenceValidator.prototype.isPresent = function(value) { return (value != null) && value !== ''; }; return PresenceValidator; })(Batman.Validator); Batman.Validators.push(Batman.PresenceValidator); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Batman.NumericValidator = (function(_super) { __extends(NumericValidator, _super); function NumericValidator() { return NumericValidator.__super__.constructor.apply(this, arguments); } NumericValidator.triggers('numeric', 'greaterThan', 'greaterThanOrEqualTo', 'equalTo', 'lessThan', 'lessThanOrEqualTo'); NumericValidator.options('allowBlank'); NumericValidator.prototype.validateEach = function(errors, record, key, callback) { var options, value; options = this.options; value = record.get(key); if (this.handleBlank(value)) { return callback(); } if (!(value != null) || !(this.isNumeric(value) || this.canCoerceToNumeric(value))) { errors.add(key, this.format(key, 'not_numeric')); } else { if (options.greaterThan && value <= options.greaterThan) { errors.add(key, this.format(key, 'greater_than', { count: options.greaterThan })); } if (options.greaterThanOrEqualTo && value < options.greaterThanOrEqualTo) { errors.add(key, this.format(key, 'greater_than_or_equal_to', { count: options.greaterThanOrEqualTo })); } if (options.equalTo && value !== options.equalTo) { errors.add(key, this.format(key, 'equal_to', { count: options.equalTo })); } if (options.lessThan && value >= options.lessThan) { errors.add(key, this.format(key, 'less_than', { count: options.lessThan })); } if (options.lessThanOrEqualTo && value > options.lessThanOrEqualTo) { errors.add(key, this.format(key, 'less_than_or_equal_to', { count: options.lessThanOrEqualTo })); } } return callback(); }; NumericValidator.prototype.isNumeric = function(value) { return !isNaN(parseFloat(value)) && isFinite(value); }; NumericValidator.prototype.canCoerceToNumeric = function(value) { return (value - 0) == value && value.length > 0; }; return NumericValidator; })(Batman.Validator); Batman.Validators.push(Batman.NumericValidator); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Batman.LengthValidator = (function(_super) { __extends(LengthValidator, _super); LengthValidator.triggers('minLength', 'maxLength', 'length', 'lengthWithin', 'lengthIn'); LengthValidator.options('allowBlank'); function LengthValidator(options) { var range; if (range = options.lengthIn || options.lengthWithin) { options.minLength = range[0]; options.maxLength = range[1] || -1; delete options.lengthWithin; delete options.lengthIn; } LengthValidator.__super__.constructor.apply(this, arguments); } LengthValidator.prototype.validateEach = function(errors, record, key, callback) { var options, value; options = this.options; value = record.get(key); if (value !== '' && this.handleBlank(value)) { return callback(); } if (value == null) { value = []; } if (options.minLength && value.length < options.minLength) { errors.add(key, this.format(key, 'too_short', { count: options.minLength })); } if (options.maxLength && value.length > options.maxLength) { errors.add(key, this.format(key, 'too_long', { count: options.maxLength })); } if (options.length && value.length !== options.length) { errors.add(key, this.format(key, 'wrong_length', { count: options.length })); } return callback(); }; return LengthValidator; })(Batman.Validator); Batman.Validators.push(Batman.LengthValidator); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Batman.AssociatedValidator = (function(_super) { __extends(AssociatedValidator, _super); function AssociatedValidator() { return AssociatedValidator.__super__.constructor.apply(this, arguments); } AssociatedValidator.triggers('associated'); AssociatedValidator.prototype.validateEach = function(errors, record, key, callback) { var childFinished, count, value, _this = this; value = record.get(key); if (value != null) { if (value instanceof Batman.AssociationProxy) { value = typeof value.get === "function" ? value.get('target') : void 0; } count = 1; childFinished = function(err, childErrors) { if (childErrors.length > 0) { errors.add(key, _this.format(key, 'invalid_association')); } if (--count === 0) { return callback(); } }; if ((value != null ? value.forEach : void 0) != null) { value.forEach(function(record) { count += 1; return record.validate(childFinished); }); } else if ((value != null ? value.validate : void 0) != null) { count += 1; value.validate(childFinished); } return childFinished(null, []); } else { return callback(); } }; return AssociatedValidator; })(Batman.Validator); Batman.Validators.push(Batman.AssociatedValidator); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Batman.ControllerActionFrame = (function(_super) { __extends(ControllerActionFrame, _super); ControllerActionFrame.prototype.operationOccurred = false; ControllerActionFrame.prototype.remainingOperations = 0; ControllerActionFrame.prototype.event('complete').oneShot = true; function ControllerActionFrame(options, onComplete) { ControllerActionFrame.__super__.constructor.call(this, options); this.once('complete', onComplete); } ControllerActionFrame.prototype.startOperation = function(options) { if (options == null) { options = {}; } if (!options.internal) { this.operationOccurred = true; } this._changeOperationsCounter(1); return true; }; ControllerActionFrame.prototype.finishOperation = function() { this._changeOperationsCounter(-1); return true; }; ControllerActionFrame.prototype.startAndFinishOperation = function(options) { this.startOperation(options); this.finishOperation(options); return true; }; ControllerActionFrame.prototype._changeOperationsCounter = function(delta) { var _ref; this.remainingOperations += delta; if (this.remainingOperations === 0) { this.fire('complete'); } if ((_ref = this.parentFrame) != null) { _ref._changeOperationsCounter(delta); } }; return ControllerActionFrame; })(Batman.Object); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Batman.DOM.InsertionBinding = (function(_super) { __extends(InsertionBinding, _super); InsertionBinding.prototype.isTwoWay = false; InsertionBinding.prototype.bindImmediately = false; InsertionBinding.prototype.onlyObserve = Batman.BindingDefinitionOnlyObserve.Data; function InsertionBinding(definition) { var _this = this; this.invert = definition.invert; this.placeholderNode = document.createComment("detached node " + (this.get('_batmanID'))); InsertionBinding.__super__.constructor.apply(this, arguments); Batman.DOM.onParseExit(this.node, function() { _this.bind(); if (_this.placeholderNode != null) { return Batman.DOM.trackBinding(_this, _this.placeholderNode); } }); } InsertionBinding.prototype.dataChange = function(value) { var parentNode; parentNode = this.placeholderNode.parentNode || this.node.parentNode; if ( !! value === !this.invert) { if (!(this.node.parentNode != null)) { Batman.DOM.insertBefore(parentNode, this.node, this.placeholderNode); return parentNode.removeChild(this.placeholderNode); } } else { if (this.node.parentNode != null) { parentNode.insertBefore(this.placeholderNode, this.node); return Batman.DOM.removeNode(this.node); } } }; InsertionBinding.prototype.die = function() { var filteredValue, node, placeholderNode; if (this.dead) { return; } node = this.node, placeholderNode = this.placeholderNode; filteredValue = this.get('filteredValue'); InsertionBinding.__super__.die.apply(this, arguments); if ( !! filteredValue === !this.invert) { return Batman.DOM.destroyNode(placeholderNode); } else { return Batman.DOM.destroyNode(node); } }; return InsertionBinding; })(Batman.DOM.AbstractBinding); }).call(this); (function() { var isEmptyDataObject; isEmptyDataObject = function(obj) { var name; for (name in obj) { return false; } return true; }; Batman.extend(Batman, { cache: {}, uuid: 0, expando: "batman" + Math.random().toString().replace(/\D/g, ''), canDeleteExpando: (function() { var div; try { div = document.createElement('div'); return delete div.test; } catch (e) { return Batman.canDeleteExpando = false; } })(), noData: { "embed": true, "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000", "applet": true }, hasData: function(elem) { elem = (elem.nodeType ? Batman.cache[elem[Batman.expando]] : elem[Batman.expando]); return !!elem && !isEmptyDataObject(elem); }, data: function(elem, name, data, pvt) { var cache, getByName, id, internalKey, ret, thisCache; if (!Batman.acceptData(elem)) { return; } internalKey = Batman.expando; getByName = typeof name === "string"; cache = Batman.cache; id = elem[Batman.expando]; if ((!id || (pvt && id && (cache[id] && !cache[id][internalKey]))) && getByName && data === void 0) { return; } if (!id) { if (elem.nodeType !== 3) { elem[Batman.expando] = id = ++Batman.uuid; } else { id = Batman.expando; } } if (!cache[id]) { cache[id] = {}; } if (typeof name === "object" || typeof name === "function") { if (pvt) { cache[id][internalKey] = Batman.extend(cache[id][internalKey], name); } else { cache[id] = Batman.extend(cache[id], name); } } thisCache = cache[id]; if (pvt) { thisCache[internalKey] || (thisCache[internalKey] = {}); thisCache = thisCache[internalKey]; } if (data !== void 0) { thisCache[name] = data; } if (getByName) { ret = thisCache[name]; } else { ret = thisCache; } return ret; }, removeData: function(elem, name, pvt) { var cache, id, internalCache, internalKey, isNode, thisCache; if (!Batman.acceptData(elem)) { return; } internalKey = Batman.expando; isNode = elem.nodeType; cache = Batman.cache; id = elem[Batman.expando]; if (!cache[id]) { return; } if (name) { thisCache = pvt ? cache[id][internalKey] : cache[id]; if (thisCache) { delete thisCache[name]; if (!isEmptyDataObject(thisCache)) { return; } } } if (pvt) { delete cache[id][internalKey]; if (!isEmptyDataObject(cache[id])) { return; } } internalCache = cache[id][internalKey]; if (Batman.canDeleteExpando || !cache.setInterval) { delete cache[id]; } else { cache[id] = null; } if (internalCache) { cache[id] = {}; return cache[id][internalKey] = internalCache; } else { if (Batman.canDeleteExpando) { return delete elem[Batman.expando]; } else if (elem.removeAttribute) { return elem.removeAttribute(Batman.expando); } else { return elem[Batman.expando] = null; } } }, _data: function(elem, name, data) { return Batman.data(elem, name, data, true); }, acceptData: function(elem) { var match; if (elem.nodeName) { match = Batman.noData[elem.nodeName.toLowerCase()]; if (match) { return !(match === true || elem.getAttribute("classid") !== match); } } return true; } }); }).call(this); (function() { var buntUndefined, defaultAndOr, __slice = [].slice; buntUndefined = function(f) { return function(value) { if (value == null) { return void 0; } else { return f.apply(this, arguments); } }; }; defaultAndOr = function(lhs, rhs) { return lhs || rhs; }; Batman.Filters = { raw: buntUndefined(function(value, binding) { binding.escapeValue = false; return value; }), get: buntUndefined(function(value, key) { if (value.get != null) { return value.get(key); } else { return value[key]; } }), equals: buntUndefined(function(lhs, rhs, binding) { return lhs === rhs; }), and: function(lhs, rhs) { return lhs && rhs; }, or: function(lhs, rhs, binding) { return lhs || rhs; }, not: function(value, binding) { return !value; }, trim: buntUndefined(function(value, binding) { return value.trim(); }), matches: buntUndefined(function(value, searchFor) { return value.indexOf(searchFor) !== -1; }), truncate: buntUndefined(function(value, length, end, binding) { if (end == null) { end = "..."; } if (!binding) { binding = end; end = "..."; } if (value.length > length) { value = value.substr(0, length - end.length) + end; } return value; }), "default": function(value, defaultValue, binding) { if ((value != null) && value !== '') { return value; } else { return defaultValue; } }, prepend: function(value, string, binding) { return (string != null ? string : '') + (value != null ? value : ''); }, append: function(value, string, binding) { return (value != null ? value : '') + (string != null ? string : ''); }, replace: buntUndefined(function(value, searchFor, replaceWith, flags, binding) { if (!binding) { binding = flags; flags = void 0; } if (flags === void 0) { return value.replace(searchFor, replaceWith); } else { return value.replace(searchFor, replaceWith, flags); } }), downcase: buntUndefined(function(value) { return value.toLowerCase(); }), upcase: buntUndefined(function(value) { return value.toUpperCase(); }), pluralize: buntUndefined(function(string, count, includeCount, binding) { if (!binding) { binding = includeCount; includeCount = true; if (!binding) { binding = count; count = void 0; } } if (count != null) { return Batman.helpers.pluralize(count, string, void 0, includeCount); } else { return Batman.helpers.pluralize(string); } }), humanize: buntUndefined(function(string, binding) { return Batman.helpers.humanize(string); }), join: buntUndefined(function(value, withWhat, binding) { if (withWhat == null) { withWhat = ''; } if (!binding) { binding = withWhat; withWhat = ''; } return value.join(withWhat); }), sort: buntUndefined(function(value) { return value.sort(); }), map: buntUndefined(function(value, key) { return value.map(function(x) { return Batman.get(x, key); }); }), has: function(set, item) { if (set == null) { return false; } return Batman.contains(set, item); }, first: buntUndefined(function(value) { return value[0]; }), meta: buntUndefined(function(value, keypath) { Batman.developer.assert(value.meta, "Error, value doesn't have a meta to filter on!"); return value.meta.get(keypath); }), interpolate: function(string, interpolationKeypaths, binding) { var k, v, values; if (!binding) { binding = interpolationKeypaths; interpolationKeypaths = void 0; } if (!string) { return; } values = {}; for (k in interpolationKeypaths) { v = interpolationKeypaths[k]; values[k] = this.get(v); if (!(values[k] != null)) { Batman.developer.warn("Warning! Undefined interpolation key " + k + " for interpolation", string); values[k] = ''; } } return Batman.helpers.interpolate(string, values); }, withArguments: function() { var binding, block, curryArgs, _i; block = arguments[0], curryArgs = 3 <= arguments.length ? __slice.call(arguments, 1, _i = arguments.length - 1) : (_i = 1, []), binding = arguments[_i++]; if (!block) { return; } return function() { var regularArgs; regularArgs = 1 <= arguments.length ? __slice.call(arguments, 0) : []; return block.call.apply(block, [this].concat(__slice.call(curryArgs), __slice.call(regularArgs))); }; }, routeToAction: buntUndefined(function(model, action) { var params; params = Batman.Dispatcher.paramsFromArgument(model); params.action = action; return params; }), escape: buntUndefined(Batman.escapeHTML) }; (function() { var k, _i, _len, _ref, _results; _ref = ['capitalize', 'singularize', 'underscore', 'camelize']; _results = []; for (_i = 0, _len = _ref.length; _i < _len; _i++) { k = _ref[_i]; _results.push(Batman.Filters[k] = buntUndefined(Batman.helpers[k])); } return _results; })(); Batman.developer.addFilters(); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Batman.RenderContext = (function() { var ContextProxy; RenderContext.deProxy = function(object) { if ((object != null) && object.isContextProxy) { return object.get('proxiedObject'); } else { return object; } }; RenderContext.root = function() { var root; if (Batman.currentApp != null) { root = Batman.currentApp.get('_renderContext'); } return root != null ? root : root = this.base; }; RenderContext.prototype.windowWrapper = { window: Batman.container }; function RenderContext(object, parent) { this.object = object; this.parent = parent; } RenderContext.prototype.findKey = function(key) { var base, currentNode, val; base = key.split('.')[0].split('|')[0].trim(); currentNode = this; while (currentNode) { val = Batman.get(currentNode.object, base); if (typeof val !== 'undefined') { val = Batman.get(currentNode.object, key); return [val, currentNode.object].map(this.constructor.deProxy); } currentNode = currentNode.parent; } return [Batman.get(this.windowWrapper, key), this.windowWrapper]; }; RenderContext.prototype.get = function(key) { return this.findKey(key)[0]; }; RenderContext.prototype.contextForKey = function(key) { return this.findKey(key)[1]; }; RenderContext.prototype.descend = function(object, scopedKey) { var oldObject; if (scopedKey) { oldObject = object; object = new Batman.Object(); object[scopedKey] = oldObject; } return new this.constructor(object, this); }; RenderContext.prototype.descendWithDefinition = function(definition) { var proxy; proxy = new ContextProxy(definition); return this.descend(proxy, definition.attr); }; RenderContext.prototype.chain = function() { var parent, x; x = []; parent = this; while (parent) { x.push(parent.object); parent = parent.parent; } return x; }; RenderContext.ContextProxy = ContextProxy = (function(_super) { __extends(ContextProxy, _super); ContextProxy.prototype.isContextProxy = true; ContextProxy.accessor('proxiedObject', function() { return this.binding.get('filteredValue'); }); ContextProxy.accessor({ get: function(key) { return this.get("proxiedObject." + key); }, set: function(key, value) { return this.set("proxiedObject." + key, value); }, unset: function(key) { return this.unset("proxiedObject." + key); } }); function ContextProxy(definition) { this.binding = new Batman.DOM.AbstractBinding(definition); } return ContextProxy; })(Batman.Object); return RenderContext; }).call(this); Batman.RenderContext.base = new Batman.RenderContext(Batman.RenderContext.prototype.windowWrapper); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Batman.ViewStore = (function(_super) { __extends(ViewStore, _super); function ViewStore() { ViewStore.__super__.constructor.apply(this, arguments); this._viewContents = {}; this._requestedPaths = new Batman.SimpleSet; } ViewStore.prototype.propertyClass = Batman.Property; ViewStore.prototype.fetchView = function(path) { var _this = this; return new Batman.Request({ url: Batman.Navigator.normalizePath(Batman.config.viewPrefix, "" + path + ".html"), type: 'html', success: function(response) { return _this.set(path, response); }, error: function(response) { throw new Error("Could not load view from " + path); } }); }; ViewStore.accessor({ 'final': true, get: function(path) { var contents; if (path.charAt(0) !== '/') { return this.get("/" + path); } if (this._viewContents[path]) { return this._viewContents[path]; } if (this._requestedPaths.has(path)) { return; } if (contents = this._sourceFromDOM(path)) { return contents; } if (Batman.config.fetchRemoteViews) { this.fetchView(path); } else { throw new Error("Couldn't find view source for \'" + path + "\'!"); } }, set: function(path, content) { if (path.charAt(0) !== '/') { return this.set("/" + path, content); } this._requestedPaths.add(path); return this._viewContents[path] = content; } }); ViewStore.prototype.prefetch = function(path) { this.get(path); return true; }; ViewStore.prototype._sourceFromDOM = function(path) { var node, relativePath; relativePath = path.slice(1); if (node = Batman.DOM.querySelector(document, "[data-defineview*='" + relativePath + "']")) { Batman.setImmediate(function() { var _ref; return (_ref = node.parentNode) != null ? _ref.removeChild(node) : void 0; }); return Batman.DOM.defineView(path, node); } }; return ViewStore; })(Batman.Object); }).call(this); (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, __slice = [].slice; Batman.View = (function(_super) { __extends(View, _super); View.YieldStorage = (function(_super1) { __extends(YieldStorage, _super1); function YieldStorage() { return YieldStorage.__super__.constructor.apply(this, arguments); } YieldStorage.wrapAccessor(function(core) { return { get: function(key) { var val; val = core.get.call(this, key); if (!(val != null)) { val = this.set(key, []); } return val; } }; }); return YieldStorage; })(Batman.Hash); View.store = new Batman.ViewStore(); View.option = function() { var keys; keys = 1 <= arguments.length ? __slice.call(arguments, 0) : []; return this.accessor.apply(this, __slice.call(keys).concat([{ get: function(key) { var _ref; return (_ref = this.get("argumentBindings." + key)) != null ? _ref.get('filteredValue') : void 0; }, set: function(key, value) { var _ref; return (_ref = this.get("argumentBindings." + key)) != null ? _ref.set('filteredValue', value) : void 0; }, unset: function(key) { var _ref; return (_ref = this.get("argumentBindings." + key)) != null ? _ref.unset('filteredValue') : void 0; } }])); }; View.prototype.isView = true; View.prototype.cache = true; View.prototype._rendered = false; View.prototype.node = null; View.prototype.event('ready').oneShot = true; View.accessor('argumentBindings', function() { var _this = this; return new Batman.TerminalAccessible(function(key) { var bindingKey, context, definition, keyPath, node, _ref; if (!((node = _this.get('node')) && (context = _this.get('context')))) { return; } keyPath = node.getAttribute(("data-view-" + key).toLowerCase()); if (keyPath == null) { return; } bindingKey = "_argumentBinding" + key; if ((_ref = _this[bindingKey]) != null) { _ref.die(); } definition = new Batman.DOM.ReaderBindingDefinition(node, keyPath, context); return _this[bindingKey] = new Batman.DOM.ViewArgumentBinding(definition); }); }); View.accessor('html', { get: function() { var source; if (this.html && this.html.length > 0) { return this.html; } if (!(source = this.get('source'))) { return; } source = Batman.Navigator.normalizePath(source); return this.html = this.constructor.store.get(source); }, set: function(_, html) { return this.html = html; } }); View.accessor('node', { get: function() { var html; if (this.node == null) { html = this.get('html'); if (!(html && html.length > 0)) { return; } this.node = document.createElement('div'); this._setNodeOwner(this.node); Batman.DOM.setInnerHTML(this.node, html); } return this.node; }, set: function(_, node) { var updateHTML, _this = this; this.node = node; this._setNodeOwner(node); updateHTML = function(html) { if (html != null) { Batman.DOM.setInnerHTML(_this.node, html); return _this.forget('html', updateHTML); } }; this.observeAndFire('html', updateHTML); return node; } }); View.accessor('yields', function() { return new this.constructor.YieldStorage; }); View.accessor('fetched?', function() { return this.get('source') != null; }); View.accessor('readyToRender', function() { var _ref; return this.get('node') && (this.get('fetched?') ? ((_ref = this.get('html')) != null ? _ref.length : void 0) > 0 : true); }); function View(options) { var context, _this = this; if (options == null) { options = {}; } context = options.context; if (context) { if (!(context instanceof Batman.RenderContext)) { context = Batman.RenderContext.root().descend(context); } } else { context = Batman.RenderContext.root(); } options.context = context.descend(this); View.__super__.constructor.call(this, options); Batman.Property.withoutTracking(function() { return _this.observeAndFire('readyToRender', function(ready) { if (ready) { return _this.render(); } }); }); } View.prototype.render = function() { var node, _this = this; if (this._rendered) { return; } this._rendered = true; this._renderer = new Batman.Renderer(node = this.get('node'), this.get('context'), this); return this._renderer.once('rendered', function() { return _this.fire('ready', node); }); }; View.prototype.isInDOM = function() { var node; if ((node = this.get('node'))) { return (node.parentNode != null) || this.get('yields').some(function(name, nodes) { var _i, _len; for (_i = 0, _len = nodes.length; _i < _len; _i++) { node = nodes[_i].node; if (node.parentNode != null) { return true; } } return false; }); } else { return false; } }; View.prototype.die = function() { var _ref; this.fire('destroy', this.node); this.forget(); if ((_ref = this._batman.properties) != null) { _ref.forEach(function(key, property) { return property.die(); }); } return this.get('yields').forEach(function(name, actions) { var node, _i, _len, _results; _results = []; for (_i = 0, _len = actions.length; _i < _len; _i++) { node = actions[_i].node; _results.push(Batman.DOM.didDestroyNode(node)); } return _results; }); }; View.prototype.applyYields = function() { return this.get('yields').forEach(function(name, nodes) { var action, node, yieldObject, _i, _len, _ref, _results; yieldObject = Batman.DOM.Yield.withName(name); _results = []; for (_i = 0, _len = nodes.length; _i < _len; _i++) { _ref = nodes[_i], node = _ref.node, action = _ref.action; _results.push(yieldObject[action](node)); } return _results; }); }; View.prototype.retractYields = function() { return this.get('yields').forEach(function(name, nodes) { var node, _i, _len, _ref, _results; _results = []; for (_i = 0, _len = nodes.length; _i < _len; _i++) { node = nodes[_i].node; _results.push((_ref = node.parentNode) != null ? _ref.removeChild(node) : void 0); } return _results; }); }; View.prototype.pushYieldAction = function(key, action, node) { this._setNodeYielder(node); return this.get("yields").get(key).push({ node: node, action: action }); }; View.prototype._setNodeOwner = function(node) { return Batman._data(node, 'view', this); }; View.prototype._setNodeYielder = function(node) { return Batman._data(node, 'yielder', this); }; View.prototype.on('ready', function() { return typeof this.ready === "function" ? this.ready.apply(this, arguments) : void 0; }); View.prototype.on('appear', function() { return typeof this.viewDidAppear === "function" ? this.viewDidAppear.apply(this, arguments) : void 0; }); View.prototype.on('disappear', function() { return typeof this.viewDidDisappear === "function" ? this.viewDidDisappear.apply(this, arguments) : void 0; }); View.prototype.on('beforeAppear', function() { return typeof this.viewWillAppear === "function" ? this.viewWillAppear.apply(this, arguments) : void 0; }); View.prototype.on('beforeDisappear', function() { return typeof this.viewWillDisappear === "function" ? this.viewWillDisappear.apply(this, arguments) : void 0; }); return View; }).call(this, Batman.Object); }).call(this); (function() { var Yield, __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, __slice = [].slice; Batman.DOM.Yield = Yield = (function(_super) { __extends(Yield, _super); Yield.yields = {}; Yield.queued = function(fn) { return function() { var args, handler, _this = this; args = 1 <= arguments.length ? __slice.call(arguments, 0) : []; if (this.containerNode != null) { return fn.apply(this, args); } else { return handler = this.observe('containerNode', function() { var result; result = fn.apply(_this, args); _this.forget('containerNode', handler); return result; }); } }; }; Yield.reset = function() { return this.yields = {}; }; Yield.withName = function(name) { var _base; (_base = this.yields)[name] || (_base[name] = new this({ name: name })); return this.yields[name]; }; Yield.forEach = function(f) { var name, yieldObject, _ref; _ref = this.yields; for (name in _ref) { yieldObject = _ref[name]; f(yieldObject); } }; Yield.clearAll = function() { return this.forEach(function(yieldObject) { return yieldObject.clear(); }); }; Yield.cycleAll = function() { return this.forEach(function(yieldObject) { return yieldObject.cycle(); }); }; Yield.clearAllStale = function() { return this.forEach(function(yieldObject) { return yieldObject.clearStale(); }); }; function Yield() { this.cycle(); } Yield.prototype.cycle = function() { return this.currentVersionNodes = []; }; Yield.prototype.clear = Yield.queued(function() { var child, _i, _len, _ref, _results; this.cycle(); _ref = (function() { var _j, _len, _ref, _results1; _ref = this.containerNode.childNodes; _results1 = []; for (_j = 0, _len = _ref.length; _j < _len; _j++) { child = _ref[_j]; _results1.push(child); } return _results1; }).call(this); _results = []; for (_i = 0, _len = _ref.length; _i < _len; _i++) { child = _ref[_i]; _results.push(Batman.DOM.removeOrDestroyNode(child)); } return _results; }); Yield.prototype.clearStale = Yield.queued(function() { var child, _i, _len, _ref, _results; _ref = (function() { var _j, _len, _ref, _results1; _ref = this.containerNode.childNodes; _results1 = []; for (_j = 0, _len = _ref.length; _j < _len; _j++) { child = _ref[_j]; _results1.push(child); } return _results1; }).call(this); _results = []; for (_i = 0, _len = _ref.length; _i < _len; _i++) { child = _ref[_i]; if (!~this.currentVersionNodes.indexOf(child)) { _results.push(Batman.DOM.removeOrDestroyNode(child)); } } return _results; }); Yield.prototype.append = Yield.queued(function(node) { this.currentVersionNodes.push(node); return Batman.DOM.appendChild(this.containerNode, node, true); }); Yield.prototype.replace = Yield.queued(function(node) { this.clear(); return this.append(node); }); return Yield; })(Batman.Object); }).call(this); (function() { }).call(this); ================================================ FILE: javascripts/dashing.coffee ================================================ #= require jquery #= require es5-shim #= require batman #= require batman.jquery Batman.Filters.prettyNumber = (num) -> num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") unless isNaN(num) Batman.Filters.dashize = (str) -> dashes_rx1 = /([A-Z]+)([A-Z][a-z])/g; dashes_rx2 = /([a-z\d])([A-Z])/g; return str.replace(dashes_rx1, '$1_$2').replace(dashes_rx2, '$1_$2').replace(/_/g, '-').toLowerCase() Batman.Filters.shortenedNumber = (num) -> return num if isNaN(num) if num >= 1000000000 (num / 1000000000).toFixed(1) + 'B' else if num >= 1000000 (num / 1000000).toFixed(1) + 'M' else if num >= 1000 (num / 1000).toFixed(1) + 'K' else num class window.Dashing extends Batman.App @on 'reload', (data) -> window.location.reload(true) @root -> Dashing.params = Batman.URI.paramsFromQuery(window.location.search.slice(1)); class Dashing.Widget extends Batman.View constructor: -> # Set the view path @constructor::source = Batman.Filters.underscore(@constructor.name) super @mixin($(@node).data()) Dashing.widgets[@id] ||= [] Dashing.widgets[@id].push(@) type = Batman.Filters.dashize(@view) $(@node).addClass("widget widget-#{type} #{@id}") @accessor 'updatedAtMessage', -> if updatedAt = @get('updatedAt') timestamp = new Date(updatedAt * 1000) hours = timestamp.getHours() minutes = ("0" + timestamp.getMinutes()).slice(-2) "Last updated at #{hours}:#{minutes}" @::on 'ready', -> Dashing.Widget.fire 'ready' # In case the events from the server came before the widget was rendered lastData = Dashing.lastEvents[@id] if lastData @mixin(lastData) @onData(lastData) receiveData: (data) => @mixin(data) @onData(data) onData: (data) => # Widgets override this to handle incoming data Dashing.AnimatedValue = get: Batman.Property.defaultAccessor.get set: (k, to) -> if !to? || isNaN(to) @[k] = to else timer = "interval_#{k}" num = if (!isNaN(@[k]) && @[k]?) then @[k] else 0 unless @[timer] || num == to to = parseFloat(to) num = parseFloat(num) up = to > num num_interval = Math.abs(num - to) / 90 @[timer] = setInterval => num = if up then Math.ceil(num+num_interval) else Math.floor(num-num_interval) if (up && num > to) || (!up && num < to) num = to clearInterval(@[timer]) @[timer] = null delete @[timer] @[k] = num @set k, to , 10 @[k] = num Dashing.widgets = widgets = {} Dashing.lastEvents = lastEvents = {} Dashing.debugMode = false source = new EventSource('events') source.addEventListener 'open', (e) -> console.log("Connection opened", e) source.addEventListener 'error', (e)-> console.log("Connection error", e) if (e.currentTarget.readyState == EventSource.CLOSED) console.log("Connection closed") setTimeout (-> window.location.reload() ), 5*60*1000 source.addEventListener 'message', (e) -> data = JSON.parse(e.data) if lastEvents[data.id]?.updatedAt != data.updatedAt if Dashing.debugMode console.log("Received data for #{data.id}", data) lastEvents[data.id] = data if widgets[data.id]?.length > 0 for widget in widgets[data.id] widget.receiveData(data) source.addEventListener 'dashboards', (e) -> data = JSON.parse(e.data) if Dashing.debugMode console.log("Received data for dashboards", data) if data.dashboard is '*' or window.location.pathname is "/#{data.dashboard}" Dashing.fire data.event, data $(document).ready -> Dashing.run() ================================================ FILE: javascripts/es5-shim.js ================================================ // vim: ts=4 sts=4 sw=4 expandtab // -- kriskowal Kris Kowal Copyright (C) 2009-2011 MIT License // -- tlrobinson Tom Robinson Copyright (C) 2009-2010 MIT License (Narwhal Project) // -- dantman Daniel Friesen Copyright (C) 2010 XXX TODO License or CLA // -- fschaefer Florian Schäfer Copyright (C) 2010 MIT License // -- Gozala Irakli Gozalishvili Copyright (C) 2010 MIT License // -- kitcambridge Kit Cambridge Copyright (C) 2011 MIT License // -- kossnocorp Sasha Koss XXX TODO License or CLA // -- bryanforbes Bryan Forbes XXX TODO License or CLA // -- killdream Quildreen Motta Copyright (C) 2011 MIT Licence // -- michaelficarra Michael Ficarra Copyright (C) 2011 3-clause BSD License // -- sharkbrainguy Gerard Paapu Copyright (C) 2011 MIT License // -- bbqsrc Brendan Molloy XXX TODO License or CLA // -- iwyg XXX TODO License or CLA // -- DomenicDenicola Domenic Denicola XXX TODO License or CLA // -- xavierm02 Montillet Xavier XXX TODO License or CLA // -- Raynos Raynos XXX TODO License or CLA // -- samsonjs Sami Samhuri XXX TODO License or CLA // -- rwldrn Rick Waldron Copyright (C) 2011 MIT License // -- lexer Alexey Zakharov XXX TODO License or CLA /*! Copyright (c) 2009, 280 North Inc. http://280north.com/ MIT License. http://github.com/280north/narwhal/blob/master/README.md */ // Module systems magic dance (function (definition) { // RequireJS if (typeof define == "function") { define(definition); // CommonJS and ") $ -> $('#save-gridster').leanModal() $('#save-gridster').click -> $('#save-gridster').slideUp() ================================================ FILE: templates/project/assets/javascripts/jquery.knob.js ================================================ /*!jQuery Knob*/ /** * Downward compatible, touchable dial * * Version: 1.2.0 (15/07/2012) * Requires: jQuery v1.7+ * * Copyright (c) 2012 Anthony Terrien * Under MIT and GPL licenses: * http://www.opensource.org/licenses/mit-license.php * http://www.gnu.org/licenses/gpl.html * * Thanks to vor, eskimoblood, spiffistan, FabrizioC */ $(function () { /** * Kontrol library */ "use strict"; /** * Definition of globals and core */ var k = {}, // kontrol max = Math.max, min = Math.min; k.c = {}; k.c.d = $(document); k.c.t = function (e) { return e.originalEvent.touches.length - 1; }; /** * Kontrol Object * * Definition of an abstract UI control * * Each concrete component must call this one. * * k.o.call(this); * */ k.o = function () { var s = this; this.o = null; // array of options this.$ = null; // jQuery wrapped element this.i = null; // mixed HTMLInputElement or array of HTMLInputElement this.g = null; // 2D graphics context for 'pre-rendering' this.v = null; // value ; mixed array or integer this.cv = null; // change value ; not commited value this.x = 0; // canvas x position this.y = 0; // canvas y position this.$c = null; // jQuery canvas element this.c = null; // rendered canvas context this.t = 0; // touches index this.isInit = false; this.fgColor = null; // main color this.pColor = null; // previous color this.dH = null; // draw hook this.cH = null; // change hook this.eH = null; // cancel hook this.rH = null; // release hook this.run = function () { var cf = function (e, conf) { var k; for (k in conf) { s.o[k] = conf[k]; } s.init(); s._configure() ._draw(); }; if(this.$.data('kontroled')) return; this.$.data('kontroled', true); this.extend(); this.o = $.extend( { // Config min : this.$.data('min') || 0, max : this.$.data('max') || 100, stopper : true, readOnly : this.$.data('readonly'), // UI cursor : (this.$.data('cursor') === true && 30) || this.$.data('cursor') || 0, thickness : this.$.data('thickness') || 0.35, width : this.$.data('width') || 200, height : this.$.data('height') || 200, displayInput : this.$.data('displayinput') == null || this.$.data('displayinput'), displayPrevious : this.$.data('displayprevious'), fgColor : this.$.data('fgcolor') || '#87CEEB', inline : false, // Hooks draw : null, // function () {} change : null, // function (value) {} cancel : null, // function () {} release : null // function (value) {} }, this.o ); // routing value if(this.$.is('fieldset')) { // fieldset = array of integer this.v = {}; this.i = this.$.find('input') this.i.each(function(k) { var $this = $(this); s.i[k] = $this; s.v[k] = $this.val(); $this.bind( 'change' , function () { var val = {}; val[k] = $this.val(); s.val(val); } ); }); this.$.find('legend').remove(); } else { // input = integer this.i = this.$; this.v = this.$.val(); (this.v == '') && (this.v = this.o.min); this.$.bind( 'change' , function () { s.val(s.$.val()); } ); } (!this.o.displayInput) && this.$.hide(); this.$c = $(''); this.c = this.$c[0].getContext("2d"); this.$ .wrap($('
')) .before(this.$c); if (this.v instanceof Object) { this.cv = {}; this.copy(this.v, this.cv); } else { this.cv = this.v; } this.$ .bind("configure", cf) .parent() .bind("configure", cf); this._listen() ._configure() ._xy() .init(); this.isInit = true; this._draw(); return this; }; this._draw = function () { // canvas pre-rendering var d = true, c = document.createElement('canvas'); c.width = s.o.width; c.height = s.o.height; s.g = c.getContext('2d'); s.clear(); s.dH && (d = s.dH()); (d !== false) && s.draw(); s.c.drawImage(c, 0, 0); c = null; }; this._touch = function (e) { var touchMove = function (e) { var v = s.xy2val( e.originalEvent.touches[s.t].pageX, e.originalEvent.touches[s.t].pageY ); if (v == s.cv) return; if ( s.cH && (s.cH(v) === false) ) return; s.change(v); s._draw(); }; // get touches index this.t = k.c.t(e); // First touch touchMove(e); // Touch events listeners k.c.d .bind("touchmove.k", touchMove) .bind( "touchend.k" , function () { k.c.d.unbind('touchmove.k touchend.k'); if ( s.rH && (s.rH(s.cv) === false) ) return; s.val(s.cv); } ); return this; }; this._mouse = function (e) { var mouseMove = function (e) { var v = s.xy2val(e.pageX, e.pageY); if (v == s.cv) return; if ( s.cH && (s.cH(v) === false) ) return; s.change(v); s._draw(); }; // First click mouseMove(e); // Mouse events listeners k.c.d .bind("mousemove.k", mouseMove) .bind( // Escape key cancel current change "keyup.k" , function (e) { if (e.keyCode === 27) { k.c.d.unbind("mouseup.k mousemove.k keyup.k"); if ( s.eH && (s.eH() === false) ) return; s.cancel(); } } ) .bind( "mouseup.k" , function (e) { k.c.d.unbind('mousemove.k mouseup.k keyup.k'); if ( s.rH && (s.rH(s.cv) === false) ) return; s.val(s.cv); } ); return this; }; this._xy = function () { var o = this.$c.offset(); this.x = o.left; this.y = o.top; return this; }; this._listen = function () { if (!this.o.readOnly) { this.$c .bind( "mousedown" , function (e) { e.preventDefault(); s._xy()._mouse(e); } ) .bind( "touchstart" , function (e) { e.preventDefault(); s._xy()._touch(e); } ); this.listen(); } else { this.$.attr('readonly', 'readonly'); } return this; }; this._configure = function () { // Hooks if (this.o.draw) this.dH = this.o.draw; if (this.o.change) this.cH = this.o.change; if (this.o.cancel) this.eH = this.o.cancel; if (this.o.release) this.rH = this.o.release; if (this.o.displayPrevious) { this.pColor = this.h2rgba(this.o.fgColor, "0.4"); this.fgColor = this.h2rgba(this.o.fgColor, "0.6"); } else { this.fgColor = this.o.fgColor; } return this; }; this._clear = function () { this.$c[0].width = this.$c[0].width; }; // Abstract methods this.listen = function () {}; // on start, one time this.extend = function () {}; // each time configure triggered this.init = function () {}; // each time configure triggered this.change = function (v) {}; // on change this.val = function (v) {}; // on release this.xy2val = function (x, y) {}; // this.draw = function () {}; // on change / on release this.clear = function () { this._clear(); }; // Utils this.h2rgba = function (h, a) { var rgb; h = h.substring(1,7) rgb = [parseInt(h.substring(0,2),16) ,parseInt(h.substring(2,4),16) ,parseInt(h.substring(4,6),16)]; return "rgba(" + rgb[0] + "," + rgb[1] + "," + rgb[2] + "," + a + ")"; }; this.copy = function (f, t) { for (var i in f) { t[i] = f[i]; } }; }; /** * k.Dial */ k.Dial = function () { k.o.call(this); this.startAngle = null; this.xy = null; this.radius = null; this.lineWidth = null; this.cursorExt = null; this.w2 = null; this.PI2 = 2*Math.PI; this.extend = function () { this.o = $.extend( { bgColor : this.$.data('bgcolor') || '#EEEEEE', angleOffset : this.$.data('angleoffset') || 0, angleArc : this.$.data('anglearc') || 360, inline : true }, this.o ); }; this.val = function (v) { if (null != v) { this.cv = this.o.stopper ? max(min(v, this.o.max), this.o.min) : v; this.v = this.cv; this.$.val(this.v); this._draw(); } else { return this.v; } }; this.xy2val = function (x, y) { var a, ret; a = Math.atan2( x - (this.x + this.w2) , - (y - this.y - this.w2) ) - this.angleOffset; if(this.angleArc != this.PI2 && (a < 0) && (a > -0.5)) { // if isset angleArc option, set to min if .5 under min a = 0; } else if (a < 0) { a += this.PI2; } ret = ~~ (0.5 + (a * (this.o.max - this.o.min) / this.angleArc)) + this.o.min; this.o.stopper && (ret = max(min(ret, this.o.max), this.o.min)); return ret; }; this.listen = function () { // bind MouseWheel var s = this, mw = function (e) { e.preventDefault(); var ori = e.originalEvent ,deltaX = ori.detail || ori.wheelDeltaX ,deltaY = ori.detail || ori.wheelDeltaY ,v = parseInt(s.$.val()) + (deltaX>0 || deltaY>0 ? 1 : deltaX<0 || deltaY<0 ? -1 : 0); if ( s.cH && (s.cH(v) === false) ) return; s.val(v); } , kval, to, m = 1, kv = {37:-1, 38:1, 39:1, 40:-1}; this.$ .bind( "keydown" ,function (e) { var kc = e.keyCode; kval = parseInt(String.fromCharCode(kc)); if (isNaN(kval)) { (kc !== 13) // enter && (kc !== 8) // bs && (kc !== 9) // tab && (kc !== 189) // - && e.preventDefault(); // arrows if ($.inArray(kc,[37,38,39,40]) > -1) { e.preventDefault(); var v = parseInt(s.$.val()) + kv[kc] * m; s.o.stopper && (v = max(min(v, s.o.max), s.o.min)); s.change(v); s._draw(); // long time keydown speed-up to = window.setTimeout( function () { m*=2; } ,30 ); } } } ) .bind( "keyup" ,function (e) { if (isNaN(kval)) { if (to) { window.clearTimeout(to); to = null; m = 1; s.val(s.$.val()); } } else { // kval postcond (s.$.val() > s.o.max && s.$.val(s.o.max)) || (s.$.val() < s.o.min && s.$.val(s.o.min)); } } ); this.$c.bind("mousewheel DOMMouseScroll", mw); this.$.bind("mousewheel DOMMouseScroll", mw) }; this.init = function () { if ( this.v < this.o.min || this.v > this.o.max ) this.v = this.o.min; this.$.val(this.v); this.w2 = this.o.width / 2; this.cursorExt = this.o.cursor / 100; this.xy = this.w2; this.lineWidth = this.xy * this.o.thickness; this.radius = this.xy - this.lineWidth / 2; this.o.angleOffset && (this.o.angleOffset = isNaN(this.o.angleOffset) ? 0 : this.o.angleOffset); this.o.angleArc && (this.o.angleArc = isNaN(this.o.angleArc) ? this.PI2 : this.o.angleArc); // deg to rad this.angleOffset = this.o.angleOffset * Math.PI / 180; this.angleArc = this.o.angleArc * Math.PI / 180; // compute start and end angles this.startAngle = 1.5 * Math.PI + this.angleOffset; this.endAngle = 1.5 * Math.PI + this.angleOffset + this.angleArc; var s = max( String(Math.abs(this.o.max)).length , String(Math.abs(this.o.min)).length , 2 ) + 2; this.o.displayInput && this.i.css({ 'width' : ((this.o.width / 2 + 4) >> 0) + 'px' ,'height' : ((this.o.width / 3) >> 0) + 'px' ,'position' : 'absolute' ,'vertical-align' : 'middle' ,'margin-top' : ((this.o.width / 3) >> 0) + 'px' ,'margin-left' : '-' + ((this.o.width * 3 / 4 + 2) >> 0) + 'px' ,'border' : 0 ,'background' : 'none' ,'font' : 'bold ' + ((this.o.width / s) >> 0) + 'px Arial' ,'text-align' : 'center' ,'color' : this.o.fgColor ,'padding' : '0px' ,'-webkit-appearance': 'none' }) || this.i.css({ 'width' : '0px' ,'visibility' : 'hidden' }); }; this.change = function (v) { this.cv = v; this.$.val(v); }; this.angle = function (v) { return (v - this.o.min) * this.angleArc / (this.o.max - this.o.min); }; this.draw = function () { var c = this.g, // context a = this.angle(this.cv) // Angle , sat = this.startAngle // Start angle , eat = sat + a // End angle , sa, ea // Previous angles , r = 1; c.lineWidth = this.lineWidth; this.o.cursor && (sat = eat - this.cursorExt) && (eat = eat + this.cursorExt); c.beginPath(); c.strokeStyle = this.o.bgColor; c.arc(this.xy, this.xy, this.radius, this.endAngle, this.startAngle, true); c.stroke(); if (this.o.displayPrevious) { ea = this.startAngle + this.angle(this.v); sa = this.startAngle; this.o.cursor && (sa = ea - this.cursorExt) && (ea = ea + this.cursorExt); c.beginPath(); c.strokeStyle = this.pColor; c.arc(this.xy, this.xy, this.radius, sa, ea, false); c.stroke(); r = (this.cv == this.v); } c.beginPath(); c.strokeStyle = r ? this.o.fgColor : this.fgColor ; c.arc(this.xy, this.xy, this.radius, sat, eat, false); c.stroke(); }; this.cancel = function () { this.val(this.v); }; }; $.fn.dial = $.fn.knob = function (o) { return this.each( function () { var d = new k.Dial(); d.o = o; d.$ = $(this); d.run(); } ).parent(); }; }); ================================================ FILE: templates/project/assets/stylesheets/application.scss ================================================ /* //=require_directory . //=require_tree ../../widgets */ // ---------------------------------------------------------------------------- // Sass declarations // ---------------------------------------------------------------------------- $background-color: #222; $text-color: #fff; $background-warning-color-1: #e82711; $background-warning-color-2: #9b2d23; $text-warning-color: #fff; $background-danger-color-1: #eeae32; $background-danger-color-2: #ff9618; $text-danger-color: #fff; @-webkit-keyframes status-warning-background { 0% { background-color: $background-warning-color-1; } 50% { background-color: $background-warning-color-2; } 100% { background-color: $background-warning-color-1; } } @-webkit-keyframes status-danger-background { 0% { background-color: $background-danger-color-1; } 50% { background-color: $background-danger-color-2; } 100% { background-color: $background-danger-color-1; } } @mixin animation($animation-name, $duration, $function, $animation-iteration-count:""){ -webkit-animation: $animation-name $duration $function #{$animation-iteration-count}; -moz-animation: $animation-name $duration $function #{$animation-iteration-count}; -ms-animation: $animation-name $duration $function #{$animation-iteration-count}; } // ---------------------------------------------------------------------------- // Base styles // ---------------------------------------------------------------------------- html { font-size: 100%; -webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; } body { margin: 0; background-color: $background-color; font-size: 20px; color: $text-color; font-family: 'Open Sans', "Helvetica Neue", Helvetica, Arial, sans-serif; } b, strong { font-weight: bold; } a { text-decoration: none; color: inherit; } img { border: 0; -ms-interpolation-mode: bicubic; vertical-align: middle; } img, object { max-width: 100%; } iframe { max-width: 100%; } table { border-collapse: collapse; border-spacing: 0; width: 100%; } td { vertical-align: middle; } ul, ol { padding: 0; margin: 0; } h1, h2, h3, h4, h5, p { padding: 0; margin: 0; } h1 { margin-bottom: 12px; text-align: center; font-size: 30px; font-weight: 400; } h2 { text-transform: uppercase; font-size: 76px; font-weight: 700; color: $text-color; } h3 { font-size: 25px; font-weight: 600; color: $text-color; } // ---------------------------------------------------------------------------- // Base widget styles // ---------------------------------------------------------------------------- .gridster { margin: 0px auto; } .icon-background { pointer-events: none; width: 100%!important; height: 100%; position: absolute; left: 0; top: 0; opacity: 0.1; font-size: 275px; text-align: center; margin-top: 82px; } .list-nostyle { list-style: none; } .gridster ul { list-style: none; } .gs_w { width: 100%; display: table; cursor: pointer; } .widget { text-align: center; width: inherit; height: inherit; display: table-cell; vertical-align: middle; } .widget.status-warning { background-color: $background-warning-color-1; @include animation(status-warning-background, 2s, ease, infinite); .icon-warning-sign { display: inline-block; } .title, .more-info { color: $text-warning-color; } } .widget.status-danger { color: $text-danger-color; background-color: $background-danger-color-1; @include animation(status-danger-background, 2s, ease, infinite); .icon-warning-sign { display: inline-block; } .title, .more-info { color: $text-danger-color; } } .more-info { font-size: 15px; position: absolute; bottom: 32px; left: 0; right: 0; } .updated-at { font-size: 15px; position: absolute; bottom: 12px; left: 0; right: 0; } #save-gridster { display: none; position: fixed; top: 0; margin: 0px auto; left: 50%; z-index: 1000; background: black; width: 190px; text-align: center; border: 1px solid white; border-top: 0px; margin-left: -95px; padding: 15px; } #save-gridster:hover { padding-top: 25px; } #saving-instructions { display: none; padding: 10px; width: 500px; height: 122px; z-index: 1000; background: white; top: 100px; color: black; font-size: 15px; padding-bottom: 4px; textarea { white-space: nowrap; width: 494px; height: 80px; } } #lean_overlay { position: fixed; z-index:100; top: 0px; left: 0px; height:100%; width:100%; background: #000; display: none; } #container { padding-top: 5px; } // ---------------------------------------------------------------------------- // Clearfix // ---------------------------------------------------------------------------- .clearfix:before, .clearfix:after { content: "\0020"; display: block; height: 0; overflow: hidden; } .clearfix:after { clear: both; } .clearfix { zoom: 1; } ================================================ FILE: templates/project/assets/stylesheets/font-awesome.css ================================================ /*! * Font Awesome 4.5.0 by @davegandy - http://fontawesome.io - @fontawesome * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) */ /* FONT PATH * -------------------------- */ @font-face { font-family: 'FontAwesome'; src: url('../assets/fontawesome-webfont.eot?v=4.5.0'); src: url('../assets/fontawesome-webfont.eot?#iefix&v=4.5.0') format('embedded-opentype'), url('../assets/fontawesome-webfont.woff2?v=4.5.0') format('woff2'), url('../assets/fontawesome-webfont.woff?v=4.5.0') format('woff'), url('../assets/fontawesome-webfont.ttf?v=4.5.0') format('truetype'), url('../assets/fontawesome-webfont.svg?v=4.5.0#fontawesomeregular') format('svg'); font-weight: normal; font-style: normal; } .fa { display: inline-block; font: normal normal normal 14px/1 FontAwesome; font-size: inherit; text-rendering: auto; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } /* makes the font 33% larger relative to the icon container */ .fa-lg { font-size: 1.33333333em; line-height: 0.75em; vertical-align: -15%; } .fa-2x { font-size: 2em; } .fa-3x { font-size: 3em; } .fa-4x { font-size: 4em; } .fa-5x { font-size: 5em; } .fa-fw { width: 1.28571429em; text-align: center; } .fa-ul { padding-left: 0; margin-left: 2.14285714em; list-style-type: none; } .fa-ul > li { position: relative; } .fa-li { position: absolute; left: -2.14285714em; width: 2.14285714em; top: 0.14285714em; text-align: center; } .fa-li.fa-lg { left: -1.85714286em; } .fa-border { padding: .2em .25em .15em; border: solid 0.08em #eeeeee; border-radius: .1em; } .fa-pull-left { float: left; } .fa-pull-right { float: right; } .fa.fa-pull-left { margin-right: .3em; } .fa.fa-pull-right { margin-left: .3em; } /* Deprecated as of 4.4.0 */ .pull-right { float: right; } .pull-left { float: left; } .fa.pull-left { margin-right: .3em; } .fa.pull-right { margin-left: .3em; } .fa-spin { -webkit-animation: fa-spin 2s infinite linear; animation: fa-spin 2s infinite linear; } .fa-pulse { -webkit-animation: fa-spin 1s infinite steps(8); animation: fa-spin 1s infinite steps(8); } @-webkit-keyframes fa-spin { 0% { -webkit-transform: rotate(0deg); transform: rotate(0deg); } 100% { -webkit-transform: rotate(359deg); transform: rotate(359deg); } } @keyframes fa-spin { 0% { -webkit-transform: rotate(0deg); transform: rotate(0deg); } 100% { -webkit-transform: rotate(359deg); transform: rotate(359deg); } } .fa-rotate-90 { filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=1); -webkit-transform: rotate(90deg); -ms-transform: rotate(90deg); transform: rotate(90deg); } .fa-rotate-180 { filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2); -webkit-transform: rotate(180deg); -ms-transform: rotate(180deg); transform: rotate(180deg); } .fa-rotate-270 { filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=3); -webkit-transform: rotate(270deg); -ms-transform: rotate(270deg); transform: rotate(270deg); } .fa-flip-horizontal { filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1); -webkit-transform: scale(-1, 1); -ms-transform: scale(-1, 1); transform: scale(-1, 1); } .fa-flip-vertical { filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1); -webkit-transform: scale(1, -1); -ms-transform: scale(1, -1); transform: scale(1, -1); } :root .fa-rotate-90, :root .fa-rotate-180, :root .fa-rotate-270, :root .fa-flip-horizontal, :root .fa-flip-vertical { filter: none; } .fa-stack { position: relative; display: inline-block; width: 2em; height: 2em; line-height: 2em; vertical-align: middle; } .fa-stack-1x, .fa-stack-2x { position: absolute; left: 0; width: 100%; text-align: center; } .fa-stack-1x { line-height: inherit; } .fa-stack-2x { font-size: 2em; } .fa-inverse { color: #ffffff; } /* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen readers do not read off random characters that represent icons */ .fa-glass:before { content: "\f000"; } .fa-music:before { content: "\f001"; } .fa-search:before { content: "\f002"; } .fa-envelope-o:before { content: "\f003"; } .fa-heart:before { content: "\f004"; } .fa-star:before { content: "\f005"; } .fa-star-o:before { content: "\f006"; } .fa-user:before { content: "\f007"; } .fa-film:before { content: "\f008"; } .fa-th-large:before { content: "\f009"; } .fa-th:before { content: "\f00a"; } .fa-th-list:before { content: "\f00b"; } .fa-check:before { content: "\f00c"; } .fa-remove:before, .fa-close:before, .fa-times:before { content: "\f00d"; } .fa-search-plus:before { content: "\f00e"; } .fa-search-minus:before { content: "\f010"; } .fa-power-off:before { content: "\f011"; } .fa-signal:before { content: "\f012"; } .fa-gear:before, .fa-cog:before { content: "\f013"; } .fa-trash-o:before { content: "\f014"; } .fa-home:before { content: "\f015"; } .fa-file-o:before { content: "\f016"; } .fa-clock-o:before { content: "\f017"; } .fa-road:before { content: "\f018"; } .fa-download:before { content: "\f019"; } .fa-arrow-circle-o-down:before { content: "\f01a"; } .fa-arrow-circle-o-up:before { content: "\f01b"; } .fa-inbox:before { content: "\f01c"; } .fa-play-circle-o:before { content: "\f01d"; } .fa-rotate-right:before, .fa-repeat:before { content: "\f01e"; } .fa-refresh:before { content: "\f021"; } .fa-list-alt:before { content: "\f022"; } .fa-lock:before { content: "\f023"; } .fa-flag:before { content: "\f024"; } .fa-headphones:before { content: "\f025"; } .fa-volume-off:before { content: "\f026"; } .fa-volume-down:before { content: "\f027"; } .fa-volume-up:before { content: "\f028"; } .fa-qrcode:before { content: "\f029"; } .fa-barcode:before { content: "\f02a"; } .fa-tag:before { content: "\f02b"; } .fa-tags:before { content: "\f02c"; } .fa-book:before { content: "\f02d"; } .fa-bookmark:before { content: "\f02e"; } .fa-print:before { content: "\f02f"; } .fa-camera:before { content: "\f030"; } .fa-font:before { content: "\f031"; } .fa-bold:before { content: "\f032"; } .fa-italic:before { content: "\f033"; } .fa-text-height:before { content: "\f034"; } .fa-text-width:before { content: "\f035"; } .fa-align-left:before { content: "\f036"; } .fa-align-center:before { content: "\f037"; } .fa-align-right:before { content: "\f038"; } .fa-align-justify:before { content: "\f039"; } .fa-list:before { content: "\f03a"; } .fa-dedent:before, .fa-outdent:before { content: "\f03b"; } .fa-indent:before { content: "\f03c"; } .fa-video-camera:before { content: "\f03d"; } .fa-photo:before, .fa-image:before, .fa-picture-o:before { content: "\f03e"; } .fa-pencil:before { content: "\f040"; } .fa-map-marker:before { content: "\f041"; } .fa-adjust:before { content: "\f042"; } .fa-tint:before { content: "\f043"; } .fa-edit:before, .fa-pencil-square-o:before { content: "\f044"; } .fa-share-square-o:before { content: "\f045"; } .fa-check-square-o:before { content: "\f046"; } .fa-arrows:before { content: "\f047"; } .fa-step-backward:before { content: "\f048"; } .fa-fast-backward:before { content: "\f049"; } .fa-backward:before { content: "\f04a"; } .fa-play:before { content: "\f04b"; } .fa-pause:before { content: "\f04c"; } .fa-stop:before { content: "\f04d"; } .fa-forward:before { content: "\f04e"; } .fa-fast-forward:before { content: "\f050"; } .fa-step-forward:before { content: "\f051"; } .fa-eject:before { content: "\f052"; } .fa-chevron-left:before { content: "\f053"; } .fa-chevron-right:before { content: "\f054"; } .fa-plus-circle:before { content: "\f055"; } .fa-minus-circle:before { content: "\f056"; } .fa-times-circle:before { content: "\f057"; } .fa-check-circle:before { content: "\f058"; } .fa-question-circle:before { content: "\f059"; } .fa-info-circle:before { content: "\f05a"; } .fa-crosshairs:before { content: "\f05b"; } .fa-times-circle-o:before { content: "\f05c"; } .fa-check-circle-o:before { content: "\f05d"; } .fa-ban:before { content: "\f05e"; } .fa-arrow-left:before { content: "\f060"; } .fa-arrow-right:before { content: "\f061"; } .fa-arrow-up:before { content: "\f062"; } .fa-arrow-down:before { content: "\f063"; } .fa-mail-forward:before, .fa-share:before { content: "\f064"; } .fa-expand:before { content: "\f065"; } .fa-compress:before { content: "\f066"; } .fa-plus:before { content: "\f067"; } .fa-minus:before { content: "\f068"; } .fa-asterisk:before { content: "\f069"; } .fa-exclamation-circle:before { content: "\f06a"; } .fa-gift:before { content: "\f06b"; } .fa-leaf:before { content: "\f06c"; } .fa-fire:before { content: "\f06d"; } .fa-eye:before { content: "\f06e"; } .fa-eye-slash:before { content: "\f070"; } .fa-warning:before, .fa-exclamation-triangle:before { content: "\f071"; } .fa-plane:before { content: "\f072"; } .fa-calendar:before { content: "\f073"; } .fa-random:before { content: "\f074"; } .fa-comment:before { content: "\f075"; } .fa-magnet:before { content: "\f076"; } .fa-chevron-up:before { content: "\f077"; } .fa-chevron-down:before { content: "\f078"; } .fa-retweet:before { content: "\f079"; } .fa-shopping-cart:before { content: "\f07a"; } .fa-folder:before { content: "\f07b"; } .fa-folder-open:before { content: "\f07c"; } .fa-arrows-v:before { content: "\f07d"; } .fa-arrows-h:before { content: "\f07e"; } .fa-bar-chart-o:before, .fa-bar-chart:before { content: "\f080"; } .fa-twitter-square:before { content: "\f081"; } .fa-facebook-square:before { content: "\f082"; } .fa-camera-retro:before { content: "\f083"; } .fa-key:before { content: "\f084"; } .fa-gears:before, .fa-cogs:before { content: "\f085"; } .fa-comments:before { content: "\f086"; } .fa-thumbs-o-up:before { content: "\f087"; } .fa-thumbs-o-down:before { content: "\f088"; } .fa-star-half:before { content: "\f089"; } .fa-heart-o:before { content: "\f08a"; } .fa-sign-out:before { content: "\f08b"; } .fa-linkedin-square:before { content: "\f08c"; } .fa-thumb-tack:before { content: "\f08d"; } .fa-external-link:before { content: "\f08e"; } .fa-sign-in:before { content: "\f090"; } .fa-trophy:before { content: "\f091"; } .fa-github-square:before { content: "\f092"; } .fa-upload:before { content: "\f093"; } .fa-lemon-o:before { content: "\f094"; } .fa-phone:before { content: "\f095"; } .fa-square-o:before { content: "\f096"; } .fa-bookmark-o:before { content: "\f097"; } .fa-phone-square:before { content: "\f098"; } .fa-twitter:before { content: "\f099"; } .fa-facebook-f:before, .fa-facebook:before { content: "\f09a"; } .fa-github:before { content: "\f09b"; } .fa-unlock:before { content: "\f09c"; } .fa-credit-card:before { content: "\f09d"; } .fa-feed:before, .fa-rss:before { content: "\f09e"; } .fa-hdd-o:before { content: "\f0a0"; } .fa-bullhorn:before { content: "\f0a1"; } .fa-bell:before { content: "\f0f3"; } .fa-certificate:before { content: "\f0a3"; } .fa-hand-o-right:before { content: "\f0a4"; } .fa-hand-o-left:before { content: "\f0a5"; } .fa-hand-o-up:before { content: "\f0a6"; } .fa-hand-o-down:before { content: "\f0a7"; } .fa-arrow-circle-left:before { content: "\f0a8"; } .fa-arrow-circle-right:before { content: "\f0a9"; } .fa-arrow-circle-up:before { content: "\f0aa"; } .fa-arrow-circle-down:before { content: "\f0ab"; } .fa-globe:before { content: "\f0ac"; } .fa-wrench:before { content: "\f0ad"; } .fa-tasks:before { content: "\f0ae"; } .fa-filter:before { content: "\f0b0"; } .fa-briefcase:before { content: "\f0b1"; } .fa-arrows-alt:before { content: "\f0b2"; } .fa-group:before, .fa-users:before { content: "\f0c0"; } .fa-chain:before, .fa-link:before { content: "\f0c1"; } .fa-cloud:before { content: "\f0c2"; } .fa-flask:before { content: "\f0c3"; } .fa-cut:before, .fa-scissors:before { content: "\f0c4"; } .fa-copy:before, .fa-files-o:before { content: "\f0c5"; } .fa-paperclip:before { content: "\f0c6"; } .fa-save:before, .fa-floppy-o:before { content: "\f0c7"; } .fa-square:before { content: "\f0c8"; } .fa-navicon:before, .fa-reorder:before, .fa-bars:before { content: "\f0c9"; } .fa-list-ul:before { content: "\f0ca"; } .fa-list-ol:before { content: "\f0cb"; } .fa-strikethrough:before { content: "\f0cc"; } .fa-underline:before { content: "\f0cd"; } .fa-table:before { content: "\f0ce"; } .fa-magic:before { content: "\f0d0"; } .fa-truck:before { content: "\f0d1"; } .fa-pinterest:before { content: "\f0d2"; } .fa-pinterest-square:before { content: "\f0d3"; } .fa-google-plus-square:before { content: "\f0d4"; } .fa-google-plus:before { content: "\f0d5"; } .fa-money:before { content: "\f0d6"; } .fa-caret-down:before { content: "\f0d7"; } .fa-caret-up:before { content: "\f0d8"; } .fa-caret-left:before { content: "\f0d9"; } .fa-caret-right:before { content: "\f0da"; } .fa-columns:before { content: "\f0db"; } .fa-unsorted:before, .fa-sort:before { content: "\f0dc"; } .fa-sort-down:before, .fa-sort-desc:before { content: "\f0dd"; } .fa-sort-up:before, .fa-sort-asc:before { content: "\f0de"; } .fa-envelope:before { content: "\f0e0"; } .fa-linkedin:before { content: "\f0e1"; } .fa-rotate-left:before, .fa-undo:before { content: "\f0e2"; } .fa-legal:before, .fa-gavel:before { content: "\f0e3"; } .fa-dashboard:before, .fa-tachometer:before { content: "\f0e4"; } .fa-comment-o:before { content: "\f0e5"; } .fa-comments-o:before { content: "\f0e6"; } .fa-flash:before, .fa-bolt:before { content: "\f0e7"; } .fa-sitemap:before { content: "\f0e8"; } .fa-umbrella:before { content: "\f0e9"; } .fa-paste:before, .fa-clipboard:before { content: "\f0ea"; } .fa-lightbulb-o:before { content: "\f0eb"; } .fa-exchange:before { content: "\f0ec"; } .fa-cloud-download:before { content: "\f0ed"; } .fa-cloud-upload:before { content: "\f0ee"; } .fa-user-md:before { content: "\f0f0"; } .fa-stethoscope:before { content: "\f0f1"; } .fa-suitcase:before { content: "\f0f2"; } .fa-bell-o:before { content: "\f0a2"; } .fa-coffee:before { content: "\f0f4"; } .fa-cutlery:before { content: "\f0f5"; } .fa-file-text-o:before { content: "\f0f6"; } .fa-building-o:before { content: "\f0f7"; } .fa-hospital-o:before { content: "\f0f8"; } .fa-ambulance:before { content: "\f0f9"; } .fa-medkit:before { content: "\f0fa"; } .fa-fighter-jet:before { content: "\f0fb"; } .fa-beer:before { content: "\f0fc"; } .fa-h-square:before { content: "\f0fd"; } .fa-plus-square:before { content: "\f0fe"; } .fa-angle-double-left:before { content: "\f100"; } .fa-angle-double-right:before { content: "\f101"; } .fa-angle-double-up:before { content: "\f102"; } .fa-angle-double-down:before { content: "\f103"; } .fa-angle-left:before { content: "\f104"; } .fa-angle-right:before { content: "\f105"; } .fa-angle-up:before { content: "\f106"; } .fa-angle-down:before { content: "\f107"; } .fa-desktop:before { content: "\f108"; } .fa-laptop:before { content: "\f109"; } .fa-tablet:before { content: "\f10a"; } .fa-mobile-phone:before, .fa-mobile:before { content: "\f10b"; } .fa-circle-o:before { content: "\f10c"; } .fa-quote-left:before { content: "\f10d"; } .fa-quote-right:before { content: "\f10e"; } .fa-spinner:before { content: "\f110"; } .fa-circle:before { content: "\f111"; } .fa-mail-reply:before, .fa-reply:before { content: "\f112"; } .fa-github-alt:before { content: "\f113"; } .fa-folder-o:before { content: "\f114"; } .fa-folder-open-o:before { content: "\f115"; } .fa-smile-o:before { content: "\f118"; } .fa-frown-o:before { content: "\f119"; } .fa-meh-o:before { content: "\f11a"; } .fa-gamepad:before { content: "\f11b"; } .fa-keyboard-o:before { content: "\f11c"; } .fa-flag-o:before { content: "\f11d"; } .fa-flag-checkered:before { content: "\f11e"; } .fa-terminal:before { content: "\f120"; } .fa-code:before { content: "\f121"; } .fa-mail-reply-all:before, .fa-reply-all:before { content: "\f122"; } .fa-star-half-empty:before, .fa-star-half-full:before, .fa-star-half-o:before { content: "\f123"; } .fa-location-arrow:before { content: "\f124"; } .fa-crop:before { content: "\f125"; } .fa-code-fork:before { content: "\f126"; } .fa-unlink:before, .fa-chain-broken:before { content: "\f127"; } .fa-question:before { content: "\f128"; } .fa-info:before { content: "\f129"; } .fa-exclamation:before { content: "\f12a"; } .fa-superscript:before { content: "\f12b"; } .fa-subscript:before { content: "\f12c"; } .fa-eraser:before { content: "\f12d"; } .fa-puzzle-piece:before { content: "\f12e"; } .fa-microphone:before { content: "\f130"; } .fa-microphone-slash:before { content: "\f131"; } .fa-shield:before { content: "\f132"; } .fa-calendar-o:before { content: "\f133"; } .fa-fire-extinguisher:before { content: "\f134"; } .fa-rocket:before { content: "\f135"; } .fa-maxcdn:before { content: "\f136"; } .fa-chevron-circle-left:before { content: "\f137"; } .fa-chevron-circle-right:before { content: "\f138"; } .fa-chevron-circle-up:before { content: "\f139"; } .fa-chevron-circle-down:before { content: "\f13a"; } .fa-html5:before { content: "\f13b"; } .fa-css3:before { content: "\f13c"; } .fa-anchor:before { content: "\f13d"; } .fa-unlock-alt:before { content: "\f13e"; } .fa-bullseye:before { content: "\f140"; } .fa-ellipsis-h:before { content: "\f141"; } .fa-ellipsis-v:before { content: "\f142"; } .fa-rss-square:before { content: "\f143"; } .fa-play-circle:before { content: "\f144"; } .fa-ticket:before { content: "\f145"; } .fa-minus-square:before { content: "\f146"; } .fa-minus-square-o:before { content: "\f147"; } .fa-level-up:before { content: "\f148"; } .fa-level-down:before { content: "\f149"; } .fa-check-square:before { content: "\f14a"; } .fa-pencil-square:before { content: "\f14b"; } .fa-external-link-square:before { content: "\f14c"; } .fa-share-square:before { content: "\f14d"; } .fa-compass:before { content: "\f14e"; } .fa-toggle-down:before, .fa-caret-square-o-down:before { content: "\f150"; } .fa-toggle-up:before, .fa-caret-square-o-up:before { content: "\f151"; } .fa-toggle-right:before, .fa-caret-square-o-right:before { content: "\f152"; } .fa-euro:before, .fa-eur:before { content: "\f153"; } .fa-gbp:before { content: "\f154"; } .fa-dollar:before, .fa-usd:before { content: "\f155"; } .fa-rupee:before, .fa-inr:before { content: "\f156"; } .fa-cny:before, .fa-rmb:before, .fa-yen:before, .fa-jpy:before { content: "\f157"; } .fa-ruble:before, .fa-rouble:before, .fa-rub:before { content: "\f158"; } .fa-won:before, .fa-krw:before { content: "\f159"; } .fa-bitcoin:before, .fa-btc:before { content: "\f15a"; } .fa-file:before { content: "\f15b"; } .fa-file-text:before { content: "\f15c"; } .fa-sort-alpha-asc:before { content: "\f15d"; } .fa-sort-alpha-desc:before { content: "\f15e"; } .fa-sort-amount-asc:before { content: "\f160"; } .fa-sort-amount-desc:before { content: "\f161"; } .fa-sort-numeric-asc:before { content: "\f162"; } .fa-sort-numeric-desc:before { content: "\f163"; } .fa-thumbs-up:before { content: "\f164"; } .fa-thumbs-down:before { content: "\f165"; } .fa-youtube-square:before { content: "\f166"; } .fa-youtube:before { content: "\f167"; } .fa-xing:before { content: "\f168"; } .fa-xing-square:before { content: "\f169"; } .fa-youtube-play:before { content: "\f16a"; } .fa-dropbox:before { content: "\f16b"; } .fa-stack-overflow:before { content: "\f16c"; } .fa-instagram:before { content: "\f16d"; } .fa-flickr:before { content: "\f16e"; } .fa-adn:before { content: "\f170"; } .fa-bitbucket:before { content: "\f171"; } .fa-bitbucket-square:before { content: "\f172"; } .fa-tumblr:before { content: "\f173"; } .fa-tumblr-square:before { content: "\f174"; } .fa-long-arrow-down:before { content: "\f175"; } .fa-long-arrow-up:before { content: "\f176"; } .fa-long-arrow-left:before { content: "\f177"; } .fa-long-arrow-right:before { content: "\f178"; } .fa-apple:before { content: "\f179"; } .fa-windows:before { content: "\f17a"; } .fa-android:before { content: "\f17b"; } .fa-linux:before { content: "\f17c"; } .fa-dribbble:before { content: "\f17d"; } .fa-skype:before { content: "\f17e"; } .fa-foursquare:before { content: "\f180"; } .fa-trello:before { content: "\f181"; } .fa-female:before { content: "\f182"; } .fa-male:before { content: "\f183"; } .fa-gittip:before, .fa-gratipay:before { content: "\f184"; } .fa-sun-o:before { content: "\f185"; } .fa-moon-o:before { content: "\f186"; } .fa-archive:before { content: "\f187"; } .fa-bug:before { content: "\f188"; } .fa-vk:before { content: "\f189"; } .fa-weibo:before { content: "\f18a"; } .fa-renren:before { content: "\f18b"; } .fa-pagelines:before { content: "\f18c"; } .fa-stack-exchange:before { content: "\f18d"; } .fa-arrow-circle-o-right:before { content: "\f18e"; } .fa-arrow-circle-o-left:before { content: "\f190"; } .fa-toggle-left:before, .fa-caret-square-o-left:before { content: "\f191"; } .fa-dot-circle-o:before { content: "\f192"; } .fa-wheelchair:before { content: "\f193"; } .fa-vimeo-square:before { content: "\f194"; } .fa-turkish-lira:before, .fa-try:before { content: "\f195"; } .fa-plus-square-o:before { content: "\f196"; } .fa-space-shuttle:before { content: "\f197"; } .fa-slack:before { content: "\f198"; } .fa-envelope-square:before { content: "\f199"; } .fa-wordpress:before { content: "\f19a"; } .fa-openid:before { content: "\f19b"; } .fa-institution:before, .fa-bank:before, .fa-university:before { content: "\f19c"; } .fa-mortar-board:before, .fa-graduation-cap:before { content: "\f19d"; } .fa-yahoo:before { content: "\f19e"; } .fa-google:before { content: "\f1a0"; } .fa-reddit:before { content: "\f1a1"; } .fa-reddit-square:before { content: "\f1a2"; } .fa-stumbleupon-circle:before { content: "\f1a3"; } .fa-stumbleupon:before { content: "\f1a4"; } .fa-delicious:before { content: "\f1a5"; } .fa-digg:before { content: "\f1a6"; } .fa-pied-piper:before { content: "\f1a7"; } .fa-pied-piper-alt:before { content: "\f1a8"; } .fa-drupal:before { content: "\f1a9"; } .fa-joomla:before { content: "\f1aa"; } .fa-language:before { content: "\f1ab"; } .fa-fax:before { content: "\f1ac"; } .fa-building:before { content: "\f1ad"; } .fa-child:before { content: "\f1ae"; } .fa-paw:before { content: "\f1b0"; } .fa-spoon:before { content: "\f1b1"; } .fa-cube:before { content: "\f1b2"; } .fa-cubes:before { content: "\f1b3"; } .fa-behance:before { content: "\f1b4"; } .fa-behance-square:before { content: "\f1b5"; } .fa-steam:before { content: "\f1b6"; } .fa-steam-square:before { content: "\f1b7"; } .fa-recycle:before { content: "\f1b8"; } .fa-automobile:before, .fa-car:before { content: "\f1b9"; } .fa-cab:before, .fa-taxi:before { content: "\f1ba"; } .fa-tree:before { content: "\f1bb"; } .fa-spotify:before { content: "\f1bc"; } .fa-deviantart:before { content: "\f1bd"; } .fa-soundcloud:before { content: "\f1be"; } .fa-database:before { content: "\f1c0"; } .fa-file-pdf-o:before { content: "\f1c1"; } .fa-file-word-o:before { content: "\f1c2"; } .fa-file-excel-o:before { content: "\f1c3"; } .fa-file-powerpoint-o:before { content: "\f1c4"; } .fa-file-photo-o:before, .fa-file-picture-o:before, .fa-file-image-o:before { content: "\f1c5"; } .fa-file-zip-o:before, .fa-file-archive-o:before { content: "\f1c6"; } .fa-file-sound-o:before, .fa-file-audio-o:before { content: "\f1c7"; } .fa-file-movie-o:before, .fa-file-video-o:before { content: "\f1c8"; } .fa-file-code-o:before { content: "\f1c9"; } .fa-vine:before { content: "\f1ca"; } .fa-codepen:before { content: "\f1cb"; } .fa-jsfiddle:before { content: "\f1cc"; } .fa-life-bouy:before, .fa-life-buoy:before, .fa-life-saver:before, .fa-support:before, .fa-life-ring:before { content: "\f1cd"; } .fa-circle-o-notch:before { content: "\f1ce"; } .fa-ra:before, .fa-rebel:before { content: "\f1d0"; } .fa-ge:before, .fa-empire:before { content: "\f1d1"; } .fa-git-square:before { content: "\f1d2"; } .fa-git:before { content: "\f1d3"; } .fa-y-combinator-square:before, .fa-yc-square:before, .fa-hacker-news:before { content: "\f1d4"; } .fa-tencent-weibo:before { content: "\f1d5"; } .fa-qq:before { content: "\f1d6"; } .fa-wechat:before, .fa-weixin:before { content: "\f1d7"; } .fa-send:before, .fa-paper-plane:before { content: "\f1d8"; } .fa-send-o:before, .fa-paper-plane-o:before { content: "\f1d9"; } .fa-history:before { content: "\f1da"; } .fa-circle-thin:before { content: "\f1db"; } .fa-header:before { content: "\f1dc"; } .fa-paragraph:before { content: "\f1dd"; } .fa-sliders:before { content: "\f1de"; } .fa-share-alt:before { content: "\f1e0"; } .fa-share-alt-square:before { content: "\f1e1"; } .fa-bomb:before { content: "\f1e2"; } .fa-soccer-ball-o:before, .fa-futbol-o:before { content: "\f1e3"; } .fa-tty:before { content: "\f1e4"; } .fa-binoculars:before { content: "\f1e5"; } .fa-plug:before { content: "\f1e6"; } .fa-slideshare:before { content: "\f1e7"; } .fa-twitch:before { content: "\f1e8"; } .fa-yelp:before { content: "\f1e9"; } .fa-newspaper-o:before { content: "\f1ea"; } .fa-wifi:before { content: "\f1eb"; } .fa-calculator:before { content: "\f1ec"; } .fa-paypal:before { content: "\f1ed"; } .fa-google-wallet:before { content: "\f1ee"; } .fa-cc-visa:before { content: "\f1f0"; } .fa-cc-mastercard:before { content: "\f1f1"; } .fa-cc-discover:before { content: "\f1f2"; } .fa-cc-amex:before { content: "\f1f3"; } .fa-cc-paypal:before { content: "\f1f4"; } .fa-cc-stripe:before { content: "\f1f5"; } .fa-bell-slash:before { content: "\f1f6"; } .fa-bell-slash-o:before { content: "\f1f7"; } .fa-trash:before { content: "\f1f8"; } .fa-copyright:before { content: "\f1f9"; } .fa-at:before { content: "\f1fa"; } .fa-eyedropper:before { content: "\f1fb"; } .fa-paint-brush:before { content: "\f1fc"; } .fa-birthday-cake:before { content: "\f1fd"; } .fa-area-chart:before { content: "\f1fe"; } .fa-pie-chart:before { content: "\f200"; } .fa-line-chart:before { content: "\f201"; } .fa-lastfm:before { content: "\f202"; } .fa-lastfm-square:before { content: "\f203"; } .fa-toggle-off:before { content: "\f204"; } .fa-toggle-on:before { content: "\f205"; } .fa-bicycle:before { content: "\f206"; } .fa-bus:before { content: "\f207"; } .fa-ioxhost:before { content: "\f208"; } .fa-angellist:before { content: "\f209"; } .fa-cc:before { content: "\f20a"; } .fa-shekel:before, .fa-sheqel:before, .fa-ils:before { content: "\f20b"; } .fa-meanpath:before { content: "\f20c"; } .fa-buysellads:before { content: "\f20d"; } .fa-connectdevelop:before { content: "\f20e"; } .fa-dashcube:before { content: "\f210"; } .fa-forumbee:before { content: "\f211"; } .fa-leanpub:before { content: "\f212"; } .fa-sellsy:before { content: "\f213"; } .fa-shirtsinbulk:before { content: "\f214"; } .fa-simplybuilt:before { content: "\f215"; } .fa-skyatlas:before { content: "\f216"; } .fa-cart-plus:before { content: "\f217"; } .fa-cart-arrow-down:before { content: "\f218"; } .fa-diamond:before { content: "\f219"; } .fa-ship:before { content: "\f21a"; } .fa-user-secret:before { content: "\f21b"; } .fa-motorcycle:before { content: "\f21c"; } .fa-street-view:before { content: "\f21d"; } .fa-heartbeat:before { content: "\f21e"; } .fa-venus:before { content: "\f221"; } .fa-mars:before { content: "\f222"; } .fa-mercury:before { content: "\f223"; } .fa-intersex:before, .fa-transgender:before { content: "\f224"; } .fa-transgender-alt:before { content: "\f225"; } .fa-venus-double:before { content: "\f226"; } .fa-mars-double:before { content: "\f227"; } .fa-venus-mars:before { content: "\f228"; } .fa-mars-stroke:before { content: "\f229"; } .fa-mars-stroke-v:before { content: "\f22a"; } .fa-mars-stroke-h:before { content: "\f22b"; } .fa-neuter:before { content: "\f22c"; } .fa-genderless:before { content: "\f22d"; } .fa-facebook-official:before { content: "\f230"; } .fa-pinterest-p:before { content: "\f231"; } .fa-whatsapp:before { content: "\f232"; } .fa-server:before { content: "\f233"; } .fa-user-plus:before { content: "\f234"; } .fa-user-times:before { content: "\f235"; } .fa-hotel:before, .fa-bed:before { content: "\f236"; } .fa-viacoin:before { content: "\f237"; } .fa-train:before { content: "\f238"; } .fa-subway:before { content: "\f239"; } .fa-medium:before { content: "\f23a"; } .fa-yc:before, .fa-y-combinator:before { content: "\f23b"; } .fa-optin-monster:before { content: "\f23c"; } .fa-opencart:before { content: "\f23d"; } .fa-expeditedssl:before { content: "\f23e"; } .fa-battery-4:before, .fa-battery-full:before { content: "\f240"; } .fa-battery-3:before, .fa-battery-three-quarters:before { content: "\f241"; } .fa-battery-2:before, .fa-battery-half:before { content: "\f242"; } .fa-battery-1:before, .fa-battery-quarter:before { content: "\f243"; } .fa-battery-0:before, .fa-battery-empty:before { content: "\f244"; } .fa-mouse-pointer:before { content: "\f245"; } .fa-i-cursor:before { content: "\f246"; } .fa-object-group:before { content: "\f247"; } .fa-object-ungroup:before { content: "\f248"; } .fa-sticky-note:before { content: "\f249"; } .fa-sticky-note-o:before { content: "\f24a"; } .fa-cc-jcb:before { content: "\f24b"; } .fa-cc-diners-club:before { content: "\f24c"; } .fa-clone:before { content: "\f24d"; } .fa-balance-scale:before { content: "\f24e"; } .fa-hourglass-o:before { content: "\f250"; } .fa-hourglass-1:before, .fa-hourglass-start:before { content: "\f251"; } .fa-hourglass-2:before, .fa-hourglass-half:before { content: "\f252"; } .fa-hourglass-3:before, .fa-hourglass-end:before { content: "\f253"; } .fa-hourglass:before { content: "\f254"; } .fa-hand-grab-o:before, .fa-hand-rock-o:before { content: "\f255"; } .fa-hand-stop-o:before, .fa-hand-paper-o:before { content: "\f256"; } .fa-hand-scissors-o:before { content: "\f257"; } .fa-hand-lizard-o:before { content: "\f258"; } .fa-hand-spock-o:before { content: "\f259"; } .fa-hand-pointer-o:before { content: "\f25a"; } .fa-hand-peace-o:before { content: "\f25b"; } .fa-trademark:before { content: "\f25c"; } .fa-registered:before { content: "\f25d"; } .fa-creative-commons:before { content: "\f25e"; } .fa-gg:before { content: "\f260"; } .fa-gg-circle:before { content: "\f261"; } .fa-tripadvisor:before { content: "\f262"; } .fa-odnoklassniki:before { content: "\f263"; } .fa-odnoklassniki-square:before { content: "\f264"; } .fa-get-pocket:before { content: "\f265"; } .fa-wikipedia-w:before { content: "\f266"; } .fa-safari:before { content: "\f267"; } .fa-chrome:before { content: "\f268"; } .fa-firefox:before { content: "\f269"; } .fa-opera:before { content: "\f26a"; } .fa-internet-explorer:before { content: "\f26b"; } .fa-tv:before, .fa-television:before { content: "\f26c"; } .fa-contao:before { content: "\f26d"; } .fa-500px:before { content: "\f26e"; } .fa-amazon:before { content: "\f270"; } .fa-calendar-plus-o:before { content: "\f271"; } .fa-calendar-minus-o:before { content: "\f272"; } .fa-calendar-times-o:before { content: "\f273"; } .fa-calendar-check-o:before { content: "\f274"; } .fa-industry:before { content: "\f275"; } .fa-map-pin:before { content: "\f276"; } .fa-map-signs:before { content: "\f277"; } .fa-map-o:before { content: "\f278"; } .fa-map:before { content: "\f279"; } .fa-commenting:before { content: "\f27a"; } .fa-commenting-o:before { content: "\f27b"; } .fa-houzz:before { content: "\f27c"; } .fa-vimeo:before { content: "\f27d"; } .fa-black-tie:before { content: "\f27e"; } .fa-fonticons:before { content: "\f280"; } .fa-reddit-alien:before { content: "\f281"; } .fa-edge:before { content: "\f282"; } .fa-credit-card-alt:before { content: "\f283"; } .fa-codiepie:before { content: "\f284"; } .fa-modx:before { content: "\f285"; } .fa-fort-awesome:before { content: "\f286"; } .fa-usb:before { content: "\f287"; } .fa-product-hunt:before { content: "\f288"; } .fa-mixcloud:before { content: "\f289"; } .fa-scribd:before { content: "\f28a"; } .fa-pause-circle:before { content: "\f28b"; } .fa-pause-circle-o:before { content: "\f28c"; } .fa-stop-circle:before { content: "\f28d"; } .fa-stop-circle-o:before { content: "\f28e"; } .fa-shopping-bag:before { content: "\f290"; } .fa-shopping-basket:before { content: "\f291"; } .fa-hashtag:before { content: "\f292"; } .fa-bluetooth:before { content: "\f293"; } .fa-bluetooth-b:before { content: "\f294"; } .fa-percent:before { content: "\f295"; } ================================================ FILE: templates/project/config.ru ================================================ require 'dashing' configure do set :auth_token, 'YOUR_AUTH_TOKEN' helpers do def protected! # Put any authentication code you want in here. # This method is run before accessing any resource. end end end map Sinatra::Application.assets_prefix do run Sinatra::Application.sprockets end run Sinatra::Application ================================================ FILE: templates/project/dashboards/layout.erb ================================================ <%= yield_content(:title) %>
<%= yield %>
<% if development? %>

Paste the following at the top of <%= params[:dashboard] %>.erb

Save this layout <% end %> ================================================ FILE: templates/project/dashboards/sample.erb ================================================ <% content_for :title do %>My super sweet dashboard<% end %>
Try this: curl -d '{ "auth_token": "YOUR_AUTH_TOKEN", "text": "Hey, Look what I can do!" }' \http://<%=request.host%>:<%=request.port%>/widgets/welcome
================================================ FILE: templates/project/dashboards/sampletv.erb ================================================ <% content_for :title do %>1080p dashboard<% end %>
Try this: curl -d '{ "auth_token": "YOUR_AUTH_TOKEN", "text": "Hey, Look what I can do!" }' \http://<%=request.host%>:<%=request.port%>/widgets/welcome
================================================ FILE: templates/project/jobs/buzzwords.rb ================================================ buzzwords = ['Paradigm shift', 'Leverage', 'Pivoting', 'Turn-key', 'Streamlininess', 'Exit strategy', 'Synergy', 'Enterprise', 'Web 2.0'] buzzword_counts = Hash.new({ value: 0 }) SCHEDULER.every '2s' do random_buzzword = buzzwords.sample buzzword_counts[random_buzzword] = { label: random_buzzword, value: (buzzword_counts[random_buzzword][:value] + 1) % 30 } send_event('buzzwords', { items: buzzword_counts.values }) end ================================================ FILE: templates/project/jobs/convergence.rb ================================================ # Populate the graph with some random points points = [] (1..10).each do |i| points << { x: i, y: rand(50) } end last_x = points.last[:x] SCHEDULER.every '2s' do points.shift last_x += 1 points << { x: last_x, y: rand(50) } send_event('convergence', points: points) end ================================================ FILE: templates/project/jobs/sample.rb ================================================ current_valuation = 0 current_karma = 0 SCHEDULER.every '2s' do last_valuation = current_valuation last_karma = current_karma current_valuation = rand(100) current_karma = rand(200000) send_event('valuation', { current: current_valuation, last: last_valuation }) send_event('karma', { current: current_karma, last: last_karma }) send_event('synergy', { value: rand(100) }) end ================================================ FILE: templates/project/jobs/twitter.rb ================================================ require 'twitter' #### Get your twitter keys & secrets: #### https://dev.twitter.com/docs/auth/tokens-devtwittercom twitter = Twitter::REST::Client.new do |config| config.consumer_key = 'YOUR_CONSUMER_KEY' config.consumer_secret = 'YOUR_CONSUMER_SECRET' config.access_token = 'YOUR_OAUTH_TOKEN' config.access_token_secret = 'YOUR_OAUTH_SECRET' end search_term = URI::encode('#todayilearned') SCHEDULER.every '10m', :first_in => 0 do |job| begin tweets = twitter.search("#{search_term}") if tweets tweets = tweets.map do |tweet| { name: tweet.user.name, body: tweet.text, avatar: tweet.user.profile_image_url_https } end send_event('twitter_mentions', comments: tweets) end rescue Twitter::Error puts "\e[33mFor the twitter widget to work, you need to put in your twitter API keys in the jobs/twitter.rb file.\e[0m" end end ================================================ FILE: templates/project/lib/.empty_directory ================================================ .empty_directory ================================================ FILE: templates/project/public/404.html ================================================ This Dashboard doesn't exist.

Drats! That Dashboard doesn't exist.

You may have mistyped the address or the page may have moved.

================================================ FILE: templates/project/widgets/clock/clock.coffee ================================================ class Dashing.Clock extends Dashing.Widget ready: -> setInterval(@startTime, 500) startTime: => today = new Date() h = today.getHours() m = today.getMinutes() s = today.getSeconds() m = @formatTime(m) s = @formatTime(s) @set('time', h + ":" + m + ":" + s) @set('date', today.toDateString()) formatTime: (i) -> if i < 10 then "0" + i else i ================================================ FILE: templates/project/widgets/clock/clock.html ================================================

================================================ FILE: templates/project/widgets/clock/clock.scss ================================================ // ---------------------------------------------------------------------------- // Sass declarations // ---------------------------------------------------------------------------- $background-color: #dc5945; // ---------------------------------------------------------------------------- // Widget-clock styles // ---------------------------------------------------------------------------- .widget-clock { background-color: $background-color; } ================================================ FILE: templates/project/widgets/comments/comments.coffee ================================================ class Dashing.Comments extends Dashing.Widget @accessor 'quote', -> "“#{@get('current_comment')?.body}”" ready: -> @currentIndex = 0 @commentElem = $(@node).find('.comment-container') @nextComment() @startCarousel() onData: (data) -> @currentIndex = 0 startCarousel: -> setInterval(@nextComment, 8000) nextComment: => comments = @get('comments') if comments @commentElem.fadeOut => @currentIndex = (@currentIndex + 1) % comments.length @set 'current_comment', comments[@currentIndex] @commentElem.fadeIn() ================================================ FILE: templates/project/widgets/comments/comments.html ================================================

================================================ FILE: templates/project/widgets/comments/comments.scss ================================================ // ---------------------------------------------------------------------------- // Sass declarations // ---------------------------------------------------------------------------- $background-color: #eb9c3c; $title-color: rgba(255, 255, 255, 0.7); $moreinfo-color: rgba(255, 255, 255, 0.7); // ---------------------------------------------------------------------------- // Widget-comment styles // ---------------------------------------------------------------------------- .widget-comments { background-color: $background-color; .title { color: $title-color; margin-bottom: 15px; } .name { padding-left: 5px; } .comment-container { display: none; } .more-info { color: $moreinfo-color; } } ================================================ FILE: templates/project/widgets/graph/graph.coffee ================================================ class Dashing.Graph extends Dashing.Widget @accessor 'current', -> return @get('displayedValue') if @get('displayedValue') points = @get('points') if points points[points.length - 1].y ready: -> container = $(@node).parent() # Gross hacks. Let's fix this. width = (Dashing.widget_base_dimensions[0] * container.data("sizex")) + Dashing.widget_margins[0] * 2 * (container.data("sizex") - 1) height = (Dashing.widget_base_dimensions[1] * container.data("sizey")) @graph = new Rickshaw.Graph( element: @node width: width height: height renderer: @get("graphtype") series: [ { color: "#fff", data: [{x:0, y:0}] } ] padding: {top: 0.02, left: 0.02, right: 0.02, bottom: 0.02} ) @graph.series[0].data = @get('points') if @get('points') x_axis = new Rickshaw.Graph.Axis.Time(graph: @graph) y_axis = new Rickshaw.Graph.Axis.Y(graph: @graph, tickFormat: Rickshaw.Fixtures.Number.formatKMBT) @graph.render() onData: (data) -> if @graph @graph.series[0].data = data.points @graph.render() ================================================ FILE: templates/project/widgets/graph/graph.html ================================================

================================================ FILE: templates/project/widgets/graph/graph.scss ================================================ // ---------------------------------------------------------------------------- // Sass declarations // ---------------------------------------------------------------------------- $background-color: #dc5945; $title-color: rgba(255, 255, 255, 0.7); $moreinfo-color: rgba(255, 255, 255, 0.3); $tick-color: rgba(0, 0, 0, 0.4); // ---------------------------------------------------------------------------- // Widget-graph styles // ---------------------------------------------------------------------------- .widget-graph { background-color: $background-color; position: relative; svg { position: absolute; opacity: 0.4; fill-opacity: 0.4; left: 0px; top: 0px; } .title, .value { position: relative; z-index: 99; } .title { color: $title-color; } .more-info { color: $moreinfo-color; font-weight: 600; font-size: 20px; margin-top: 0; } .x_tick { position: absolute; bottom: 0; .title { font-size: 20px; color: $tick-color; opacity: 0.5; padding-bottom: 3px; } } .y_ticks { font-size: 20px; fill: $tick-color; fill-opacity: 1; } .domain { display: none; } } ================================================ FILE: templates/project/widgets/iframe/iframe.coffee ================================================ class Dashing.Iframe extends Dashing.Widget ready: -> # This is fired when the widget is done being rendered onData: (data) -> # Handle incoming data # You can access the html node of this widget with `@node` # Example: $(@node).fadeOut().fadeIn() will make the node flash each time data comes in. ================================================ FILE: templates/project/widgets/iframe/iframe.html ================================================ ================================================ FILE: templates/project/widgets/iframe/iframe.scss ================================================ .widget-iframe { padding: 3px 0px 0px 0px !important; iframe { width: 100%; height: 100%; } } ================================================ FILE: templates/project/widgets/image/image.coffee ================================================ class Dashing.Image extends Dashing.Widget ready: -> # This is fired when the widget is done being rendered onData: (data) -> # Handle incoming data # You can access the html node of this widget with `@node` # Example: $(@node).fadeOut().fadeIn() will make the node flash each time data comes in. ================================================ FILE: templates/project/widgets/image/image.html ================================================ ================================================ FILE: templates/project/widgets/image/image.scss ================================================ // ---------------------------------------------------------------------------- // Sass declarations // ---------------------------------------------------------------------------- $background-color: #4b4b4b; // ---------------------------------------------------------------------------- // Widget-image styles // ---------------------------------------------------------------------------- .widget-image { background-color: $background-color; } ================================================ FILE: templates/project/widgets/list/list.coffee ================================================ class Dashing.List extends Dashing.Widget ready: -> if @get('unordered') $(@node).find('ol').remove() else $(@node).find('ul').remove() ================================================ FILE: templates/project/widgets/list/list.html ================================================

================================================ FILE: templates/project/widgets/list/list.scss ================================================ // ---------------------------------------------------------------------------- // Sass declarations // ---------------------------------------------------------------------------- $background-color: #12b0c5; $value-color: #fff; $title-color: rgba(255, 255, 255, 0.7); $label-color: rgba(255, 255, 255, 0.7); $moreinfo-color: rgba(255, 255, 255, 0.7); // ---------------------------------------------------------------------------- // Widget-list styles // ---------------------------------------------------------------------------- .widget-list { background-color: $background-color; vertical-align: top; .title { color: $title-color; } ol, ul { margin: 0 15px; text-align: left; color: $label-color; } ol { list-style-position: inside; } li { margin-bottom: 5px; } .list-nostyle { list-style: none; } .label { color: $label-color; } .value { float: right; margin-left: 12px; font-weight: 600; color: $value-color; } .updated-at { color: rgba(0, 0, 0, 0.3); } .more-info { color: $moreinfo-color; } } ================================================ FILE: templates/project/widgets/meter/meter.coffee ================================================ class Dashing.Meter extends Dashing.Widget @accessor 'value', Dashing.AnimatedValue constructor: -> super @observe 'value', (value) -> $(@node).find(".meter").val(value).trigger('change') ready: -> meter = $(@node).find(".meter") meter.attr("data-bgcolor", meter.css("background-color")) meter.attr("data-fgcolor", meter.css("color")) meter.knob() ================================================ FILE: templates/project/widgets/meter/meter.html ================================================

================================================ FILE: templates/project/widgets/meter/meter.scss ================================================ // ---------------------------------------------------------------------------- // Sass declarations // ---------------------------------------------------------------------------- $background-color: #9c4274; $title-color: rgba(255, 255, 255, 0.7); $moreinfo-color: rgba(255, 255, 255, 0.3); $meter-background: darken($background-color, 15%); // ---------------------------------------------------------------------------- // Widget-meter styles // ---------------------------------------------------------------------------- .widget-meter { background-color: $background-color; input.meter { background-color: $meter-background; color: #fff; } .title { color: $title-color; } .more-info { color: $moreinfo-color; } .updated-at { color: rgba(0, 0, 0, 0.3); } } ================================================ FILE: templates/project/widgets/number/number.coffee ================================================ class Dashing.Number extends Dashing.Widget @accessor 'current', Dashing.AnimatedValue @accessor 'difference', -> if @get('last') last = parseInt(@get('last')) current = parseInt(@get('current')) if last != 0 diff = Math.abs(Math.round((current - last) / last * 100)) "#{diff}%" else "" @accessor 'arrow', -> if @get('last') if parseInt(@get('current')) > parseInt(@get('last')) then 'fa fa-arrow-up' else 'fa fa-arrow-down' onData: (data) -> if data.status # clear existing "status-*" classes $(@get('node')).attr 'class', (i,c) -> c.replace /\bstatus-\S+/g, '' # add new class $(@get('node')).addClass "status-#{data.status}" ================================================ FILE: templates/project/widgets/number/number.html ================================================

================================================ FILE: templates/project/widgets/number/number.scss ================================================ // ---------------------------------------------------------------------------- // Sass declarations // ---------------------------------------------------------------------------- $background-color: #47bbb3; $value-color: #fff; $title-color: rgba(255, 255, 255, 0.7); $moreinfo-color: rgba(255, 255, 255, 0.7); // ---------------------------------------------------------------------------- // Widget-number styles // ---------------------------------------------------------------------------- .widget-number { background-color: $background-color; .title { color: $title-color; } .value { color: $value-color; } .change-rate { font-weight: 500; font-size: 30px; color: $value-color; } .more-info { color: $moreinfo-color; } .updated-at { color: rgba(0, 0, 0, 0.3); } } ================================================ FILE: templates/project/widgets/text/text.coffee ================================================ class Dashing.Text extends Dashing.Widget ================================================ FILE: templates/project/widgets/text/text.html ================================================

================================================ FILE: templates/project/widgets/text/text.scss ================================================ // ---------------------------------------------------------------------------- // Sass declarations // ---------------------------------------------------------------------------- $background-color: #ec663c; $title-color: rgba(255, 255, 255, 0.7); $moreinfo-color: rgba(255, 255, 255, 0.7); // ---------------------------------------------------------------------------- // Widget-text styles // ---------------------------------------------------------------------------- .widget-text { background-color: $background-color; .title { color: $title-color; } .more-info { color: $moreinfo-color; } .updated-at { color: rgba(255, 255, 255, 0.7); } &.large h3 { font-size: 65px; } } ================================================ FILE: templates/widget/%name%/%name%.coffee.tt ================================================ class Dashing.<%= Thor::Util.camel_case(name) %> extends Dashing.Widget ready: -> # This is fired when the widget is done being rendered onData: (data) -> # Handle incoming data # You can access the html node of this widget with `@node` # Example: $(@node).fadeOut().fadeIn() will make the node flash each time data comes in. ================================================ FILE: templates/widget/%name%/%name%.html ================================================
================================================ FILE: templates/widget/%name%/%name%.scss.tt ================================================ .widget-<%= Dashing::CLI.hyphenate(name) %> { } ================================================ FILE: test/app_test.rb ================================================ require 'test_helper' require 'haml' class AppTest < Dashing::Test def setup @connection = [] app.settings.connections = [@connection] app.settings.auth_token = nil app.settings.default_dashboard = nil app.settings.history_file = File.join(Dir.tmpdir, 'history.yml') end def test_redirect_to_first_dashboard with_generated_project do get '/' assert_equal 302, last_response.status assert_equal 'http://example.org/sample', last_response.location end end def test_redirect_to_first_dashboard_without_erb with_generated_project do |dir| FileUtils.touch(File.join(dir, "dashboards/htmltest.html")) get '/' assert_equal 302, last_response.status assert_equal 'http://example.org/htmltest', last_response.location end end def test_redirect_to_default_dashboard with_generated_project do app.settings.default_dashboard = 'test1' get '/' assert_equal 302, last_response.status assert_equal 'http://example.org/test1', last_response.location end end def test_errors_out_when_no_dashboards_available with_generated_project do app.settings.views = File.join(app.settings.root, 'lib') get '/' assert_equal 500, last_response.status end end def test_post_widgets_without_auth_token post '/widgets/some_widget', JSON.generate({value: 6}) assert_equal 204, last_response.status assert_equal 1, @connection.length data = parse_data @connection[0] assert_equal 6, data['value'] assert_equal 'some_widget', data['id'] assert data['updatedAt'] end def test_post_widgets_with_invalid_auth_token app.settings.auth_token = 'sekrit' post '/widgets/some_widget', JSON.generate({value: 9}) assert_equal 401, last_response.status end def test_post_widgets_with_valid_auth_token app.settings.auth_token = 'sekrit' post '/widgets/some_widget', JSON.generate({value: 9, auth_token: 'sekrit'}) assert_equal 204, last_response.status end def test_get_events post '/widgets/some_widget', JSON.generate({value: 8}) assert_equal 204, last_response.status get '/events' assert_equal 200, last_response.status assert_equal 8, parse_data(@connection[0])['value'] end def test_dashboard_events post '/dashboards/my_super_sweet_dashboard', JSON.generate({event: 'reload'}) assert_equal 204, last_response.status get '/events' assert_equal 200, last_response.status assert_equal 'dashboards', parse_event(@connection[0]) assert_equal 'reload', parse_data(@connection[0])['event'] end def test_get_dashboard with_generated_project do get '/sampletv' assert_equal 200, last_response.status assert_includes last_response.body, 'class="gridster"' assert_includes last_response.body, "DOCTYPE" end end def test_page_title_set_correctly with_generated_project do get '/sampletv' assert_includes last_response.body, '1080p dashboard' end end def test_get_haml_dashboard with_generated_project do |dir| File.write(File.join(dir, 'dashboards/hamltest.haml'), '.gridster') get '/hamltest' assert_equal 200, last_response.status assert_includes last_response.body, "class='gridster'" end end def test_get_haml_widget with_generated_project do |dir| File.write(File.join(dir, 'widgets/clock/clock.haml'), '%h1 haml') File.unlink(File.join(dir, 'widgets/clock/clock.html')) get '/views/clock.html' assert_equal 200, last_response.status assert_includes last_response.body, '

haml

' end end def test_get_nonexistent_dashboard with_generated_project do get '/nodashboard' assert_equal 404, last_response.status end end def test_get_widget with_generated_project do get '/views/meter.html' assert_equal 200, last_response.status assert_includes last_response.body, 'class="meter"' end end def with_generated_project source_path = File.expand_path('../../templates', __FILE__) temp do |dir| cli = Dashing::CLI.new cli.stubs(:source_paths).returns([source_path]) silent { cli.new 'new_project' } app.settings.public_folder = File.join(dir, 'new_project/public') app.settings.views = File.join(dir, 'new_project/dashboards') app.settings.root = File.join(dir, 'new_project') yield app.settings.root end end def app Sinatra::Application end def parse_data(string) JSON.parse string[/data: (.+)/, 1] end def parse_event(string) string[/event: (.+)/, 1] end end ================================================ FILE: test/cli_test.rb ================================================ require 'test_helper' class CLITest < Dashing::Test def setup @cli = Dashing::CLI.new end def test_new_task_creates_project_directory app_name = 'custom_dashboard' @cli.stubs(:directory).with(:project, app_name).once @cli.new(app_name) end def test_generate_task_delegates_to_type types = %w(widget dashboard job) types.each do |type| @cli.stubs(:public_send).with("generate_#{type}".to_sym, 'name').once @cli.generate(type, 'name') end end def test_generate_task_warns_when_generator_is_not_defined output, _ = capture_io do @cli.generate('wtf', 'name') end assert_includes output, 'Invalid generator' end def test_generate_widget_creates_a_new_widget @cli.stubs(:directory).with(:widget, 'widgets').once @cli.generate_widget('WidgetName') assert_equal 'widget_name', @cli.name end def test_generate_dashboard_creates_a_new_dashboard @cli.stubs(:directory).with(:dashboard, 'dashboards').once @cli.generate_dashboard('DashBoardName') assert_equal 'dash_board_name', @cli.name end def test_generate_job_creates_a_new_job @cli.stubs(:directory).with(:job, 'jobs').once @cli.generate_job('MyCustomJob') assert_equal 'my_custom_job', @cli.name end def test_install_task_requests_gist_from_downloader return_value = { 'files' => [] } Dashing::Downloader.stubs(:get_gist).with(123).returns(return_value).once capture_io { @cli.install(123) } end def test_install_task_calls_create_file_for_each_valid_file_in_gist json_response = <<-JSON { "files": { "ruby_job.rb": { "content": "some job content" }, "num.html": { "content": "some html content" }, "num.scss": { "content": "some sass content" }, "num.coffee": { "content": "some coffee content" } } } JSON Dir.stubs(:pwd).returns('') Dashing::Downloader.stubs(:get_gist).returns(JSON.parse(json_response)) @cli.stubs(:create_file).with('/jobs/ruby_job.rb', 'some job content', {:skip => false}).once @cli.stubs(:create_file).with('/widgets/num/num.html', 'some html content', {:skip => false}).once @cli.stubs(:create_file).with('/widgets/num/num.scss', 'some sass content', {:skip => false}).once @cli.stubs(:create_file).with('/widgets/num/num.coffee', 'some coffee content', {:skip => false}).once capture_io { @cli.install(123) } end def test_install_task_ignores_invalid_files json_response = <<-JSON { "files": { "ruby_job.js": { "content": "some job content" }, "num.css": { "content": "some sass content" } } } JSON Dashing::Downloader.stubs(:get_gist).returns(JSON.parse(json_response)) @cli.stubs(:create_file).never capture_io { @cli.install(123) } end def test_install_task_warns_when_gist_not_found error = OpenURI::HTTPError.new('error', mock()) Dashing::Downloader.stubs(:get_gist).raises(error) output, _ = capture_io { @cli.install(123) } assert_includes output, 'Could not find gist at ' end def test_start_task_starts_thin_with_default_port command = 'bundle exec thin -R config.ru start -p 3030 ' @cli.stubs(:run_command).with(command).once @cli.start end def test_start_task_starts_thin_with_specified_port command = 'bundle exec thin -R config.ru start -p 2020' @cli.stubs(:run_command).with(command).once @cli.start('-p', '2020') end def test_start_task_supports_job_path_option commands = [ 'export JOB_PATH=other_spot; ', 'bundle exec thin -R config.ru start -p 3030 ' ] @cli.stubs(:options).returns(job_path: 'other_spot') @cli.stubs(:run_command).with(commands.join('')).once @cli.start end def test_stop_task_stops_thin_server @cli.stubs(:run_command).with('bundle exec thin stop') @cli.stop end def test_job_task_requires_job_file Dir.stubs(:pwd).returns('') @cli.stubs(:require_file).with('/jobs/special_job.rb').once @cli.job('special_job') end def test_job_task_requires_every_ruby_file_in_lib Dir.stubs(:pwd).returns('') Dir.stubs(:[]).returns(['lib/dashing/cli.rb', 'lib/dashing.rb']) @cli.stubs(:require_file).times(3) @cli.job('special_job') end def test_job_sets_auth_token @cli.class.stubs(:auth_token=).with('my_token').once @cli.stubs(:require_file) @cli.job('my_job', 'my_token') end def test_hyphenate_lowers_and_hyphenates_inputs assertion_map = { 'Power' => 'power', 'POWER' => 'power', 'PowerRangers' => 'power-rangers', 'Power_ranger' => 'power-ranger', 'SuperPowerRangers' => 'super-power-rangers' } assertion_map.each do |input, expected| assert_equal expected, Dashing::CLI.hyphenate(input) end end end ================================================ FILE: test/downloader_test.rb ================================================ require 'test_helper' class DownloaderTest < Minitest::Test def test_get_json_requests_and_parses_content endpoint = 'http://somehost.com/file.json' response = '{ "name": "value" }' FakeWeb.register_uri(:get, endpoint, body: response) JSON.stubs(:parse).with(response).once Dashing::Downloader.get_json(endpoint) end def test_get_json_raises_on_bad_request FakeWeb.register_uri(:get, 'http://dead-host.com/', status: '404') assert_raises(OpenURI::HTTPError) do Dashing::Downloader.get_json('http://dead-host.com/') end end def test_load_gist_attempts_to_get_the_gist Dashing::Downloader.stubs(:get_json).once Dashing::Downloader.get_gist(123) end end ================================================ FILE: test/test_helper.rb ================================================ require 'simplecov' SimpleCov.start do add_filter "/vendor/" add_filter "/test/" end require 'rack/test' require 'stringio' require 'tmpdir' require 'fakeweb' require 'minitest/autorun' require 'minitest/pride' require 'mocha/setup' require_relative '../lib/dashing' FakeWeb.allow_net_connect = false ENV['RACK_ENV'] = 'test' WORKING_DIRECTORY = Dir.pwd.freeze ARGV.clear def load_quietly(file) Minitest::Test.new(nil).capture_io do load file end end def temp path = File.expand_path "#{Dir.tmpdir}/#{Time.now.to_i}#{rand(1000)}/" FileUtils.mkdir_p path Dir.chdir path yield path ensure Dir.chdir WORKING_DIRECTORY FileUtils.rm_rf(path) if File.exists?(path) end module Dashing class Test < Minitest::Test include Rack::Test::Methods alias_method :silent, :capture_io def teardown FileUtils.rm_f('history.yml') end end end