text: // Backbone.js 0.9.2
  
  // (c) 2010-2012 Jeremy Ashkenas, DocumentCloud Inc.
  // Backbone may be freely distributed under the MIT license.
  // For all details and documentation:
  // http://backbonejs.org
  (function () {
    var l = this, y = l.Backbone, z = Array.prototype.slice, A = Array.prototype.splice, g;
    g = "undefined" !== typeof exports ? exports : l.Backbone = {};
    g.VERSION = "0.9.2";
    var f = l._;
    !f && "undefined" !== typeof require && (f = require("underscore"));
    var i = l.jQuery || l.Zepto || l.ender;
    g.setDomLibrary = function (a) {
      i = a
    };
    g.noConflict = function () {
      l.Backbone = y;
      return this
    };
    g.emulateHTTP = !1;
    g.emulateJSON = !1;
    var p = /\s+/, k = g.Events = {
      on: function (a, b, c) {
        var d, e, f, g, j;
        if (!b)return this;
        a = a.split(p);
        for (d = this._callbacks || (this._callbacks =
          {}); e = a.shift();)f = (j = d[e]) ? j.tail : {}, f.next = g = {}, f.context = c, f.callback = b, d[e] = {
          tail: g,
          next: j ? j.next : f
        };
        return this
      }, off: function (a, b, c) {
        var d, e, h, g, j, q;
        if (e = this._callbacks) {
          if (!a && !b && !c)return delete this._callbacks, this;
          for (a = a ? a.split(p) : f.keys(e); d = a.shift();)if (h = e[d], delete e[d], h && (b || c))for (g = h.tail; (h = h.next) !== g;)if (j = h.callback, q = h.context, b && j !== b || c && q !== c)this.on(d, j, q);
          return this
        }
      }, trigger: function (a) {
        var b, c, d, e, f, g;
        if (!(d = this._callbacks))return this;
        f = d.all;
        a = a.split(p);
        for (g =
               z.call(arguments, 1); b = a.shift();) {
          if (c = d[b])for (e = c.tail; (c = c.next) !== e;)c.callback.apply(c.context || this, g);
          if (c = f) {
            e = c.tail;
            for (b = [b].concat(g); (c = c.next) !== e;)c.callback.apply(c.context || this, b)
          }
        }
        return this
      }
    };
    k.bind = k.on;
    k.unbind = k.off;
    var o = g.Model = function (a, b) {
      var c;
      a || (a = {});
      b && b.parse && (a = this.parse(a));
      if (c = n(this, "defaults"))a = f.extend({}, c, a);
      b && b.collection && (this.collection = b.collection);
      this.attributes = {};
      this._escapedAttributes = {};
      this.cid = f.uniqueId("c");
      this.changed = {};
      this._silent =
      {};
      this._pending = {};
      this.set(a, {silent: !0});
      this.changed = {};
      this._silent = {};
      this._pending = {};
      this._previousAttributes = f.clone(this.attributes);
      this.initialize.apply(this, arguments)
    };
    f.extend(o.prototype, k, {
      changed: null, _silent: null, _pending: null, idAttribute: "id", initialize: function () {
      }, toJSON: function () {
        return f.clone(this.attributes)
      }, get: function (a) {
        return this.attributes[a]
      }, escape: function (a) {
        var b;
        if (b = this._escapedAttributes[a])return b;
        b = this.get(a);
        return this._escapedAttributes[a] = f.escape(null ==
        b ? "" : "" + b)
      }, has: function (a) {
        return null != this.get(a)
      }, set: function (a, b, c) {
        var d, e;
        f.isObject(a) || null == a ? (d = a, c = b) : (d = {}, d[a] = b);
        c || (c = {});
        if (!d)return this;
        d instanceof o && (d = d.attributes);
        if (c.unset)for (e in d)d[e] = void 0;
        if (!this._validate(d, c))return !1;
        this.idAttribute in d && (this.id = d[this.idAttribute]);
        var b = c.changes = {}, h = this.attributes, g = this._escapedAttributes, j = this._previousAttributes || {};
        for (e in d) {
          a = d[e];
          if (!f.isEqual(h[e], a) || c.unset && f.has(h, e))delete g[e], (c.silent ? this._silent :
            b)[e] = !0;
          c.unset ? delete h[e] : h[e] = a;
          !f.isEqual(j[e], a) || f.has(h, e) != f.has(j, e) ? (this.changed[e] = a, c.silent || (this._pending[e] = !0)) : (delete this.changed[e], delete this._pending[e])
        }
        c.silent || this.change(c);
        return this
      }, unset: function (a, b) {
        (b || (b = {})).unset = !0;
        return this.set(a, null, b)
      }, clear: function (a) {
        (a || (a = {})).unset = !0;
        return this.set(f.clone(this.attributes), a)
      }, fetch: function (a) {
        var a = a ? f.clone(a) : {}, b = this, c = a.success;
        a.success = function (d, e, f) {
          if (!b.set(b.parse(d, f), a))return !1;
          c && c(b, d)
        };
        a.error = g.wrapError(a.error, b, a);
        return (this.sync || g.sync).call(this, "read", this, a)
      }, save: function (a, b, c) {
        var d, e;
        f.isObject(a) || null == a ? (d = a, c = b) : (d = {}, d[a] = b);
        c = c ? f.clone(c) : {};
        if (c.wait) {
          if (!this._validate(d, c))return !1;
          e = f.clone(this.attributes)
        }
        a = f.extend({}, c, {silent: !0});
        if (d && !this.set(d, c.wait ? a : c))return !1;
        var h = this, i = c.success;
        c.success = function (a, b, e) {
          b = h.parse(a, e);
          if (c.wait) {
            delete c.wait;
            b = f.extend(d || {}, b)
          }
          if (!h.set(b, c))return false;
          i ? i(h, a) : h.trigger("sync", h, a, c)
        };
        c.error = g.wrapError(c.error,
          h, c);
        b = this.isNew() ? "create" : "update";
        b = (this.sync || g.sync).call(this, b, this, c);
        c.wait && this.set(e, a);
        return b
      }, destroy: function (a) {
        var a = a ? f.clone(a) : {}, b = this, c = a.success, d = function () {
          b.trigger("destroy", b, b.collection, a)
        };
        if (this.isNew())return d(), !1;
        a.success = function (e) {
          a.wait && d();
          c ? c(b, e) : b.trigger("sync", b, e, a)
        };
        a.error = g.wrapError(a.error, b, a);
        var e = (this.sync || g.sync).call(this, "delete", this, a);
        a.wait || d();
        return e
      }, url: function () {
        var a = n(this, "urlRoot") || n(this.collection, "url") || t();
        return this.isNew() ? a : a + ("/" == a.charAt(a.length - 1) ? "" : "/") + encodeURIComponent(this.id)
      }, parse: function (a) {
        return a
      }, clone: function () {
        return new this.constructor(this.attributes)
      }, isNew: function () {
        return null == this.id
      }, change: function (a) {
        a || (a = {});
        var b = this._changing;
        this._changing = !0;
        for (var c in this._silent)this._pending[c] = !0;
        var d = f.extend({}, a.changes, this._silent);
        this._silent = {};
        for (c in d)this.trigger("change:" + c, this, this.get(c), a);
        if (b)return this;
        for (; !f.isEmpty(this._pending);) {
          this._pending =
          {};
          this.trigger("change", this, a);
          for (c in this.changed)!this._pending[c] && !this._silent[c] && delete this.changed[c];
          this._previousAttributes = f.clone(this.attributes)
        }
        this._changing = !1;
        return this
      }, hasChanged: function (a) {
        return !arguments.length ? !f.isEmpty(this.changed) : f.has(this.changed, a)
      }, changedAttributes: function (a) {
        if (!a)return this.hasChanged() ? f.clone(this.changed) : !1;
        var b, c = !1, d = this._previousAttributes, e;
        for (e in a)if (!f.isEqual(d[e], b = a[e]))(c || (c = {}))[e] = b;
        return c
      }, previous: function (a) {
        return !arguments.length || !this._previousAttributes ? null : this._previousAttributes[a]
      }, previousAttributes: function () {
        return f.clone(this._previousAttributes)
      }, isValid: function () {
        return !this.validate(this.attributes)
      }, _validate: function (a, b) {
        if (b.silent || !this.validate)return !0;
        var a = f.extend({}, this.attributes, a), c = this.validate(a, b);
        if (!c)return !0;
        b && b.error ? b.error(this, c, b) : this.trigger("error", this, c, b);
        return !1
      }
    });
    var r = g.Collection = function (a, b) {
      b || (b = {});
      b.model && (this.model = b.model);
      b.comparator && (this.comparator = b.comparator);
      this._reset();
      this.initialize.apply(this, arguments);
      a && this.reset(a, {silent: !0, parse: b.parse})
    };
    f.extend(r.prototype, k, {
      model: o, initialize: function () {
      }, toJSON: function (a) {
        return this.map(function (b) {
          return b.toJSON(a)
        })
      }, add: function (a, b) {
        var c, d, e, g, i, j = {}, k = {}, l = [];
        b || (b = {});
        a = f.isArray(a) ? a.slice() : [a];
        c = 0;
        for (d = a.length; c < d; c++) {
          if (!(e = a[c] = this._prepareModel(a[c], b)))throw Error("Can't add an invalid model to a collection");
          g = e.cid;
          i = e.id;
          j[g] || this._byCid[g] || null != i && (k[i] || this._byId[i]) ?
            l.push(c) : j[g] = k[i] = e
        }
        for (c = l.length; c--;)a.splice(l[c], 1);
        c = 0;
        for (d = a.length; c < d; c++)(e = a[c]).on("all", this._onModelEvent, this), this._byCid[e.cid] = e, null != e.id && (this._byId[e.id] = e);
        this.length += d;
        A.apply(this.models, [null != b.at ? b.at : this.models.length, 0].concat(a));
        this.comparator && this.sort({silent: !0});
        if (b.silent)return this;
        c = 0;
        for (d = this.models.length; c < d; c++)if (j[(e = this.models[c]).cid])b.index = c, e.trigger("add", e, this, b);
        return this
      }, remove: function (a, b) {
        var c, d, e, g;
        b || (b = {});
        a = f.isArray(a) ?
          a.slice() : [a];
        c = 0;
        for (d = a.length; c < d; c++)if (g = this.getByCid(a[c]) || this.get(a[c]))delete this._byId[g.id], delete this._byCid[g.cid], e = this.indexOf(g), this.models.splice(e, 1), this.length--, b.silent || (b.index = e, g.trigger("remove", g, this, b)), this._removeReference(g);
        return this
      }, push: function (a, b) {
        a = this._prepareModel(a, b);
        this.add(a, b);
        return a
      }, pop: function (a) {
        var b = this.at(this.length - 1);
        this.remove(b, a);
        return b
      }, unshift: function (a, b) {
        a = this._prepareModel(a, b);
        this.add(a, f.extend({at: 0}, b));
        return a
      },
      shift: function (a) {
        var b = this.at(0);
        this.remove(b, a);
        return b
      }, get: function (a) {
        return null == a ? void 0 : this._byId[null != a.id ? a.id : a]
      }, getByCid: function (a) {
        return a && this._byCid[a.cid || a]
      }, at: function (a) {
        return this.models[a]
      }, where: function (a) {
        return f.isEmpty(a) ? [] : this.filter(function (b) {
          for (var c in a)if (a[c] !== b.get(c))return !1;
          return !0
        })
      }, sort: function (a) {
        a || (a = {});
        if (!this.comparator)throw Error("Cannot sort a set without a comparator");
        var b = f.bind(this.comparator, this);
        1 == this.comparator.length ?
          this.models = this.sortBy(b) : this.models.sort(b);
        a.silent || this.trigger("reset", this, a);
        return this
      }, pluck: function (a) {
        return f.map(this.models, function (b) {
          return b.get(a)
        })
      }, reset: function (a, b) {
        a || (a = []);
        b || (b = {});
        for (var c = 0, d = this.models.length; c < d; c++)this._removeReference(this.models[c]);
        this._reset();
        this.add(a, f.extend({silent: !0}, b));
        b.silent || this.trigger("reset", this, b);
        return this
      }, fetch: function (a) {
        a = a ? f.clone(a) : {};
        void 0 === a.parse && (a.parse = !0);
        var b = this, c = a.success;
        a.success = function (d,
                              e, f) {
          b[a.add ? "add" : "reset"](b.parse(d, f), a);
          c && c(b, d)
        };
        a.error = g.wrapError(a.error, b, a);
        return (this.sync || g.sync).call(this, "read", this, a)
      }, create: function (a, b) {
        var c = this, b = b ? f.clone(b) : {}, a = this._prepareModel(a, b);
        if (!a)return !1;
        b.wait || c.add(a, b);
        var d = b.success;
        b.success = function (e, f) {
          b.wait && c.add(e, b);
          d ? d(e, f) : e.trigger("sync", a, f, b)
        };
        a.save(null, b);
        return a
      }, parse: function (a) {
        return a
      }, chain: function () {
        return f(this.models).chain()
      }, _reset: function () {
        this.length = 0;
        this.models = [];
        this._byId =
        {};
        this._byCid = {}
      }, _prepareModel: function (a, b) {
        b || (b = {});
        a instanceof o ? a.collection || (a.collection = this) : (b.collection = this, a = new this.model(a, b), a._validate(a.attributes, b) || (a = !1));
        return a
      }, _removeReference: function (a) {
        this == a.collection && delete a.collection;
        a.off("all", this._onModelEvent, this)
      }, _onModelEvent: function (a, b, c, d) {
        ("add" == a || "remove" == a) && c != this || ("destroy" == a && this.remove(b, d), b && a === "change:" + b.idAttribute && (delete this._byId[b.previous(b.idAttribute)], this._byId[b.id] = b), this.trigger.apply(this,
          arguments))
      }
    });
    f.each("forEach,each,map,reduce,reduceRight,find,detect,filter,select,reject,every,all,some,any,include,contains,invoke,max,min,sortBy,sortedIndex,toArray,size,first,initial,rest,last,without,indexOf,shuffle,lastIndexOf,isEmpty,groupBy".split(","), function (a) {
      r.prototype[a] = function () {
        return f[a].apply(f, [this.models].concat(f.toArray(arguments)))
      }
    });
    var u = g.Router = function (a) {
        a || (a = {});
        a.routes && (this.routes = a.routes);
        this._bindRoutes();
        this.initialize.apply(this, arguments)
      }, B = /:\w+/g,
      C = /\*\w+/g, D = /[-[\]{}()+?.,\\^$|#\s]/g;
    f.extend(u.prototype, k, {
      initialize: function () {
      }, route: function (a, b, c) {
        g.history || (g.history = new m);
        f.isRegExp(a) || (a = this._routeToRegExp(a));
        c || (c = this[b]);
        g.history.route(a, f.bind(function (d) {
          d = this._extractParameters(a, d);
          c && c.apply(this, d);
          this.trigger.apply(this, ["route:" + b].concat(d));
          g.history.trigger("route", this, b, d)
        }, this));
        return this
      }, navigate: function (a, b) {
        g.history.navigate(a, b)
      }, _bindRoutes: function () {
        if (this.routes) {
          var a = [], b;
          for (b in this.routes)a.unshift([b,
            this.routes[b]]);
          b = 0;
          for (var c = a.length; b < c; b++)this.route(a[b][0], a[b][1], this[a[b][1]])
        }
      }, _routeToRegExp: function (a) {
        a = a.replace(D, "\\$&").replace(B, "([^/]+)").replace(C, "(.*?)");
        return RegExp("^" + a + "$")
      }, _extractParameters: function (a, b) {
        return a.exec(b).slice(1)
      }
    });
    var m = g.History = function () {
      this.handlers = [];
      f.bindAll(this, "checkUrl")
    }, s = /^[#\/]/, E = /msie [\w.]+/;
    m.started = !1;
    f.extend(m.prototype, k, {
      interval: 50, getHash: function (a) {
        return (a = (a ? a.location : window.location).href.match(/#(.*)$/)) ? a[1] :
          ""
      }, getFragment: function (a, b) {
        if (null == a)if (this._hasPushState || b) {
          var a = window.location.pathname, c = window.location.search;
          c && (a += c)
        } else a = this.getHash();
        a.indexOf(this.options.root) || (a = a.substr(this.options.root.length));
        return a.replace(s, "")
      }, start: function (a) {
        if (m.started)throw Error("Backbone.history has already been started");
        m.started = !0;
        this.options = f.extend({}, {root: "/"}, this.options, a);
        this._wantsHashChange = !1 !== this.options.hashChange;
        this._wantsPushState = !!this.options.pushState;
        this._hasPushState = !(!this.options.pushState || !window.history || !window.history.pushState);
        var a = this.getFragment(), b = document.documentMode;
        if (b = E.exec(navigator.userAgent.toLowerCase()) && (!b || 7 >= b))this.iframe = i('<iframe src="javascript:0" tabindex="-1" />').hide().appendTo("body")[0].contentWindow, this.navigate(a);
        this._hasPushState ? i(window).bind("popstate", this.checkUrl) : this._wantsHashChange && "onhashchange" in window && !b ? i(window).bind("hashchange", this.checkUrl) : this._wantsHashChange && (this._checkUrlInterval = setInterval(this.checkUrl,
          this.interval));
        this.fragment = a;
        a = window.location;
        b = a.pathname == this.options.root;
        if (this._wantsHashChange && this._wantsPushState && !this._hasPushState && !b)return this.fragment = this.getFragment(null, !0), window.location.replace(this.options.root + "#" + this.fragment), !0;
        this._wantsPushState && this._hasPushState && b && a.hash && (this.fragment = this.getHash().replace(s, ""), window.history.replaceState({}, document.title, a.protocol + "//" + a.host + this.options.root + this.fragment));
        if (!this.options.silent)return this.loadUrl()
      },
      stop: function () {
        i(window).unbind("popstate", this.checkUrl).unbind("hashchange", this.checkUrl);
        clearInterval(this._checkUrlInterval);
        m.started = !1
      }, route: function (a, b) {
        this.handlers.unshift({route: a, callback: b})
      }, checkUrl: function () {
        var a = this.getFragment();
        a == this.fragment && this.iframe && (a = this.getFragment(this.getHash(this.iframe)));
        if (a == this.fragment)return !1;
        this.iframe && this.navigate(a);
        this.loadUrl() || this.loadUrl(this.getHash())
      }, loadUrl: function (a) {
        var b = this.fragment = this.getFragment(a);
        return f.any(this.handlers,
          function (a) {
            if (a.route.test(b))return a.callback(b), !0
          })
      }, navigate: function (a, b) {
        if (!m.started)return !1;
        if (!b || !0 === b)b = {trigger: b};
        var c = (a || "").replace(s, "");
        this.fragment != c && (this._hasPushState ? (0 != c.indexOf(this.options.root) && (c = this.options.root + c), this.fragment = c, window.history[b.replace ? "replaceState" : "pushState"]({}, document.title, c)) : this._wantsHashChange ? (this.fragment = c, this._updateHash(window.location, c, b.replace), this.iframe && c != this.getFragment(this.getHash(this.iframe)) && (b.replace ||
        this.iframe.document.open().close(), this._updateHash(this.iframe.location, c, b.replace))) : window.location.assign(this.options.root + a), b.trigger && this.loadUrl(a))
      }, _updateHash: function (a, b, c) {
        c ? a.replace(a.toString().replace(/(javascript:|#).*$/, "") + "#" + b) : a.hash = b
      }
    });
    var v = g.View = function (a) {
      this.cid = f.uniqueId("view");
      this._configure(a || {});
      this._ensureElement();
      this.initialize.apply(this, arguments);
      this.delegateEvents()
    }, F = /^(\S+)\s*(.*)$/, w = "model,collection,el,id,attributes,className,tagName".split(",");
    f.extend(v.prototype, k, {
      tagName: "div", $: function (a) {
        return this.$el.find(a)
      }, initialize: function () {
      }, render: function () {
        return this
      }, remove: function () {
        this.$el.remove();
        return this
      }, make: function (a, b, c) {
        a = document.createElement(a);
        b && i(a).attr(b);
        c && i(a).html(c);
        return a
      }, setElement: function (a, b) {
        this.$el && this.undelegateEvents();
        this.$el = a instanceof i ? a : i(a);
        this.el = this.$el[0];
        !1 !== b && this.delegateEvents();
        return this
      }, delegateEvents: function (a) {
        if (a || (a = n(this, "events"))) {
          this.undelegateEvents();
          for (var b in a) {
            var c = a[b];
            f.isFunction(c) || (c = this[a[b]]);
            if (!c)throw Error('Method "' + a[b] + '" does not exist');
            var d = b.match(F), e = d[1], d = d[2], c = f.bind(c, this), e = e + (".delegateEvents" + this.cid);
            "" === d ? this.$el.bind(e, c) : this.$el.delegate(d, e, c)
          }
        }
      }, undelegateEvents: function () {
        this.$el.unbind(".delegateEvents" + this.cid)
      }, _configure: function (a) {
        this.options && (a = f.extend({}, this.options, a));
        for (var b = 0, c = w.length; b < c; b++) {
          var d = w[b];
          a[d] && (this[d] = a[d])
        }
        this.options = a
      }, _ensureElement: function () {
        if (this.el)this.setElement(this.el,
          !1); else {
          var a = n(this, "attributes") || {};
          this.id && (a.id = this.id);
          this.className && (a["class"] = this.className);
          this.setElement(this.make(this.tagName, a), !1)
        }
      }
    });
    o.extend = r.extend = u.extend = v.extend = function (a, b) {
      var c = G(this, a, b);
      c.extend = this.extend;
      return c
    };
    var H = {create: "POST", update: "PUT", "delete": "DELETE", read: "GET"};
    g.sync = function (a, b, c) {
      var d = H[a];
      c || (c = {});
      var e = {type: d, dataType: "json"};
      c.url || (e.url = n(b, "url") || t());
      if (!c.data && b && ("create" == a || "update" == a))e.contentType = "application/json",
        e.data = JSON.stringify(b.toJSON());
      g.emulateJSON && (e.contentType = "application/x-www-form-urlencoded", e.data = e.data ? {model: e.data} : {});
      if (g.emulateHTTP && ("PUT" === d || "DELETE" === d))g.emulateJSON && (e.data._method = d), e.type = "POST", e.beforeSend = function (a) {
        a.setRequestHeader("X-HTTP-Method-Override", d)
      };
      "GET" !== e.type && !g.emulateJSON && (e.processData = !1);
      return i.ajax(f.extend(e, c))
    };
    g.wrapError = function (a, b, c) {
      return function (d, e) {
        e = d === b ? e : d;
        a ? a(b, e, c) : b.trigger("error", b, e, c)
      }
    };
    var x = function () {
    }, G = function (a,
                     b, c) {
      var d;
      d = b && b.hasOwnProperty("constructor") ? b.constructor : function () {
        a.apply(this, arguments)
      };
      f.extend(d, a);
      x.prototype = a.prototype;
      d.prototype = new x;
      b && f.extend(d.prototype, b);
      c && f.extend(d, c);
      d.prototype.constructor = d;
      d.__super__ = a.prototype;
      return d
    }, n = function (a, b) {
      return !a || !a[b] ? null : f.isFunction(a[b]) ? a[b]() : a[b]
    }, t = function () {
      throw Error('A "url" property or function must be specified');
    }
  }).call(this);
  