5002 lines
230 KiB
HTML
5002 lines
230 KiB
HTML
<!DOCTYPE html>
|
||
|
||
<html>
|
||
<head>
|
||
<title>backbone.js</title>
|
||
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
||
<meta name="viewport" content="width=device-width, target-densitydpi=160dpi, initial-scale=1.0; maximum-scale=1.0; user-scalable=0;">
|
||
<link rel="stylesheet" media="all" href="docco.css" />
|
||
</head>
|
||
<body>
|
||
<div id="container">
|
||
<div id="background"></div>
|
||
|
||
<ul class="sections">
|
||
|
||
<li id="title">
|
||
<div class="annotation">
|
||
<h1>backbone.js</h1>
|
||
</div>
|
||
</li>
|
||
|
||
|
||
|
||
<li id="section-1">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-1">¶</a>
|
||
</div>
|
||
<pre><code>Backbone.js <span class="hljs-number">1.3</span><span class="hljs-number">.3</span>
|
||
</code></pre>
|
||
</div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-2">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-2">¶</a>
|
||
</div>
|
||
<pre><code>(c) <span class="hljs-number">2010</span><span class="hljs-number">-2016</span> Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
|
||
Backbone may be freely distributed under the MIT license.
|
||
For all details and documentation:
|
||
http:<span class="hljs-comment">//backbonejs.org</span>
|
||
</code></pre>
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre>
|
||
(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">factory</span>) </span>{</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-3">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-3">¶</a>
|
||
</div>
|
||
<p>Establish the root object, <code>window</code> (<code>self</code>) in the browser, or <code>global</code> on the server.
|
||
We use <code>self</code> instead of <code>window</code> for <code>WebWorker</code> support.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> root = (<span class="hljs-keyword">typeof</span> self == <span class="hljs-string">'object'</span> && self.self === self && self) ||
|
||
(<span class="hljs-keyword">typeof</span> global == <span class="hljs-string">'object'</span> && global.global === global && global);</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-4">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-4">¶</a>
|
||
</div>
|
||
<p>Set up Backbone appropriately for the environment. Start with AMD.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> define === <span class="hljs-string">'function'</span> && define.amd) {
|
||
define([<span class="hljs-string">'underscore'</span>, <span class="hljs-string">'jquery'</span>, <span class="hljs-string">'exports'</span>], <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">_, $, exports</span>) </span>{</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-5">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-5">¶</a>
|
||
</div>
|
||
<p>Export global even in AMD case in case this script is loaded with
|
||
others that may still expect a global Backbone.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> root.Backbone = factory(root, exports, _, $);
|
||
});</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-6">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-6">¶</a>
|
||
</div>
|
||
<p>Next for Node.js or CommonJS. jQuery may not be needed as a module.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> exports !== <span class="hljs-string">'undefined'</span>) {
|
||
<span class="hljs-keyword">var</span> _ = <span class="hljs-built_in">require</span>(<span class="hljs-string">'underscore'</span>), $;
|
||
<span class="hljs-keyword">try</span> { $ = <span class="hljs-built_in">require</span>(<span class="hljs-string">'jquery'</span>); } <span class="hljs-keyword">catch</span> (e) {}
|
||
factory(root, exports, _, $);</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-7">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-7">¶</a>
|
||
</div>
|
||
<p>Finally, as a browser global.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> } <span class="hljs-keyword">else</span> {
|
||
root.Backbone = factory(root, {}, root._, (root.jQuery || root.Zepto || root.ender || root.$));
|
||
}
|
||
|
||
})(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">root, Backbone, _, $</span>) </span>{</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-8">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-8">¶</a>
|
||
</div>
|
||
<h2 id="initial-setup">Initial Setup</h2>
|
||
|
||
</div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-9">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-9">¶</a>
|
||
</div>
|
||
|
||
</div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-10">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-10">¶</a>
|
||
</div>
|
||
<p>Save the previous value of the <code>Backbone</code> variable, so that it can be
|
||
restored later on, if <code>noConflict</code> is used.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> previousBackbone = root.Backbone;</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-11">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-11">¶</a>
|
||
</div>
|
||
<p>Create a local reference to a common array method we’ll want to use later.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> slice = <span class="hljs-built_in">Array</span>.prototype.slice;</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-12">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-12">¶</a>
|
||
</div>
|
||
<p>Current version of the library. Keep in sync with <code>package.json</code>.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> Backbone.VERSION = <span class="hljs-string">'1.3.3'</span>;</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-13">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-13">¶</a>
|
||
</div>
|
||
<p>For Backbone’s purposes, jQuery, Zepto, Ender, or My Library (kidding) owns
|
||
the <code>$</code> variable.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> Backbone.$ = $;</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-14">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-14">¶</a>
|
||
</div>
|
||
<p>Runs Backbone.js in <em>noConflict</em> mode, returning the <code>Backbone</code> variable
|
||
to its previous owner. Returns a reference to this Backbone object.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> Backbone.noConflict = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
|
||
root.Backbone = previousBackbone;
|
||
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
|
||
};</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-15">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-15">¶</a>
|
||
</div>
|
||
<p>Turn on <code>emulateHTTP</code> to support legacy HTTP servers. Setting this option
|
||
will fake <code>"PATCH"</code>, <code>"PUT"</code> and <code>"DELETE"</code> requests via the <code>_method</code> parameter and
|
||
set a <code>X-Http-Method-Override</code> header.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> Backbone.emulateHTTP = <span class="hljs-literal">false</span>;</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-16">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-16">¶</a>
|
||
</div>
|
||
<p>Turn on <code>emulateJSON</code> to support legacy servers that can’t deal with direct
|
||
<code>application/json</code> requests … this will encode the body as
|
||
<code>application/x-www-form-urlencoded</code> instead and will send the model in a
|
||
form param named <code>model</code>.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> Backbone.emulateJSON = <span class="hljs-literal">false</span>;</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-17">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-17">¶</a>
|
||
</div>
|
||
<p>Proxy Backbone class methods to Underscore functions, wrapping the model’s
|
||
<code>attributes</code> object or collection’s <code>models</code> array behind the scenes.</p>
|
||
<p>collection.filter(function(model) { return model.get(‘age’) > 10 });
|
||
collection.each(this.addView);</p>
|
||
<p><code>Function#apply</code> can be slow so we use the method’s arg count, if we know it.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> addMethod = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">length, method, attribute</span>) </span>{
|
||
<span class="hljs-keyword">switch</span> (length) {
|
||
<span class="hljs-keyword">case</span> <span class="hljs-number">1</span>: <span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
|
||
<span class="hljs-keyword">return</span> _[method](<span class="hljs-keyword">this</span>[attribute]);
|
||
};
|
||
<span class="hljs-keyword">case</span> <span class="hljs-number">2</span>: <span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">value</span>) </span>{
|
||
<span class="hljs-keyword">return</span> _[method](<span class="hljs-keyword">this</span>[attribute], value);
|
||
};
|
||
<span class="hljs-keyword">case</span> <span class="hljs-number">3</span>: <span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">iteratee, context</span>) </span>{
|
||
<span class="hljs-keyword">return</span> _[method](<span class="hljs-keyword">this</span>[attribute], cb(iteratee, <span class="hljs-keyword">this</span>), context);
|
||
};
|
||
<span class="hljs-keyword">case</span> <span class="hljs-number">4</span>: <span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">iteratee, defaultVal, context</span>) </span>{
|
||
<span class="hljs-keyword">return</span> _[method](<span class="hljs-keyword">this</span>[attribute], cb(iteratee, <span class="hljs-keyword">this</span>), defaultVal, context);
|
||
};
|
||
<span class="hljs-keyword">default</span>: <span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
|
||
<span class="hljs-keyword">var</span> args = slice.call(<span class="hljs-built_in">arguments</span>);
|
||
args.unshift(<span class="hljs-keyword">this</span>[attribute]);
|
||
<span class="hljs-keyword">return</span> _[method].apply(_, args);
|
||
};
|
||
}
|
||
};
|
||
<span class="hljs-keyword">var</span> addUnderscoreMethods = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">Class, methods, attribute</span>) </span>{
|
||
_.each(methods, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">length, method</span>) </span>{
|
||
<span class="hljs-keyword">if</span> (_[method]) Class.prototype[method] = addMethod(length, method, attribute);
|
||
});
|
||
};</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-18">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-18">¶</a>
|
||
</div>
|
||
<p>Support <code>collection.sortBy('attr')</code> and <code>collection.findWhere({id: 1})</code>.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> cb = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">iteratee, instance</span>) </span>{
|
||
<span class="hljs-keyword">if</span> (_.isFunction(iteratee)) <span class="hljs-keyword">return</span> iteratee;
|
||
<span class="hljs-keyword">if</span> (_.isObject(iteratee) && !instance._isModel(iteratee)) <span class="hljs-keyword">return</span> modelMatcher(iteratee);
|
||
<span class="hljs-keyword">if</span> (_.isString(iteratee)) <span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">model</span>) </span>{ <span class="hljs-keyword">return</span> model.get(iteratee); };
|
||
<span class="hljs-keyword">return</span> iteratee;
|
||
};
|
||
<span class="hljs-keyword">var</span> modelMatcher = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">attrs</span>) </span>{
|
||
<span class="hljs-keyword">var</span> matcher = _.matches(attrs);
|
||
<span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">model</span>) </span>{
|
||
<span class="hljs-keyword">return</span> matcher(model.attributes);
|
||
};
|
||
};</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-19">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-19">¶</a>
|
||
</div>
|
||
<h2 id="backbone-events">Backbone.Events</h2>
|
||
|
||
</div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-20">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-20">¶</a>
|
||
</div>
|
||
|
||
</div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-21">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-21">¶</a>
|
||
</div>
|
||
<p>A module that can be mixed in to <em>any object</em> in order to provide it with
|
||
a custom event channel. You may bind a callback to an event with <code>on</code> or
|
||
remove with <code>off</code>; <code>trigger</code>-ing an event fires all callbacks in
|
||
succession.</p>
|
||
<pre><code><span class="hljs-keyword">var</span> object = {};
|
||
_.extend(object, Backbone.Events);
|
||
object.on(<span class="hljs-string">'expand'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>)</span>{ alert(<span class="hljs-string">'expanded'</span>); });
|
||
object.trigger(<span class="hljs-string">'expand'</span>);
|
||
</code></pre>
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> Events = Backbone.Events = {};</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-22">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-22">¶</a>
|
||
</div>
|
||
<p>Regular expression used to split event strings.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> eventSplitter = <span class="hljs-regexp">/\s+/</span>;</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-23">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-23">¶</a>
|
||
</div>
|
||
<p>Iterates over the standard <code>event, callback</code> (as well as the fancy multiple
|
||
space-separated events <code>"change blur", callback</code> and jQuery-style event
|
||
maps <code>{event: callback}</code>).</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> eventsApi = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">iteratee, events, name, callback, opts</span>) </span>{
|
||
<span class="hljs-keyword">var</span> i = <span class="hljs-number">0</span>, names;
|
||
<span class="hljs-keyword">if</span> (name && <span class="hljs-keyword">typeof</span> name === <span class="hljs-string">'object'</span>) {</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-24">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-24">¶</a>
|
||
</div>
|
||
<p>Handle event maps.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (callback !== <span class="hljs-keyword">void</span> <span class="hljs-number">0</span> && <span class="hljs-string">'context'</span> <span class="hljs-keyword">in</span> opts && opts.context === <span class="hljs-keyword">void</span> <span class="hljs-number">0</span>) opts.context = callback;
|
||
<span class="hljs-keyword">for</span> (names = _.keys(name); i < names.length ; i++) {
|
||
events = eventsApi(iteratee, events, names[i], name[names[i]], opts);
|
||
}
|
||
} <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (name && eventSplitter.test(name)) {</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-25">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-25">¶</a>
|
||
</div>
|
||
<p>Handle space-separated event names by delegating them individually.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">for</span> (names = name.split(eventSplitter); i < names.length; i++) {
|
||
events = iteratee(events, names[i], callback, opts);
|
||
}
|
||
} <span class="hljs-keyword">else</span> {</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-26">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-26">¶</a>
|
||
</div>
|
||
<p>Finally, standard events.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> events = iteratee(events, name, callback, opts);
|
||
}
|
||
<span class="hljs-keyword">return</span> events;
|
||
};</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-27">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-27">¶</a>
|
||
</div>
|
||
<p>Bind an event to a <code>callback</code> function. Passing <code>"all"</code> will bind
|
||
the callback to all events fired.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> Events.on = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">name, callback, context</span>) </span>{
|
||
<span class="hljs-keyword">return</span> internalOn(<span class="hljs-keyword">this</span>, name, callback, context);
|
||
};</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-28">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-28">¶</a>
|
||
</div>
|
||
<p>Guard the <code>listening</code> argument from the public API.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> internalOn = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">obj, name, callback, context, listening</span>) </span>{
|
||
obj._events = eventsApi(onApi, obj._events || {}, name, callback, {
|
||
context: context,
|
||
ctx: obj,
|
||
listening: listening
|
||
});
|
||
|
||
<span class="hljs-keyword">if</span> (listening) {
|
||
<span class="hljs-keyword">var</span> listeners = obj._listeners || (obj._listeners = {});
|
||
listeners[listening.id] = listening;
|
||
}
|
||
|
||
<span class="hljs-keyword">return</span> obj;
|
||
};</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-29">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-29">¶</a>
|
||
</div>
|
||
<p>Inversion-of-control versions of <code>on</code>. Tell <em>this</em> object to listen to
|
||
an event in another object… keeping track of what it’s listening to
|
||
for easier unbinding later.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> Events.listenTo = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">obj, name, callback</span>) </span>{
|
||
<span class="hljs-keyword">if</span> (!obj) <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
|
||
<span class="hljs-keyword">var</span> id = obj._listenId || (obj._listenId = _.uniqueId(<span class="hljs-string">'l'</span>));
|
||
<span class="hljs-keyword">var</span> listeningTo = <span class="hljs-keyword">this</span>._listeningTo || (<span class="hljs-keyword">this</span>._listeningTo = {});
|
||
<span class="hljs-keyword">var</span> listening = listeningTo[id];</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-30">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-30">¶</a>
|
||
</div>
|
||
<p>This object is not listening to any other events on <code>obj</code> yet.
|
||
Setup the necessary references to track the listening callbacks.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (!listening) {
|
||
<span class="hljs-keyword">var</span> thisId = <span class="hljs-keyword">this</span>._listenId || (<span class="hljs-keyword">this</span>._listenId = _.uniqueId(<span class="hljs-string">'l'</span>));
|
||
listening = listeningTo[id] = {obj: obj, objId: id, id: thisId, listeningTo: listeningTo, count: <span class="hljs-number">0</span>};
|
||
}</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-31">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-31">¶</a>
|
||
</div>
|
||
<p>Bind callbacks on obj, and keep track of them on listening.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> internalOn(obj, name, callback, <span class="hljs-keyword">this</span>, listening);
|
||
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
|
||
};</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-32">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-32">¶</a>
|
||
</div>
|
||
<p>The reducing API that adds a callback to the <code>events</code> object.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> onApi = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">events, name, callback, options</span>) </span>{
|
||
<span class="hljs-keyword">if</span> (callback) {
|
||
<span class="hljs-keyword">var</span> handlers = events[name] || (events[name] = []);
|
||
<span class="hljs-keyword">var</span> context = options.context, ctx = options.ctx, listening = options.listening;
|
||
<span class="hljs-keyword">if</span> (listening) listening.count++;
|
||
|
||
handlers.push({callback: callback, context: context, ctx: context || ctx, listening: listening});
|
||
}
|
||
<span class="hljs-keyword">return</span> events;
|
||
};</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-33">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-33">¶</a>
|
||
</div>
|
||
<p>Remove one or many callbacks. If <code>context</code> is null, removes all
|
||
callbacks with that function. If <code>callback</code> is null, removes all
|
||
callbacks for the event. If <code>name</code> is null, removes all bound
|
||
callbacks for all events.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> Events.off = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">name, callback, context</span>) </span>{
|
||
<span class="hljs-keyword">if</span> (!<span class="hljs-keyword">this</span>._events) <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
|
||
<span class="hljs-keyword">this</span>._events = eventsApi(offApi, <span class="hljs-keyword">this</span>._events, name, callback, {
|
||
context: context,
|
||
listeners: <span class="hljs-keyword">this</span>._listeners
|
||
});
|
||
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
|
||
};</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-34">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-34">¶</a>
|
||
</div>
|
||
<p>Tell this object to stop listening to either specific events … or
|
||
to every object it’s currently listening to.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> Events.stopListening = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">obj, name, callback</span>) </span>{
|
||
<span class="hljs-keyword">var</span> listeningTo = <span class="hljs-keyword">this</span>._listeningTo;
|
||
<span class="hljs-keyword">if</span> (!listeningTo) <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
|
||
|
||
<span class="hljs-keyword">var</span> ids = obj ? [obj._listenId] : _.keys(listeningTo);
|
||
|
||
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> i = <span class="hljs-number">0</span>; i < ids.length; i++) {
|
||
<span class="hljs-keyword">var</span> listening = listeningTo[ids[i]];</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-35">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-35">¶</a>
|
||
</div>
|
||
<p>If listening doesn’t exist, this object is not currently
|
||
listening to obj. Break out early.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (!listening) <span class="hljs-keyword">break</span>;
|
||
|
||
listening.obj.off(name, callback, <span class="hljs-keyword">this</span>);
|
||
}
|
||
|
||
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
|
||
};</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-36">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-36">¶</a>
|
||
</div>
|
||
<p>The reducing API that removes a callback from the <code>events</code> object.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> offApi = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">events, name, callback, options</span>) </span>{
|
||
<span class="hljs-keyword">if</span> (!events) <span class="hljs-keyword">return</span>;
|
||
|
||
<span class="hljs-keyword">var</span> i = <span class="hljs-number">0</span>, listening;
|
||
<span class="hljs-keyword">var</span> context = options.context, listeners = options.listeners;</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-37">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-37">¶</a>
|
||
</div>
|
||
<p>Delete all events listeners and “drop” events.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (!name && !callback && !context) {
|
||
<span class="hljs-keyword">var</span> ids = _.keys(listeners);
|
||
<span class="hljs-keyword">for</span> (; i < ids.length; i++) {
|
||
listening = listeners[ids[i]];
|
||
<span class="hljs-keyword">delete</span> listeners[listening.id];
|
||
<span class="hljs-keyword">delete</span> listening.listeningTo[listening.objId];
|
||
}
|
||
<span class="hljs-keyword">return</span>;
|
||
}
|
||
|
||
<span class="hljs-keyword">var</span> names = name ? [name] : _.keys(events);
|
||
<span class="hljs-keyword">for</span> (; i < names.length; i++) {
|
||
name = names[i];
|
||
<span class="hljs-keyword">var</span> handlers = events[name];</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-38">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-38">¶</a>
|
||
</div>
|
||
<p>Bail out if there are no events stored.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (!handlers) <span class="hljs-keyword">break</span>;</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-39">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-39">¶</a>
|
||
</div>
|
||
<p>Replace events if there are any remaining. Otherwise, clean up.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> remaining = [];
|
||
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> j = <span class="hljs-number">0</span>; j < handlers.length; j++) {
|
||
<span class="hljs-keyword">var</span> handler = handlers[j];
|
||
<span class="hljs-keyword">if</span> (
|
||
callback && callback !== handler.callback &&
|
||
callback !== handler.callback._callback ||
|
||
context && context !== handler.context
|
||
) {
|
||
remaining.push(handler);
|
||
} <span class="hljs-keyword">else</span> {
|
||
listening = handler.listening;
|
||
<span class="hljs-keyword">if</span> (listening && --listening.count === <span class="hljs-number">0</span>) {
|
||
<span class="hljs-keyword">delete</span> listeners[listening.id];
|
||
<span class="hljs-keyword">delete</span> listening.listeningTo[listening.objId];
|
||
}
|
||
}
|
||
}</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-40">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-40">¶</a>
|
||
</div>
|
||
<p>Update tail event if the list has any events. Otherwise, clean up.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (remaining.length) {
|
||
events[name] = remaining;
|
||
} <span class="hljs-keyword">else</span> {
|
||
<span class="hljs-keyword">delete</span> events[name];
|
||
}
|
||
}
|
||
<span class="hljs-keyword">return</span> events;
|
||
};</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-41">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-41">¶</a>
|
||
</div>
|
||
<p>Bind an event to only be triggered a single time. After the first time
|
||
the callback is invoked, its listener will be removed. If multiple events
|
||
are passed in using the space-separated syntax, the handler will fire
|
||
once for each event, not once for a combination of all events.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> Events.once = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">name, callback, context</span>) </span>{</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-42">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-42">¶</a>
|
||
</div>
|
||
<p>Map the event into a <code>{event: once}</code> object.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> events = eventsApi(onceMap, {}, name, callback, _.bind(<span class="hljs-keyword">this</span>.off, <span class="hljs-keyword">this</span>));
|
||
<span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> name === <span class="hljs-string">'string'</span> && context == <span class="hljs-literal">null</span>) callback = <span class="hljs-keyword">void</span> <span class="hljs-number">0</span>;
|
||
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.on(events, callback, context);
|
||
};</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-43">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-43">¶</a>
|
||
</div>
|
||
<p>Inversion-of-control versions of <code>once</code>.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> Events.listenToOnce = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">obj, name, callback</span>) </span>{</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-44">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-44">¶</a>
|
||
</div>
|
||
<p>Map the event into a <code>{event: once}</code> object.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> events = eventsApi(onceMap, {}, name, callback, _.bind(<span class="hljs-keyword">this</span>.stopListening, <span class="hljs-keyword">this</span>, obj));
|
||
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.listenTo(obj, events);
|
||
};</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-45">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-45">¶</a>
|
||
</div>
|
||
<p>Reduces the event callbacks into a map of <code>{event: onceWrapper}</code>.
|
||
<code>offer</code> unbinds the <code>onceWrapper</code> after it has been called.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> onceMap = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">map, name, callback, offer</span>) </span>{
|
||
<span class="hljs-keyword">if</span> (callback) {
|
||
<span class="hljs-keyword">var</span> once = map[name] = _.once(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
|
||
offer(name, once);
|
||
callback.apply(<span class="hljs-keyword">this</span>, <span class="hljs-built_in">arguments</span>);
|
||
});
|
||
once._callback = callback;
|
||
}
|
||
<span class="hljs-keyword">return</span> map;
|
||
};</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-46">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-46">¶</a>
|
||
</div>
|
||
<p>Trigger one or many events, firing all bound callbacks. Callbacks are
|
||
passed the same arguments as <code>trigger</code> is, apart from the event name
|
||
(unless you’re listening on <code>"all"</code>, which will cause your callback to
|
||
receive the true name of the event as the first argument).</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> Events.trigger = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">name</span>) </span>{
|
||
<span class="hljs-keyword">if</span> (!<span class="hljs-keyword">this</span>._events) <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
|
||
|
||
<span class="hljs-keyword">var</span> length = <span class="hljs-built_in">Math</span>.max(<span class="hljs-number">0</span>, <span class="hljs-built_in">arguments</span>.length - <span class="hljs-number">1</span>);
|
||
<span class="hljs-keyword">var</span> args = <span class="hljs-built_in">Array</span>(length);
|
||
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> i = <span class="hljs-number">0</span>; i < length; i++) args[i] = <span class="hljs-built_in">arguments</span>[i + <span class="hljs-number">1</span>];
|
||
|
||
eventsApi(triggerApi, <span class="hljs-keyword">this</span>._events, name, <span class="hljs-keyword">void</span> <span class="hljs-number">0</span>, args);
|
||
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
|
||
};</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-47">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-47">¶</a>
|
||
</div>
|
||
<p>Handles triggering the appropriate event callbacks.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> triggerApi = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">objEvents, name, callback, args</span>) </span>{
|
||
<span class="hljs-keyword">if</span> (objEvents) {
|
||
<span class="hljs-keyword">var</span> events = objEvents[name];
|
||
<span class="hljs-keyword">var</span> allEvents = objEvents.all;
|
||
<span class="hljs-keyword">if</span> (events && allEvents) allEvents = allEvents.slice();
|
||
<span class="hljs-keyword">if</span> (events) triggerEvents(events, args);
|
||
<span class="hljs-keyword">if</span> (allEvents) triggerEvents(allEvents, [name].concat(args));
|
||
}
|
||
<span class="hljs-keyword">return</span> objEvents;
|
||
};</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-48">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-48">¶</a>
|
||
</div>
|
||
<p>A difficult-to-believe, but optimized internal dispatch function for
|
||
triggering events. Tries to keep the usual cases speedy (most internal
|
||
Backbone events have 3 arguments).</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> triggerEvents = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">events, args</span>) </span>{
|
||
<span class="hljs-keyword">var</span> ev, i = <span class="hljs-number">-1</span>, l = events.length, a1 = args[<span class="hljs-number">0</span>], a2 = args[<span class="hljs-number">1</span>], a3 = args[<span class="hljs-number">2</span>];
|
||
<span class="hljs-keyword">switch</span> (args.length) {
|
||
<span class="hljs-keyword">case</span> <span class="hljs-number">0</span>: <span class="hljs-keyword">while</span> (++i < l) (ev = events[i]).callback.call(ev.ctx); <span class="hljs-keyword">return</span>;
|
||
<span class="hljs-keyword">case</span> <span class="hljs-number">1</span>: <span class="hljs-keyword">while</span> (++i < l) (ev = events[i]).callback.call(ev.ctx, a1); <span class="hljs-keyword">return</span>;
|
||
<span class="hljs-keyword">case</span> <span class="hljs-number">2</span>: <span class="hljs-keyword">while</span> (++i < l) (ev = events[i]).callback.call(ev.ctx, a1, a2); <span class="hljs-keyword">return</span>;
|
||
<span class="hljs-keyword">case</span> <span class="hljs-number">3</span>: <span class="hljs-keyword">while</span> (++i < l) (ev = events[i]).callback.call(ev.ctx, a1, a2, a3); <span class="hljs-keyword">return</span>;
|
||
<span class="hljs-keyword">default</span>: <span class="hljs-keyword">while</span> (++i < l) (ev = events[i]).callback.apply(ev.ctx, args); <span class="hljs-keyword">return</span>;
|
||
}
|
||
};</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-49">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-49">¶</a>
|
||
</div>
|
||
<p>Aliases for backwards compatibility.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> Events.bind = Events.on;
|
||
Events.unbind = Events.off;</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-50">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-50">¶</a>
|
||
</div>
|
||
<p>Allow the <code>Backbone</code> object to serve as a global event bus, for folks who
|
||
want global “pubsub” in a convenient place.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> _.extend(Backbone, Events);</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-51">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-51">¶</a>
|
||
</div>
|
||
<h2 id="backbone-model">Backbone.Model</h2>
|
||
|
||
</div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-52">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-52">¶</a>
|
||
</div>
|
||
|
||
</div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-53">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-53">¶</a>
|
||
</div>
|
||
<p>Backbone <strong>Models</strong> are the basic data object in the framework –
|
||
frequently representing a row in a table in a database on your server.
|
||
A discrete chunk of data and a bunch of useful, related methods for
|
||
performing computations and transformations on that data.</p>
|
||
|
||
</div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-54">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-54">¶</a>
|
||
</div>
|
||
<p>Create a new model with the specified attributes. A client id (<code>cid</code>)
|
||
is automatically generated and assigned for you.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> Model = Backbone.Model = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">attributes, options</span>) </span>{
|
||
<span class="hljs-keyword">var</span> attrs = attributes || {};
|
||
options || (options = {});
|
||
<span class="hljs-keyword">this</span>.cid = _.uniqueId(<span class="hljs-keyword">this</span>.cidPrefix);
|
||
<span class="hljs-keyword">this</span>.attributes = {};
|
||
<span class="hljs-keyword">if</span> (options.collection) <span class="hljs-keyword">this</span>.collection = options.collection;
|
||
<span class="hljs-keyword">if</span> (options.parse) attrs = <span class="hljs-keyword">this</span>.parse(attrs, options) || {};
|
||
<span class="hljs-keyword">var</span> defaults = _.result(<span class="hljs-keyword">this</span>, <span class="hljs-string">'defaults'</span>);
|
||
attrs = _.defaults(_.extend({}, defaults, attrs), defaults);
|
||
<span class="hljs-keyword">this</span>.set(attrs, options);
|
||
<span class="hljs-keyword">this</span>.changed = {};
|
||
<span class="hljs-keyword">this</span>.initialize.apply(<span class="hljs-keyword">this</span>, <span class="hljs-built_in">arguments</span>);
|
||
};</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-55">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-55">¶</a>
|
||
</div>
|
||
<p>Attach all inheritable methods to the Model prototype.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> _.extend(Model.prototype, Events, {</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-56">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-56">¶</a>
|
||
</div>
|
||
<p>A hash of attributes whose current and previous value differ.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> changed: <span class="hljs-literal">null</span>,</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-57">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-57">¶</a>
|
||
</div>
|
||
<p>The value returned during the last failed validation.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> validationError: <span class="hljs-literal">null</span>,</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-58">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-58">¶</a>
|
||
</div>
|
||
<p>The default name for the JSON <code>id</code> attribute is <code>"id"</code>. MongoDB and
|
||
CouchDB users may want to set this to <code>"_id"</code>.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> idAttribute: <span class="hljs-string">'id'</span>,</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-59">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-59">¶</a>
|
||
</div>
|
||
<p>The prefix is used to create the client id which is used to identify models locally.
|
||
You may want to override this if you’re experiencing name clashes with model ids.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> cidPrefix: <span class="hljs-string">'c'</span>,</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-60">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-60">¶</a>
|
||
</div>
|
||
<p>Initialize is an empty function by default. Override it with your own
|
||
initialization logic.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> initialize: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>)</span>{},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-61">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-61">¶</a>
|
||
</div>
|
||
<p>Return a copy of the model’s <code>attributes</code> object.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> toJSON: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">options</span>) </span>{
|
||
<span class="hljs-keyword">return</span> _.clone(<span class="hljs-keyword">this</span>.attributes);
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-62">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-62">¶</a>
|
||
</div>
|
||
<p>Proxy <code>Backbone.sync</code> by default – but override this if you need
|
||
custom syncing semantics for <em>this</em> particular model.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> sync: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
|
||
<span class="hljs-keyword">return</span> Backbone.sync.apply(<span class="hljs-keyword">this</span>, <span class="hljs-built_in">arguments</span>);
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-63">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-63">¶</a>
|
||
</div>
|
||
<p>Get the value of an attribute.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> get: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">attr</span>) </span>{
|
||
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.attributes[attr];
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-64">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-64">¶</a>
|
||
</div>
|
||
<p>Get the HTML-escaped value of an attribute.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-built_in">escape</span>: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">attr</span>) </span>{
|
||
<span class="hljs-keyword">return</span> _.escape(<span class="hljs-keyword">this</span>.get(attr));
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-65">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-65">¶</a>
|
||
</div>
|
||
<p>Returns <code>true</code> if the attribute contains a value that is not null
|
||
or undefined.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> has: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">attr</span>) </span>{
|
||
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.get(attr) != <span class="hljs-literal">null</span>;
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-66">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-66">¶</a>
|
||
</div>
|
||
<p>Special-cased proxy to underscore’s <code>_.matches</code> method.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> matches: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">attrs</span>) </span>{
|
||
<span class="hljs-keyword">return</span> !!_.iteratee(attrs, <span class="hljs-keyword">this</span>)(<span class="hljs-keyword">this</span>.attributes);
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-67">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-67">¶</a>
|
||
</div>
|
||
<p>Set a hash of model attributes on the object, firing <code>"change"</code>. This is
|
||
the core primitive operation of a model, updating the data and notifying
|
||
anyone who needs to know about the change in state. The heart of the beast.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> set: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">key, val, options</span>) </span>{
|
||
<span class="hljs-keyword">if</span> (key == <span class="hljs-literal">null</span>) <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-68">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-68">¶</a>
|
||
</div>
|
||
<p>Handle both <code>"key", value</code> and <code>{key: value}</code> -style arguments.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> attrs;
|
||
<span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> key === <span class="hljs-string">'object'</span>) {
|
||
attrs = key;
|
||
options = val;
|
||
} <span class="hljs-keyword">else</span> {
|
||
(attrs = {})[key] = val;
|
||
}
|
||
|
||
options || (options = {});</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-69">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-69">¶</a>
|
||
</div>
|
||
<p>Run validation.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (!<span class="hljs-keyword">this</span>._validate(attrs, options)) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-70">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-70">¶</a>
|
||
</div>
|
||
<p>Extract attributes and options.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> unset = options.unset;
|
||
<span class="hljs-keyword">var</span> silent = options.silent;
|
||
<span class="hljs-keyword">var</span> changes = [];
|
||
<span class="hljs-keyword">var</span> changing = <span class="hljs-keyword">this</span>._changing;
|
||
<span class="hljs-keyword">this</span>._changing = <span class="hljs-literal">true</span>;
|
||
|
||
<span class="hljs-keyword">if</span> (!changing) {
|
||
<span class="hljs-keyword">this</span>._previousAttributes = _.clone(<span class="hljs-keyword">this</span>.attributes);
|
||
<span class="hljs-keyword">this</span>.changed = {};
|
||
}
|
||
|
||
<span class="hljs-keyword">var</span> current = <span class="hljs-keyword">this</span>.attributes;
|
||
<span class="hljs-keyword">var</span> changed = <span class="hljs-keyword">this</span>.changed;
|
||
<span class="hljs-keyword">var</span> prev = <span class="hljs-keyword">this</span>._previousAttributes;</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-71">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-71">¶</a>
|
||
</div>
|
||
<p>For each <code>set</code> attribute, update or delete the current value.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> attr <span class="hljs-keyword">in</span> attrs) {
|
||
val = attrs[attr];
|
||
<span class="hljs-keyword">if</span> (!_.isEqual(current[attr], val)) changes.push(attr);
|
||
<span class="hljs-keyword">if</span> (!_.isEqual(prev[attr], val)) {
|
||
changed[attr] = val;
|
||
} <span class="hljs-keyword">else</span> {
|
||
<span class="hljs-keyword">delete</span> changed[attr];
|
||
}
|
||
unset ? <span class="hljs-keyword">delete</span> current[attr] : current[attr] = val;
|
||
}</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-72">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-72">¶</a>
|
||
</div>
|
||
<p>Update the <code>id</code>.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (<span class="hljs-keyword">this</span>.idAttribute <span class="hljs-keyword">in</span> attrs) <span class="hljs-keyword">this</span>.id = <span class="hljs-keyword">this</span>.get(<span class="hljs-keyword">this</span>.idAttribute);</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-73">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-73">¶</a>
|
||
</div>
|
||
<p>Trigger all relevant attribute changes.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (!silent) {
|
||
<span class="hljs-keyword">if</span> (changes.length) <span class="hljs-keyword">this</span>._pending = options;
|
||
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> i = <span class="hljs-number">0</span>; i < changes.length; i++) {
|
||
<span class="hljs-keyword">this</span>.trigger(<span class="hljs-string">'change:'</span> + changes[i], <span class="hljs-keyword">this</span>, current[changes[i]], options);
|
||
}
|
||
}</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-74">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-74">¶</a>
|
||
</div>
|
||
<p>You might be wondering why there’s a <code>while</code> loop here. Changes can
|
||
be recursively nested within <code>"change"</code> events.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (changing) <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
|
||
<span class="hljs-keyword">if</span> (!silent) {
|
||
<span class="hljs-keyword">while</span> (<span class="hljs-keyword">this</span>._pending) {
|
||
options = <span class="hljs-keyword">this</span>._pending;
|
||
<span class="hljs-keyword">this</span>._pending = <span class="hljs-literal">false</span>;
|
||
<span class="hljs-keyword">this</span>.trigger(<span class="hljs-string">'change'</span>, <span class="hljs-keyword">this</span>, options);
|
||
}
|
||
}
|
||
<span class="hljs-keyword">this</span>._pending = <span class="hljs-literal">false</span>;
|
||
<span class="hljs-keyword">this</span>._changing = <span class="hljs-literal">false</span>;
|
||
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-75">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-75">¶</a>
|
||
</div>
|
||
<p>Remove an attribute from the model, firing <code>"change"</code>. <code>unset</code> is a noop
|
||
if the attribute doesn’t exist.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> unset: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">attr, options</span>) </span>{
|
||
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.set(attr, <span class="hljs-keyword">void</span> <span class="hljs-number">0</span>, _.extend({}, options, {unset: <span class="hljs-literal">true</span>}));
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-76">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-76">¶</a>
|
||
</div>
|
||
<p>Clear all attributes on the model, firing <code>"change"</code>.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> clear: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">options</span>) </span>{
|
||
<span class="hljs-keyword">var</span> attrs = {};
|
||
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> key <span class="hljs-keyword">in</span> <span class="hljs-keyword">this</span>.attributes) attrs[key] = <span class="hljs-keyword">void</span> <span class="hljs-number">0</span>;
|
||
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.set(attrs, _.extend({}, options, {unset: <span class="hljs-literal">true</span>}));
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-77">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-77">¶</a>
|
||
</div>
|
||
<p>Determine if the model has changed since the last <code>"change"</code> event.
|
||
If you specify an attribute name, determine if that attribute has changed.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> hasChanged: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">attr</span>) </span>{
|
||
<span class="hljs-keyword">if</span> (attr == <span class="hljs-literal">null</span>) <span class="hljs-keyword">return</span> !_.isEmpty(<span class="hljs-keyword">this</span>.changed);
|
||
<span class="hljs-keyword">return</span> _.has(<span class="hljs-keyword">this</span>.changed, attr);
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-78">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-78">¶</a>
|
||
</div>
|
||
<p>Return an object containing all the attributes that have changed, or
|
||
false if there are no changed attributes. Useful for determining what
|
||
parts of a view need to be updated and/or what attributes need to be
|
||
persisted to the server. Unset attributes will be set to undefined.
|
||
You can also pass an attributes object to diff against the model,
|
||
determining if there <em>would be</em> a change.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> changedAttributes: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">diff</span>) </span>{
|
||
<span class="hljs-keyword">if</span> (!diff) <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.hasChanged() ? _.clone(<span class="hljs-keyword">this</span>.changed) : <span class="hljs-literal">false</span>;
|
||
<span class="hljs-keyword">var</span> old = <span class="hljs-keyword">this</span>._changing ? <span class="hljs-keyword">this</span>._previousAttributes : <span class="hljs-keyword">this</span>.attributes;
|
||
<span class="hljs-keyword">var</span> changed = {};
|
||
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> attr <span class="hljs-keyword">in</span> diff) {
|
||
<span class="hljs-keyword">var</span> val = diff[attr];
|
||
<span class="hljs-keyword">if</span> (_.isEqual(old[attr], val)) <span class="hljs-keyword">continue</span>;
|
||
changed[attr] = val;
|
||
}
|
||
<span class="hljs-keyword">return</span> _.size(changed) ? changed : <span class="hljs-literal">false</span>;
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-79">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-79">¶</a>
|
||
</div>
|
||
<p>Get the previous value of an attribute, recorded at the time the last
|
||
<code>"change"</code> event was fired.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> previous: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">attr</span>) </span>{
|
||
<span class="hljs-keyword">if</span> (attr == <span class="hljs-literal">null</span> || !<span class="hljs-keyword">this</span>._previousAttributes) <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;
|
||
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>._previousAttributes[attr];
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-80">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-80">¶</a>
|
||
</div>
|
||
<p>Get all of the attributes of the model at the time of the previous
|
||
<code>"change"</code> event.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> previousAttributes: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
|
||
<span class="hljs-keyword">return</span> _.clone(<span class="hljs-keyword">this</span>._previousAttributes);
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-81">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-81">¶</a>
|
||
</div>
|
||
<p>Fetch the model from the server, merging the response with the model’s
|
||
local attributes. Any changed attributes will trigger a “change” event.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> fetch: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">options</span>) </span>{
|
||
options = _.extend({parse: <span class="hljs-literal">true</span>}, options);
|
||
<span class="hljs-keyword">var</span> model = <span class="hljs-keyword">this</span>;
|
||
<span class="hljs-keyword">var</span> success = options.success;
|
||
options.success = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">resp</span>) </span>{
|
||
<span class="hljs-keyword">var</span> serverAttrs = options.parse ? model.parse(resp, options) : resp;
|
||
<span class="hljs-keyword">if</span> (!model.set(serverAttrs, options)) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
|
||
<span class="hljs-keyword">if</span> (success) success.call(options.context, model, resp, options);
|
||
model.trigger(<span class="hljs-string">'sync'</span>, model, resp, options);
|
||
};
|
||
wrapError(<span class="hljs-keyword">this</span>, options);
|
||
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.sync(<span class="hljs-string">'read'</span>, <span class="hljs-keyword">this</span>, options);
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-82">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-82">¶</a>
|
||
</div>
|
||
<p>Set a hash of model attributes, and sync the model to the server.
|
||
If the server returns an attributes hash that differs, the model’s
|
||
state will be <code>set</code> again.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> save: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">key, val, options</span>) </span>{</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-83">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-83">¶</a>
|
||
</div>
|
||
<p>Handle both <code>"key", value</code> and <code>{key: value}</code> -style arguments.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> attrs;
|
||
<span class="hljs-keyword">if</span> (key == <span class="hljs-literal">null</span> || <span class="hljs-keyword">typeof</span> key === <span class="hljs-string">'object'</span>) {
|
||
attrs = key;
|
||
options = val;
|
||
} <span class="hljs-keyword">else</span> {
|
||
(attrs = {})[key] = val;
|
||
}
|
||
|
||
options = _.extend({validate: <span class="hljs-literal">true</span>, parse: <span class="hljs-literal">true</span>}, options);
|
||
<span class="hljs-keyword">var</span> wait = options.wait;</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-84">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-84">¶</a>
|
||
</div>
|
||
<p>If we’re not waiting and attributes exist, save acts as
|
||
<code>set(attr).save(null, opts)</code> with validation. Otherwise, check if
|
||
the model will be valid when the attributes, if any, are set.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (attrs && !wait) {
|
||
<span class="hljs-keyword">if</span> (!<span class="hljs-keyword">this</span>.set(attrs, options)) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
|
||
} <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (!<span class="hljs-keyword">this</span>._validate(attrs, options)) {
|
||
<span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
|
||
}</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-85">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-85">¶</a>
|
||
</div>
|
||
<p>After a successful server-side save, the client is (optionally)
|
||
updated with the server-side state.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> model = <span class="hljs-keyword">this</span>;
|
||
<span class="hljs-keyword">var</span> success = options.success;
|
||
<span class="hljs-keyword">var</span> attributes = <span class="hljs-keyword">this</span>.attributes;
|
||
options.success = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">resp</span>) </span>{</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-86">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-86">¶</a>
|
||
</div>
|
||
<p>Ensure attributes are restored during synchronous saves.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> model.attributes = attributes;
|
||
<span class="hljs-keyword">var</span> serverAttrs = options.parse ? model.parse(resp, options) : resp;
|
||
<span class="hljs-keyword">if</span> (wait) serverAttrs = _.extend({}, attrs, serverAttrs);
|
||
<span class="hljs-keyword">if</span> (serverAttrs && !model.set(serverAttrs, options)) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
|
||
<span class="hljs-keyword">if</span> (success) success.call(options.context, model, resp, options);
|
||
model.trigger(<span class="hljs-string">'sync'</span>, model, resp, options);
|
||
};
|
||
wrapError(<span class="hljs-keyword">this</span>, options);</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-87">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-87">¶</a>
|
||
</div>
|
||
<p>Set temporary attributes if <code>{wait: true}</code> to properly find new ids.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (attrs && wait) <span class="hljs-keyword">this</span>.attributes = _.extend({}, attributes, attrs);
|
||
|
||
<span class="hljs-keyword">var</span> method = <span class="hljs-keyword">this</span>.isNew() ? <span class="hljs-string">'create'</span> : (options.patch ? <span class="hljs-string">'patch'</span> : <span class="hljs-string">'update'</span>);
|
||
<span class="hljs-keyword">if</span> (method === <span class="hljs-string">'patch'</span> && !options.attrs) options.attrs = attrs;
|
||
<span class="hljs-keyword">var</span> xhr = <span class="hljs-keyword">this</span>.sync(method, <span class="hljs-keyword">this</span>, options);</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-88">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-88">¶</a>
|
||
</div>
|
||
<p>Restore attributes.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">this</span>.attributes = attributes;
|
||
|
||
<span class="hljs-keyword">return</span> xhr;
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-89">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-89">¶</a>
|
||
</div>
|
||
<p>Destroy this model on the server if it was already persisted.
|
||
Optimistically removes the model from its collection, if it has one.
|
||
If <code>wait: true</code> is passed, waits for the server to respond before removal.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> destroy: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">options</span>) </span>{
|
||
options = options ? _.clone(options) : {};
|
||
<span class="hljs-keyword">var</span> model = <span class="hljs-keyword">this</span>;
|
||
<span class="hljs-keyword">var</span> success = options.success;
|
||
<span class="hljs-keyword">var</span> wait = options.wait;
|
||
|
||
<span class="hljs-keyword">var</span> destroy = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
|
||
model.stopListening();
|
||
model.trigger(<span class="hljs-string">'destroy'</span>, model, model.collection, options);
|
||
};
|
||
|
||
options.success = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">resp</span>) </span>{
|
||
<span class="hljs-keyword">if</span> (wait) destroy();
|
||
<span class="hljs-keyword">if</span> (success) success.call(options.context, model, resp, options);
|
||
<span class="hljs-keyword">if</span> (!model.isNew()) model.trigger(<span class="hljs-string">'sync'</span>, model, resp, options);
|
||
};
|
||
|
||
<span class="hljs-keyword">var</span> xhr = <span class="hljs-literal">false</span>;
|
||
<span class="hljs-keyword">if</span> (<span class="hljs-keyword">this</span>.isNew()) {
|
||
_.defer(options.success);
|
||
} <span class="hljs-keyword">else</span> {
|
||
wrapError(<span class="hljs-keyword">this</span>, options);
|
||
xhr = <span class="hljs-keyword">this</span>.sync(<span class="hljs-string">'delete'</span>, <span class="hljs-keyword">this</span>, options);
|
||
}
|
||
<span class="hljs-keyword">if</span> (!wait) destroy();
|
||
<span class="hljs-keyword">return</span> xhr;
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-90">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-90">¶</a>
|
||
</div>
|
||
<p>Default URL for the model’s representation on the server – if you’re
|
||
using Backbone’s restful methods, override this to change the endpoint
|
||
that will be called.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> url: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
|
||
<span class="hljs-keyword">var</span> base =
|
||
_.result(<span class="hljs-keyword">this</span>, <span class="hljs-string">'urlRoot'</span>) ||
|
||
_.result(<span class="hljs-keyword">this</span>.collection, <span class="hljs-string">'url'</span>) ||
|
||
urlError();
|
||
<span class="hljs-keyword">if</span> (<span class="hljs-keyword">this</span>.isNew()) <span class="hljs-keyword">return</span> base;
|
||
<span class="hljs-keyword">var</span> id = <span class="hljs-keyword">this</span>.get(<span class="hljs-keyword">this</span>.idAttribute);
|
||
<span class="hljs-keyword">return</span> base.replace(<span class="hljs-regexp">/[^\/]$/</span>, <span class="hljs-string">'$&/'</span>) + <span class="hljs-built_in">encodeURIComponent</span>(id);
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-91">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-91">¶</a>
|
||
</div>
|
||
<p><strong>parse</strong> converts a response into the hash of attributes to be <code>set</code> on
|
||
the model. The default implementation is just to pass the response along.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> parse: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">resp, options</span>) </span>{
|
||
<span class="hljs-keyword">return</span> resp;
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-92">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-92">¶</a>
|
||
</div>
|
||
<p>Create a new model with identical attributes to this one.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> clone: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
|
||
<span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-keyword">this</span>.constructor(<span class="hljs-keyword">this</span>.attributes);
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-93">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-93">¶</a>
|
||
</div>
|
||
<p>A model is new if it has never been saved to the server, and lacks an id.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> isNew: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
|
||
<span class="hljs-keyword">return</span> !<span class="hljs-keyword">this</span>.has(<span class="hljs-keyword">this</span>.idAttribute);
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-94">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-94">¶</a>
|
||
</div>
|
||
<p>Check if the model is currently in a valid state.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> isValid: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">options</span>) </span>{
|
||
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>._validate({}, _.extend({}, options, {validate: <span class="hljs-literal">true</span>}));
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-95">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-95">¶</a>
|
||
</div>
|
||
<p>Run validation against the next complete set of model attributes,
|
||
returning <code>true</code> if all is well. Otherwise, fire an <code>"invalid"</code> event.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> _validate: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">attrs, options</span>) </span>{
|
||
<span class="hljs-keyword">if</span> (!options.validate || !<span class="hljs-keyword">this</span>.validate) <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
|
||
attrs = _.extend({}, <span class="hljs-keyword">this</span>.attributes, attrs);
|
||
<span class="hljs-keyword">var</span> error = <span class="hljs-keyword">this</span>.validationError = <span class="hljs-keyword">this</span>.validate(attrs, options) || <span class="hljs-literal">null</span>;
|
||
<span class="hljs-keyword">if</span> (!error) <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
|
||
<span class="hljs-keyword">this</span>.trigger(<span class="hljs-string">'invalid'</span>, <span class="hljs-keyword">this</span>, error, _.extend(options, {validationError: error}));
|
||
<span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
|
||
}
|
||
|
||
});</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-96">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-96">¶</a>
|
||
</div>
|
||
<p>Underscore methods that we want to implement on the Model, mapped to the
|
||
number of arguments they take.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> modelMethods = {keys: <span class="hljs-number">1</span>, values: <span class="hljs-number">1</span>, pairs: <span class="hljs-number">1</span>, invert: <span class="hljs-number">1</span>, pick: <span class="hljs-number">0</span>,
|
||
omit: <span class="hljs-number">0</span>, chain: <span class="hljs-number">1</span>, isEmpty: <span class="hljs-number">1</span>};</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-97">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-97">¶</a>
|
||
</div>
|
||
<p>Mix in each Underscore method as a proxy to <code>Model#attributes</code>.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> addUnderscoreMethods(Model, modelMethods, <span class="hljs-string">'attributes'</span>);</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-98">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-98">¶</a>
|
||
</div>
|
||
<h2 id="backbone-collection">Backbone.Collection</h2>
|
||
|
||
</div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-99">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-99">¶</a>
|
||
</div>
|
||
|
||
</div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-100">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-100">¶</a>
|
||
</div>
|
||
<p>If models tend to represent a single row of data, a Backbone Collection is
|
||
more analogous to a table full of data … or a small slice or page of that
|
||
table, or a collection of rows that belong together for a particular reason
|
||
– all of the messages in this particular folder, all of the documents
|
||
belonging to this particular author, and so on. Collections maintain
|
||
indexes of their models, both in order, and for lookup by <code>id</code>.</p>
|
||
|
||
</div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-101">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-101">¶</a>
|
||
</div>
|
||
<p>Create a new <strong>Collection</strong>, perhaps to contain a specific type of <code>model</code>.
|
||
If a <code>comparator</code> is specified, the Collection will maintain
|
||
its models in sort order, as they’re added and removed.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> Collection = Backbone.Collection = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">models, options</span>) </span>{
|
||
options || (options = {});
|
||
<span class="hljs-keyword">if</span> (options.model) <span class="hljs-keyword">this</span>.model = options.model;
|
||
<span class="hljs-keyword">if</span> (options.comparator !== <span class="hljs-keyword">void</span> <span class="hljs-number">0</span>) <span class="hljs-keyword">this</span>.comparator = options.comparator;
|
||
<span class="hljs-keyword">this</span>._reset();
|
||
<span class="hljs-keyword">this</span>.initialize.apply(<span class="hljs-keyword">this</span>, <span class="hljs-built_in">arguments</span>);
|
||
<span class="hljs-keyword">if</span> (models) <span class="hljs-keyword">this</span>.reset(models, _.extend({silent: <span class="hljs-literal">true</span>}, options));
|
||
};</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-102">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-102">¶</a>
|
||
</div>
|
||
<p>Default options for <code>Collection#set</code>.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> setOptions = {add: <span class="hljs-literal">true</span>, remove: <span class="hljs-literal">true</span>, merge: <span class="hljs-literal">true</span>};
|
||
<span class="hljs-keyword">var</span> addOptions = {add: <span class="hljs-literal">true</span>, remove: <span class="hljs-literal">false</span>};</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-103">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-103">¶</a>
|
||
</div>
|
||
<p>Splices <code>insert</code> into <code>array</code> at index <code>at</code>.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> splice = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">array, insert, at</span>) </span>{
|
||
at = <span class="hljs-built_in">Math</span>.min(<span class="hljs-built_in">Math</span>.max(at, <span class="hljs-number">0</span>), array.length);
|
||
<span class="hljs-keyword">var</span> tail = <span class="hljs-built_in">Array</span>(array.length - at);
|
||
<span class="hljs-keyword">var</span> length = insert.length;
|
||
<span class="hljs-keyword">var</span> i;
|
||
<span class="hljs-keyword">for</span> (i = <span class="hljs-number">0</span>; i < tail.length; i++) tail[i] = array[i + at];
|
||
<span class="hljs-keyword">for</span> (i = <span class="hljs-number">0</span>; i < length; i++) array[i + at] = insert[i];
|
||
<span class="hljs-keyword">for</span> (i = <span class="hljs-number">0</span>; i < tail.length; i++) array[i + length + at] = tail[i];
|
||
};</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-104">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-104">¶</a>
|
||
</div>
|
||
<p>Define the Collection’s inheritable methods.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> _.extend(Collection.prototype, Events, {</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-105">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-105">¶</a>
|
||
</div>
|
||
<p>The default model for a collection is just a <strong>Backbone.Model</strong>.
|
||
This should be overridden in most cases.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> model: Model,</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-106">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-106">¶</a>
|
||
</div>
|
||
<p>Initialize is an empty function by default. Override it with your own
|
||
initialization logic.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> initialize: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>)</span>{},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-107">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-107">¶</a>
|
||
</div>
|
||
<p>The JSON representation of a Collection is an array of the
|
||
models’ attributes.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> toJSON: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">options</span>) </span>{
|
||
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.map(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">model</span>) </span>{ <span class="hljs-keyword">return</span> model.toJSON(options); });
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-108">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-108">¶</a>
|
||
</div>
|
||
<p>Proxy <code>Backbone.sync</code> by default.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> sync: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
|
||
<span class="hljs-keyword">return</span> Backbone.sync.apply(<span class="hljs-keyword">this</span>, <span class="hljs-built_in">arguments</span>);
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-109">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-109">¶</a>
|
||
</div>
|
||
<p>Add a model, or list of models to the set. <code>models</code> may be Backbone
|
||
Models or raw JavaScript objects to be converted to Models, or any
|
||
combination of the two.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> add: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">models, options</span>) </span>{
|
||
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.set(models, _.extend({merge: <span class="hljs-literal">false</span>}, options, addOptions));
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-110">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-110">¶</a>
|
||
</div>
|
||
<p>Remove a model, or a list of models from the set.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> remove: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">models, options</span>) </span>{
|
||
options = _.extend({}, options);
|
||
<span class="hljs-keyword">var</span> singular = !_.isArray(models);
|
||
models = singular ? [models] : models.slice();
|
||
<span class="hljs-keyword">var</span> removed = <span class="hljs-keyword">this</span>._removeModels(models, options);
|
||
<span class="hljs-keyword">if</span> (!options.silent && removed.length) {
|
||
options.changes = {added: [], merged: [], removed: removed};
|
||
<span class="hljs-keyword">this</span>.trigger(<span class="hljs-string">'update'</span>, <span class="hljs-keyword">this</span>, options);
|
||
}
|
||
<span class="hljs-keyword">return</span> singular ? removed[<span class="hljs-number">0</span>] : removed;
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-111">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-111">¶</a>
|
||
</div>
|
||
<p>Update a collection by <code>set</code>-ing a new list of models, adding new ones,
|
||
removing models that are no longer present, and merging models that
|
||
already exist in the collection, as necessary. Similar to <strong>Model#set</strong>,
|
||
the core operation for updating the data contained by the collection.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> set: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">models, options</span>) </span>{
|
||
<span class="hljs-keyword">if</span> (models == <span class="hljs-literal">null</span>) <span class="hljs-keyword">return</span>;
|
||
|
||
options = _.extend({}, setOptions, options);
|
||
<span class="hljs-keyword">if</span> (options.parse && !<span class="hljs-keyword">this</span>._isModel(models)) {
|
||
models = <span class="hljs-keyword">this</span>.parse(models, options) || [];
|
||
}
|
||
|
||
<span class="hljs-keyword">var</span> singular = !_.isArray(models);
|
||
models = singular ? [models] : models.slice();
|
||
|
||
<span class="hljs-keyword">var</span> at = options.at;
|
||
<span class="hljs-keyword">if</span> (at != <span class="hljs-literal">null</span>) at = +at;
|
||
<span class="hljs-keyword">if</span> (at > <span class="hljs-keyword">this</span>.length) at = <span class="hljs-keyword">this</span>.length;
|
||
<span class="hljs-keyword">if</span> (at < <span class="hljs-number">0</span>) at += <span class="hljs-keyword">this</span>.length + <span class="hljs-number">1</span>;
|
||
|
||
<span class="hljs-keyword">var</span> set = [];
|
||
<span class="hljs-keyword">var</span> toAdd = [];
|
||
<span class="hljs-keyword">var</span> toMerge = [];
|
||
<span class="hljs-keyword">var</span> toRemove = [];
|
||
<span class="hljs-keyword">var</span> modelMap = {};
|
||
|
||
<span class="hljs-keyword">var</span> add = options.add;
|
||
<span class="hljs-keyword">var</span> merge = options.merge;
|
||
<span class="hljs-keyword">var</span> remove = options.remove;
|
||
|
||
<span class="hljs-keyword">var</span> sort = <span class="hljs-literal">false</span>;
|
||
<span class="hljs-keyword">var</span> sortable = <span class="hljs-keyword">this</span>.comparator && at == <span class="hljs-literal">null</span> && options.sort !== <span class="hljs-literal">false</span>;
|
||
<span class="hljs-keyword">var</span> sortAttr = _.isString(<span class="hljs-keyword">this</span>.comparator) ? <span class="hljs-keyword">this</span>.comparator : <span class="hljs-literal">null</span>;</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-112">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-112">¶</a>
|
||
</div>
|
||
<p>Turn bare objects into model references, and prevent invalid models
|
||
from being added.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> model, i;
|
||
<span class="hljs-keyword">for</span> (i = <span class="hljs-number">0</span>; i < models.length; i++) {
|
||
model = models[i];</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-113">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-113">¶</a>
|
||
</div>
|
||
<p>If a duplicate is found, prevent it from being added and
|
||
optionally merge it into the existing model.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> existing = <span class="hljs-keyword">this</span>.get(model);
|
||
<span class="hljs-keyword">if</span> (existing) {
|
||
<span class="hljs-keyword">if</span> (merge && model !== existing) {
|
||
<span class="hljs-keyword">var</span> attrs = <span class="hljs-keyword">this</span>._isModel(model) ? model.attributes : model;
|
||
<span class="hljs-keyword">if</span> (options.parse) attrs = existing.parse(attrs, options);
|
||
existing.set(attrs, options);
|
||
toMerge.push(existing);
|
||
<span class="hljs-keyword">if</span> (sortable && !sort) sort = existing.hasChanged(sortAttr);
|
||
}
|
||
<span class="hljs-keyword">if</span> (!modelMap[existing.cid]) {
|
||
modelMap[existing.cid] = <span class="hljs-literal">true</span>;
|
||
set.push(existing);
|
||
}
|
||
models[i] = existing;</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-114">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-114">¶</a>
|
||
</div>
|
||
<p>If this is a new, valid model, push it to the <code>toAdd</code> list.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (add) {
|
||
model = models[i] = <span class="hljs-keyword">this</span>._prepareModel(model, options);
|
||
<span class="hljs-keyword">if</span> (model) {
|
||
toAdd.push(model);
|
||
<span class="hljs-keyword">this</span>._addReference(model, options);
|
||
modelMap[model.cid] = <span class="hljs-literal">true</span>;
|
||
set.push(model);
|
||
}
|
||
}
|
||
}</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-115">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-115">¶</a>
|
||
</div>
|
||
<p>Remove stale models.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (remove) {
|
||
<span class="hljs-keyword">for</span> (i = <span class="hljs-number">0</span>; i < <span class="hljs-keyword">this</span>.length; i++) {
|
||
model = <span class="hljs-keyword">this</span>.models[i];
|
||
<span class="hljs-keyword">if</span> (!modelMap[model.cid]) toRemove.push(model);
|
||
}
|
||
<span class="hljs-keyword">if</span> (toRemove.length) <span class="hljs-keyword">this</span>._removeModels(toRemove, options);
|
||
}</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-116">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-116">¶</a>
|
||
</div>
|
||
<p>See if sorting is needed, update <code>length</code> and splice in new models.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> orderChanged = <span class="hljs-literal">false</span>;
|
||
<span class="hljs-keyword">var</span> replace = !sortable && add && remove;
|
||
<span class="hljs-keyword">if</span> (set.length && replace) {
|
||
orderChanged = <span class="hljs-keyword">this</span>.length !== set.length || _.some(<span class="hljs-keyword">this</span>.models, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">m, index</span>) </span>{
|
||
<span class="hljs-keyword">return</span> m !== set[index];
|
||
});
|
||
<span class="hljs-keyword">this</span>.models.length = <span class="hljs-number">0</span>;
|
||
splice(<span class="hljs-keyword">this</span>.models, set, <span class="hljs-number">0</span>);
|
||
<span class="hljs-keyword">this</span>.length = <span class="hljs-keyword">this</span>.models.length;
|
||
} <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (toAdd.length) {
|
||
<span class="hljs-keyword">if</span> (sortable) sort = <span class="hljs-literal">true</span>;
|
||
splice(<span class="hljs-keyword">this</span>.models, toAdd, at == <span class="hljs-literal">null</span> ? <span class="hljs-keyword">this</span>.length : at);
|
||
<span class="hljs-keyword">this</span>.length = <span class="hljs-keyword">this</span>.models.length;
|
||
}</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-117">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-117">¶</a>
|
||
</div>
|
||
<p>Silently sort the collection if appropriate.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (sort) <span class="hljs-keyword">this</span>.sort({silent: <span class="hljs-literal">true</span>});</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-118">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-118">¶</a>
|
||
</div>
|
||
<p>Unless silenced, it’s time to fire all appropriate add/sort/update events.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (!options.silent) {
|
||
<span class="hljs-keyword">for</span> (i = <span class="hljs-number">0</span>; i < toAdd.length; i++) {
|
||
<span class="hljs-keyword">if</span> (at != <span class="hljs-literal">null</span>) options.index = at + i;
|
||
model = toAdd[i];
|
||
model.trigger(<span class="hljs-string">'add'</span>, model, <span class="hljs-keyword">this</span>, options);
|
||
}
|
||
<span class="hljs-keyword">if</span> (sort || orderChanged) <span class="hljs-keyword">this</span>.trigger(<span class="hljs-string">'sort'</span>, <span class="hljs-keyword">this</span>, options);
|
||
<span class="hljs-keyword">if</span> (toAdd.length || toRemove.length || toMerge.length) {
|
||
options.changes = {
|
||
added: toAdd,
|
||
removed: toRemove,
|
||
merged: toMerge
|
||
};
|
||
<span class="hljs-keyword">this</span>.trigger(<span class="hljs-string">'update'</span>, <span class="hljs-keyword">this</span>, options);
|
||
}
|
||
}</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-119">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-119">¶</a>
|
||
</div>
|
||
<p>Return the added (or merged) model (or models).</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">return</span> singular ? models[<span class="hljs-number">0</span>] : models;
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-120">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-120">¶</a>
|
||
</div>
|
||
<p>When you have more items than you want to add or remove individually,
|
||
you can reset the entire set with a new list of models, without firing
|
||
any granular <code>add</code> or <code>remove</code> events. Fires <code>reset</code> when finished.
|
||
Useful for bulk operations and optimizations.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> reset: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">models, options</span>) </span>{
|
||
options = options ? _.clone(options) : {};
|
||
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> i = <span class="hljs-number">0</span>; i < <span class="hljs-keyword">this</span>.models.length; i++) {
|
||
<span class="hljs-keyword">this</span>._removeReference(<span class="hljs-keyword">this</span>.models[i], options);
|
||
}
|
||
options.previousModels = <span class="hljs-keyword">this</span>.models;
|
||
<span class="hljs-keyword">this</span>._reset();
|
||
models = <span class="hljs-keyword">this</span>.add(models, _.extend({silent: <span class="hljs-literal">true</span>}, options));
|
||
<span class="hljs-keyword">if</span> (!options.silent) <span class="hljs-keyword">this</span>.trigger(<span class="hljs-string">'reset'</span>, <span class="hljs-keyword">this</span>, options);
|
||
<span class="hljs-keyword">return</span> models;
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-121">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-121">¶</a>
|
||
</div>
|
||
<p>Add a model to the end of the collection.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> push: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">model, options</span>) </span>{
|
||
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.add(model, _.extend({at: <span class="hljs-keyword">this</span>.length}, options));
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-122">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-122">¶</a>
|
||
</div>
|
||
<p>Remove a model from the end of the collection.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> pop: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">options</span>) </span>{
|
||
<span class="hljs-keyword">var</span> model = <span class="hljs-keyword">this</span>.at(<span class="hljs-keyword">this</span>.length - <span class="hljs-number">1</span>);
|
||
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.remove(model, options);
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-123">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-123">¶</a>
|
||
</div>
|
||
<p>Add a model to the beginning of the collection.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> unshift: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">model, options</span>) </span>{
|
||
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.add(model, _.extend({at: <span class="hljs-number">0</span>}, options));
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-124">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-124">¶</a>
|
||
</div>
|
||
<p>Remove a model from the beginning of the collection.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> shift: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">options</span>) </span>{
|
||
<span class="hljs-keyword">var</span> model = <span class="hljs-keyword">this</span>.at(<span class="hljs-number">0</span>);
|
||
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.remove(model, options);
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-125">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-125">¶</a>
|
||
</div>
|
||
<p>Slice out a sub-array of models from the collection.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> slice: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
|
||
<span class="hljs-keyword">return</span> slice.apply(<span class="hljs-keyword">this</span>.models, <span class="hljs-built_in">arguments</span>);
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-126">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-126">¶</a>
|
||
</div>
|
||
<p>Get a model from the set by id, cid, model object with id or cid
|
||
properties, or an attributes object that is transformed through modelId.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> get: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">obj</span>) </span>{
|
||
<span class="hljs-keyword">if</span> (obj == <span class="hljs-literal">null</span>) <span class="hljs-keyword">return</span> <span class="hljs-keyword">void</span> <span class="hljs-number">0</span>;
|
||
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>._byId[obj] ||
|
||
<span class="hljs-keyword">this</span>._byId[<span class="hljs-keyword">this</span>.modelId(obj.attributes || obj)] ||
|
||
obj.cid && <span class="hljs-keyword">this</span>._byId[obj.cid];
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-127">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-127">¶</a>
|
||
</div>
|
||
<p>Returns <code>true</code> if the model is in the collection.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> has: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">obj</span>) </span>{
|
||
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.get(obj) != <span class="hljs-literal">null</span>;
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-128">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-128">¶</a>
|
||
</div>
|
||
<p>Get the model at the given index.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> at: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">index</span>) </span>{
|
||
<span class="hljs-keyword">if</span> (index < <span class="hljs-number">0</span>) index += <span class="hljs-keyword">this</span>.length;
|
||
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.models[index];
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-129">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-129">¶</a>
|
||
</div>
|
||
<p>Return models with matching attributes. Useful for simple cases of
|
||
<code>filter</code>.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> where: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">attrs, first</span>) </span>{
|
||
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>[first ? <span class="hljs-string">'find'</span> : <span class="hljs-string">'filter'</span>](attrs);
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-130">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-130">¶</a>
|
||
</div>
|
||
<p>Return the first model with matching attributes. Useful for simple cases
|
||
of <code>find</code>.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> findWhere: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">attrs</span>) </span>{
|
||
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.where(attrs, <span class="hljs-literal">true</span>);
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-131">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-131">¶</a>
|
||
</div>
|
||
<p>Force the collection to re-sort itself. You don’t need to call this under
|
||
normal circumstances, as the set will maintain sort order as each item
|
||
is added.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> sort: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">options</span>) </span>{
|
||
<span class="hljs-keyword">var</span> comparator = <span class="hljs-keyword">this</span>.comparator;
|
||
<span class="hljs-keyword">if</span> (!comparator) <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">'Cannot sort a set without a comparator'</span>);
|
||
options || (options = {});
|
||
|
||
<span class="hljs-keyword">var</span> length = comparator.length;
|
||
<span class="hljs-keyword">if</span> (_.isFunction(comparator)) comparator = _.bind(comparator, <span class="hljs-keyword">this</span>);</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-132">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-132">¶</a>
|
||
</div>
|
||
<p>Run sort based on type of <code>comparator</code>.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (length === <span class="hljs-number">1</span> || _.isString(comparator)) {
|
||
<span class="hljs-keyword">this</span>.models = <span class="hljs-keyword">this</span>.sortBy(comparator);
|
||
} <span class="hljs-keyword">else</span> {
|
||
<span class="hljs-keyword">this</span>.models.sort(comparator);
|
||
}
|
||
<span class="hljs-keyword">if</span> (!options.silent) <span class="hljs-keyword">this</span>.trigger(<span class="hljs-string">'sort'</span>, <span class="hljs-keyword">this</span>, options);
|
||
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-133">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-133">¶</a>
|
||
</div>
|
||
<p>Pluck an attribute from each model in the collection.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> pluck: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">attr</span>) </span>{
|
||
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.map(attr + <span class="hljs-string">''</span>);
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-134">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-134">¶</a>
|
||
</div>
|
||
<p>Fetch the default set of models for this collection, resetting the
|
||
collection when they arrive. If <code>reset: true</code> is passed, the response
|
||
data will be passed through the <code>reset</code> method instead of <code>set</code>.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> fetch: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">options</span>) </span>{
|
||
options = _.extend({parse: <span class="hljs-literal">true</span>}, options);
|
||
<span class="hljs-keyword">var</span> success = options.success;
|
||
<span class="hljs-keyword">var</span> collection = <span class="hljs-keyword">this</span>;
|
||
options.success = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">resp</span>) </span>{
|
||
<span class="hljs-keyword">var</span> method = options.reset ? <span class="hljs-string">'reset'</span> : <span class="hljs-string">'set'</span>;
|
||
collection[method](resp, options);
|
||
<span class="hljs-keyword">if</span> (success) success.call(options.context, collection, resp, options);
|
||
collection.trigger(<span class="hljs-string">'sync'</span>, collection, resp, options);
|
||
};
|
||
wrapError(<span class="hljs-keyword">this</span>, options);
|
||
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.sync(<span class="hljs-string">'read'</span>, <span class="hljs-keyword">this</span>, options);
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-135">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-135">¶</a>
|
||
</div>
|
||
<p>Create a new instance of a model in this collection. Add the model to the
|
||
collection immediately, unless <code>wait: true</code> is passed, in which case we
|
||
wait for the server to agree.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> create: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">model, options</span>) </span>{
|
||
options = options ? _.clone(options) : {};
|
||
<span class="hljs-keyword">var</span> wait = options.wait;
|
||
model = <span class="hljs-keyword">this</span>._prepareModel(model, options);
|
||
<span class="hljs-keyword">if</span> (!model) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
|
||
<span class="hljs-keyword">if</span> (!wait) <span class="hljs-keyword">this</span>.add(model, options);
|
||
<span class="hljs-keyword">var</span> collection = <span class="hljs-keyword">this</span>;
|
||
<span class="hljs-keyword">var</span> success = options.success;
|
||
options.success = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">m, resp, callbackOpts</span>) </span>{
|
||
<span class="hljs-keyword">if</span> (wait) collection.add(m, callbackOpts);
|
||
<span class="hljs-keyword">if</span> (success) success.call(callbackOpts.context, m, resp, callbackOpts);
|
||
};
|
||
model.save(<span class="hljs-literal">null</span>, options);
|
||
<span class="hljs-keyword">return</span> model;
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-136">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-136">¶</a>
|
||
</div>
|
||
<p><strong>parse</strong> converts a response into a list of models to be added to the
|
||
collection. The default implementation is just to pass it through.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> parse: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">resp, options</span>) </span>{
|
||
<span class="hljs-keyword">return</span> resp;
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-137">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-137">¶</a>
|
||
</div>
|
||
<p>Create a new collection with an identical list of models as this one.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> clone: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
|
||
<span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-keyword">this</span>.constructor(<span class="hljs-keyword">this</span>.models, {
|
||
model: <span class="hljs-keyword">this</span>.model,
|
||
comparator: <span class="hljs-keyword">this</span>.comparator
|
||
});
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-138">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-138">¶</a>
|
||
</div>
|
||
<p>Define how to uniquely identify models in the collection.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> modelId: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">attrs</span>) </span>{
|
||
<span class="hljs-keyword">return</span> attrs[<span class="hljs-keyword">this</span>.model.prototype.idAttribute || <span class="hljs-string">'id'</span>];
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-139">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-139">¶</a>
|
||
</div>
|
||
<p>Private method to reset all internal state. Called when the collection
|
||
is first initialized or reset.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> _reset: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
|
||
<span class="hljs-keyword">this</span>.length = <span class="hljs-number">0</span>;
|
||
<span class="hljs-keyword">this</span>.models = [];
|
||
<span class="hljs-keyword">this</span>._byId = {};
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-140">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-140">¶</a>
|
||
</div>
|
||
<p>Prepare a hash of attributes (or other model) to be added to this
|
||
collection.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> _prepareModel: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">attrs, options</span>) </span>{
|
||
<span class="hljs-keyword">if</span> (<span class="hljs-keyword">this</span>._isModel(attrs)) {
|
||
<span class="hljs-keyword">if</span> (!attrs.collection) attrs.collection = <span class="hljs-keyword">this</span>;
|
||
<span class="hljs-keyword">return</span> attrs;
|
||
}
|
||
options = options ? _.clone(options) : {};
|
||
options.collection = <span class="hljs-keyword">this</span>;
|
||
<span class="hljs-keyword">var</span> model = <span class="hljs-keyword">new</span> <span class="hljs-keyword">this</span>.model(attrs, options);
|
||
<span class="hljs-keyword">if</span> (!model.validationError) <span class="hljs-keyword">return</span> model;
|
||
<span class="hljs-keyword">this</span>.trigger(<span class="hljs-string">'invalid'</span>, <span class="hljs-keyword">this</span>, model.validationError, options);
|
||
<span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-141">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-141">¶</a>
|
||
</div>
|
||
<p>Internal method called by both remove and set.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> _removeModels: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">models, options</span>) </span>{
|
||
<span class="hljs-keyword">var</span> removed = [];
|
||
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> i = <span class="hljs-number">0</span>; i < models.length; i++) {
|
||
<span class="hljs-keyword">var</span> model = <span class="hljs-keyword">this</span>.get(models[i]);
|
||
<span class="hljs-keyword">if</span> (!model) <span class="hljs-keyword">continue</span>;
|
||
|
||
<span class="hljs-keyword">var</span> index = <span class="hljs-keyword">this</span>.indexOf(model);
|
||
<span class="hljs-keyword">this</span>.models.splice(index, <span class="hljs-number">1</span>);
|
||
<span class="hljs-keyword">this</span>.length--;</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-142">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-142">¶</a>
|
||
</div>
|
||
<p>Remove references before triggering ‘remove’ event to prevent an
|
||
infinite loop. #3693</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">delete</span> <span class="hljs-keyword">this</span>._byId[model.cid];
|
||
<span class="hljs-keyword">var</span> id = <span class="hljs-keyword">this</span>.modelId(model.attributes);
|
||
<span class="hljs-keyword">if</span> (id != <span class="hljs-literal">null</span>) <span class="hljs-keyword">delete</span> <span class="hljs-keyword">this</span>._byId[id];
|
||
|
||
<span class="hljs-keyword">if</span> (!options.silent) {
|
||
options.index = index;
|
||
model.trigger(<span class="hljs-string">'remove'</span>, model, <span class="hljs-keyword">this</span>, options);
|
||
}
|
||
|
||
removed.push(model);
|
||
<span class="hljs-keyword">this</span>._removeReference(model, options);
|
||
}
|
||
<span class="hljs-keyword">return</span> removed;
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-143">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-143">¶</a>
|
||
</div>
|
||
<p>Method for checking whether an object should be considered a model for
|
||
the purposes of adding to the collection.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> _isModel: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">model</span>) </span>{
|
||
<span class="hljs-keyword">return</span> model <span class="hljs-keyword">instanceof</span> Model;
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-144">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-144">¶</a>
|
||
</div>
|
||
<p>Internal method to create a model’s ties to a collection.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> _addReference: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">model, options</span>) </span>{
|
||
<span class="hljs-keyword">this</span>._byId[model.cid] = model;
|
||
<span class="hljs-keyword">var</span> id = <span class="hljs-keyword">this</span>.modelId(model.attributes);
|
||
<span class="hljs-keyword">if</span> (id != <span class="hljs-literal">null</span>) <span class="hljs-keyword">this</span>._byId[id] = model;
|
||
model.on(<span class="hljs-string">'all'</span>, <span class="hljs-keyword">this</span>._onModelEvent, <span class="hljs-keyword">this</span>);
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-145">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-145">¶</a>
|
||
</div>
|
||
<p>Internal method to sever a model’s ties to a collection.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> _removeReference: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">model, options</span>) </span>{
|
||
<span class="hljs-keyword">delete</span> <span class="hljs-keyword">this</span>._byId[model.cid];
|
||
<span class="hljs-keyword">var</span> id = <span class="hljs-keyword">this</span>.modelId(model.attributes);
|
||
<span class="hljs-keyword">if</span> (id != <span class="hljs-literal">null</span>) <span class="hljs-keyword">delete</span> <span class="hljs-keyword">this</span>._byId[id];
|
||
<span class="hljs-keyword">if</span> (<span class="hljs-keyword">this</span> === model.collection) <span class="hljs-keyword">delete</span> model.collection;
|
||
model.off(<span class="hljs-string">'all'</span>, <span class="hljs-keyword">this</span>._onModelEvent, <span class="hljs-keyword">this</span>);
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-146">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-146">¶</a>
|
||
</div>
|
||
<p>Internal method called every time a model in the set fires an event.
|
||
Sets need to update their indexes when models change ids. All other
|
||
events simply proxy through. “add” and “remove” events that originate
|
||
in other collections are ignored.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> _onModelEvent: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">event, model, collection, options</span>) </span>{
|
||
<span class="hljs-keyword">if</span> (model) {
|
||
<span class="hljs-keyword">if</span> ((event === <span class="hljs-string">'add'</span> || event === <span class="hljs-string">'remove'</span>) && collection !== <span class="hljs-keyword">this</span>) <span class="hljs-keyword">return</span>;
|
||
<span class="hljs-keyword">if</span> (event === <span class="hljs-string">'destroy'</span>) <span class="hljs-keyword">this</span>.remove(model, options);
|
||
<span class="hljs-keyword">if</span> (event === <span class="hljs-string">'change'</span>) {
|
||
<span class="hljs-keyword">var</span> prevId = <span class="hljs-keyword">this</span>.modelId(model.previousAttributes());
|
||
<span class="hljs-keyword">var</span> id = <span class="hljs-keyword">this</span>.modelId(model.attributes);
|
||
<span class="hljs-keyword">if</span> (prevId !== id) {
|
||
<span class="hljs-keyword">if</span> (prevId != <span class="hljs-literal">null</span>) <span class="hljs-keyword">delete</span> <span class="hljs-keyword">this</span>._byId[prevId];
|
||
<span class="hljs-keyword">if</span> (id != <span class="hljs-literal">null</span>) <span class="hljs-keyword">this</span>._byId[id] = model;
|
||
}
|
||
}
|
||
}
|
||
<span class="hljs-keyword">this</span>.trigger.apply(<span class="hljs-keyword">this</span>, <span class="hljs-built_in">arguments</span>);
|
||
}
|
||
|
||
});</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-147">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-147">¶</a>
|
||
</div>
|
||
<p>Underscore methods that we want to implement on the Collection.
|
||
90% of the core usefulness of Backbone Collections is actually implemented
|
||
right here:</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> collectionMethods = {forEach: <span class="hljs-number">3</span>, each: <span class="hljs-number">3</span>, map: <span class="hljs-number">3</span>, collect: <span class="hljs-number">3</span>, reduce: <span class="hljs-number">0</span>,
|
||
foldl: <span class="hljs-number">0</span>, inject: <span class="hljs-number">0</span>, reduceRight: <span class="hljs-number">0</span>, foldr: <span class="hljs-number">0</span>, find: <span class="hljs-number">3</span>, detect: <span class="hljs-number">3</span>, filter: <span class="hljs-number">3</span>,
|
||
select: <span class="hljs-number">3</span>, reject: <span class="hljs-number">3</span>, every: <span class="hljs-number">3</span>, all: <span class="hljs-number">3</span>, some: <span class="hljs-number">3</span>, any: <span class="hljs-number">3</span>, include: <span class="hljs-number">3</span>, includes: <span class="hljs-number">3</span>,
|
||
contains: <span class="hljs-number">3</span>, invoke: <span class="hljs-number">0</span>, max: <span class="hljs-number">3</span>, min: <span class="hljs-number">3</span>, toArray: <span class="hljs-number">1</span>, size: <span class="hljs-number">1</span>, first: <span class="hljs-number">3</span>,
|
||
head: <span class="hljs-number">3</span>, take: <span class="hljs-number">3</span>, initial: <span class="hljs-number">3</span>, rest: <span class="hljs-number">3</span>, tail: <span class="hljs-number">3</span>, drop: <span class="hljs-number">3</span>, last: <span class="hljs-number">3</span>,
|
||
without: <span class="hljs-number">0</span>, difference: <span class="hljs-number">0</span>, indexOf: <span class="hljs-number">3</span>, shuffle: <span class="hljs-number">1</span>, lastIndexOf: <span class="hljs-number">3</span>,
|
||
isEmpty: <span class="hljs-number">1</span>, chain: <span class="hljs-number">1</span>, sample: <span class="hljs-number">3</span>, partition: <span class="hljs-number">3</span>, groupBy: <span class="hljs-number">3</span>, countBy: <span class="hljs-number">3</span>,
|
||
sortBy: <span class="hljs-number">3</span>, indexBy: <span class="hljs-number">3</span>, findIndex: <span class="hljs-number">3</span>, findLastIndex: <span class="hljs-number">3</span>};</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-148">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-148">¶</a>
|
||
</div>
|
||
<p>Mix in each Underscore method as a proxy to <code>Collection#models</code>.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> addUnderscoreMethods(Collection, collectionMethods, <span class="hljs-string">'models'</span>);</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-149">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-149">¶</a>
|
||
</div>
|
||
<h2 id="backbone-view">Backbone.View</h2>
|
||
|
||
</div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-150">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-150">¶</a>
|
||
</div>
|
||
|
||
</div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-151">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-151">¶</a>
|
||
</div>
|
||
<p>Backbone Views are almost more convention than they are actual code. A View
|
||
is simply a JavaScript object that represents a logical chunk of UI in the
|
||
DOM. This might be a single item, an entire list, a sidebar or panel, or
|
||
even the surrounding frame which wraps your whole app. Defining a chunk of
|
||
UI as a <strong>View</strong> allows you to define your DOM events declaratively, without
|
||
having to worry about render order … and makes it easy for the view to
|
||
react to specific changes in the state of your models.</p>
|
||
|
||
</div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-152">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-152">¶</a>
|
||
</div>
|
||
<p>Creating a Backbone.View creates its initial element outside of the DOM,
|
||
if an existing element is not provided…</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> View = Backbone.View = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">options</span>) </span>{
|
||
<span class="hljs-keyword">this</span>.cid = _.uniqueId(<span class="hljs-string">'view'</span>);
|
||
_.extend(<span class="hljs-keyword">this</span>, _.pick(options, viewOptions));
|
||
<span class="hljs-keyword">this</span>._ensureElement();
|
||
<span class="hljs-keyword">this</span>.initialize.apply(<span class="hljs-keyword">this</span>, <span class="hljs-built_in">arguments</span>);
|
||
};</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-153">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-153">¶</a>
|
||
</div>
|
||
<p>Cached regex to split keys for <code>delegate</code>.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> delegateEventSplitter = <span class="hljs-regexp">/^(\S+)\s*(.*)$/</span>;</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-154">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-154">¶</a>
|
||
</div>
|
||
<p>List of view options to be set as properties.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> viewOptions = [<span class="hljs-string">'model'</span>, <span class="hljs-string">'collection'</span>, <span class="hljs-string">'el'</span>, <span class="hljs-string">'id'</span>, <span class="hljs-string">'attributes'</span>, <span class="hljs-string">'className'</span>, <span class="hljs-string">'tagName'</span>, <span class="hljs-string">'events'</span>];</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-155">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-155">¶</a>
|
||
</div>
|
||
<p>Set up all inheritable <strong>Backbone.View</strong> properties and methods.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> _.extend(View.prototype, Events, {</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-156">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-156">¶</a>
|
||
</div>
|
||
<p>The default <code>tagName</code> of a View’s element is <code>"div"</code>.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> tagName: <span class="hljs-string">'div'</span>,</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-157">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-157">¶</a>
|
||
</div>
|
||
<p>jQuery delegate for element lookup, scoped to DOM elements within the
|
||
current view. This should be preferred to global lookups where possible.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> $: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">selector</span>) </span>{
|
||
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.$el.find(selector);
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-158">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-158">¶</a>
|
||
</div>
|
||
<p>Initialize is an empty function by default. Override it with your own
|
||
initialization logic.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> initialize: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>)</span>{},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-159">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-159">¶</a>
|
||
</div>
|
||
<p><strong>render</strong> is the core function that your view should override, in order
|
||
to populate its element (<code>this.el</code>), with the appropriate HTML. The
|
||
convention is for <strong>render</strong> to always return <code>this</code>.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> render: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
|
||
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-160">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-160">¶</a>
|
||
</div>
|
||
<p>Remove this view by taking the element out of the DOM, and removing any
|
||
applicable Backbone.Events listeners.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> remove: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
|
||
<span class="hljs-keyword">this</span>._removeElement();
|
||
<span class="hljs-keyword">this</span>.stopListening();
|
||
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-161">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-161">¶</a>
|
||
</div>
|
||
<p>Remove this view’s element from the document and all event listeners
|
||
attached to it. Exposed for subclasses using an alternative DOM
|
||
manipulation API.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> _removeElement: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
|
||
<span class="hljs-keyword">this</span>.$el.remove();
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-162">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-162">¶</a>
|
||
</div>
|
||
<p>Change the view’s element (<code>this.el</code> property) and re-delegate the
|
||
view’s events on the new element.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> setElement: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">element</span>) </span>{
|
||
<span class="hljs-keyword">this</span>.undelegateEvents();
|
||
<span class="hljs-keyword">this</span>._setElement(element);
|
||
<span class="hljs-keyword">this</span>.delegateEvents();
|
||
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-163">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-163">¶</a>
|
||
</div>
|
||
<p>Creates the <code>this.el</code> and <code>this.$el</code> references for this view using the
|
||
given <code>el</code>. <code>el</code> can be a CSS selector or an HTML string, a jQuery
|
||
context or an element. Subclasses can override this to utilize an
|
||
alternative DOM manipulation API and are only required to set the
|
||
<code>this.el</code> property.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> _setElement: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">el</span>) </span>{
|
||
<span class="hljs-keyword">this</span>.$el = el <span class="hljs-keyword">instanceof</span> Backbone.$ ? el : Backbone.$(el);
|
||
<span class="hljs-keyword">this</span>.el = <span class="hljs-keyword">this</span>.$el[<span class="hljs-number">0</span>];
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-164">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-164">¶</a>
|
||
</div>
|
||
<p>Set callbacks, where <code>this.events</code> is a hash of</p>
|
||
<p><em>{“event selector”: “callback”}</em></p>
|
||
<pre><code>{
|
||
<span class="hljs-string">'mousedown .title'</span>: <span class="hljs-string">'edit'</span>,
|
||
<span class="hljs-string">'click .button'</span>: <span class="hljs-string">'save'</span>,
|
||
<span class="hljs-string">'click .open'</span>: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">e</span>) </span>{ ... }
|
||
}
|
||
</code></pre><p>pairs. Callbacks will be bound to the view, with <code>this</code> set properly.
|
||
Uses event delegation for efficiency.
|
||
Omitting the selector binds the event to <code>this.el</code>.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> delegateEvents: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">events</span>) </span>{
|
||
events || (events = _.result(<span class="hljs-keyword">this</span>, <span class="hljs-string">'events'</span>));
|
||
<span class="hljs-keyword">if</span> (!events) <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
|
||
<span class="hljs-keyword">this</span>.undelegateEvents();
|
||
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> key <span class="hljs-keyword">in</span> events) {
|
||
<span class="hljs-keyword">var</span> method = events[key];
|
||
<span class="hljs-keyword">if</span> (!_.isFunction(method)) method = <span class="hljs-keyword">this</span>[method];
|
||
<span class="hljs-keyword">if</span> (!method) <span class="hljs-keyword">continue</span>;
|
||
<span class="hljs-keyword">var</span> match = key.match(delegateEventSplitter);
|
||
<span class="hljs-keyword">this</span>.delegate(match[<span class="hljs-number">1</span>], match[<span class="hljs-number">2</span>], _.bind(method, <span class="hljs-keyword">this</span>));
|
||
}
|
||
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-165">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-165">¶</a>
|
||
</div>
|
||
<p>Add a single event listener to the view’s element (or a child element
|
||
using <code>selector</code>). This only works for delegate-able events: not <code>focus</code>,
|
||
<code>blur</code>, and not <code>change</code>, <code>submit</code>, and <code>reset</code> in Internet Explorer.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> delegate: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">eventName, selector, listener</span>) </span>{
|
||
<span class="hljs-keyword">this</span>.$el.on(eventName + <span class="hljs-string">'.delegateEvents'</span> + <span class="hljs-keyword">this</span>.cid, selector, listener);
|
||
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-166">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-166">¶</a>
|
||
</div>
|
||
<p>Clears all callbacks previously bound to the view by <code>delegateEvents</code>.
|
||
You usually don’t need to use this, but may wish to if you have multiple
|
||
Backbone views attached to the same DOM element.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> undelegateEvents: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
|
||
<span class="hljs-keyword">if</span> (<span class="hljs-keyword">this</span>.$el) <span class="hljs-keyword">this</span>.$el.off(<span class="hljs-string">'.delegateEvents'</span> + <span class="hljs-keyword">this</span>.cid);
|
||
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-167">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-167">¶</a>
|
||
</div>
|
||
<p>A finer-grained <code>undelegateEvents</code> for removing a single delegated event.
|
||
<code>selector</code> and <code>listener</code> are both optional.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> undelegate: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">eventName, selector, listener</span>) </span>{
|
||
<span class="hljs-keyword">this</span>.$el.off(eventName + <span class="hljs-string">'.delegateEvents'</span> + <span class="hljs-keyword">this</span>.cid, selector, listener);
|
||
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-168">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-168">¶</a>
|
||
</div>
|
||
<p>Produces a DOM element to be assigned to your view. Exposed for
|
||
subclasses using an alternative DOM manipulation API.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> _createElement: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">tagName</span>) </span>{
|
||
<span class="hljs-keyword">return</span> <span class="hljs-built_in">document</span>.createElement(tagName);
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-169">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-169">¶</a>
|
||
</div>
|
||
<p>Ensure that the View has a DOM element to render into.
|
||
If <code>this.el</code> is a string, pass it through <code>$()</code>, take the first
|
||
matching element, and re-assign it to <code>el</code>. Otherwise, create
|
||
an element from the <code>id</code>, <code>className</code> and <code>tagName</code> properties.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> _ensureElement: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
|
||
<span class="hljs-keyword">if</span> (!<span class="hljs-keyword">this</span>.el) {
|
||
<span class="hljs-keyword">var</span> attrs = _.extend({}, _.result(<span class="hljs-keyword">this</span>, <span class="hljs-string">'attributes'</span>));
|
||
<span class="hljs-keyword">if</span> (<span class="hljs-keyword">this</span>.id) attrs.id = _.result(<span class="hljs-keyword">this</span>, <span class="hljs-string">'id'</span>);
|
||
<span class="hljs-keyword">if</span> (<span class="hljs-keyword">this</span>.className) attrs[<span class="hljs-string">'class'</span>] = _.result(<span class="hljs-keyword">this</span>, <span class="hljs-string">'className'</span>);
|
||
<span class="hljs-keyword">this</span>.setElement(<span class="hljs-keyword">this</span>._createElement(_.result(<span class="hljs-keyword">this</span>, <span class="hljs-string">'tagName'</span>)));
|
||
<span class="hljs-keyword">this</span>._setAttributes(attrs);
|
||
} <span class="hljs-keyword">else</span> {
|
||
<span class="hljs-keyword">this</span>.setElement(_.result(<span class="hljs-keyword">this</span>, <span class="hljs-string">'el'</span>));
|
||
}
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-170">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-170">¶</a>
|
||
</div>
|
||
<p>Set attributes from a hash on this view’s element. Exposed for
|
||
subclasses using an alternative DOM manipulation API.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> _setAttributes: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">attributes</span>) </span>{
|
||
<span class="hljs-keyword">this</span>.$el.attr(attributes);
|
||
}
|
||
|
||
});</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-171">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-171">¶</a>
|
||
</div>
|
||
<h2 id="backbone-sync">Backbone.sync</h2>
|
||
|
||
</div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-172">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-172">¶</a>
|
||
</div>
|
||
|
||
</div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-173">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-173">¶</a>
|
||
</div>
|
||
<p>Override this function to change the manner in which Backbone persists
|
||
models to the server. You will be passed the type of request, and the
|
||
model in question. By default, makes a RESTful Ajax request
|
||
to the model’s <code>url()</code>. Some possible customizations could be:</p>
|
||
<ul>
|
||
<li>Use <code>setTimeout</code> to batch rapid-fire updates into a single request.</li>
|
||
<li>Send up the models as XML instead of JSON.</li>
|
||
<li>Persist models via WebSockets instead of Ajax.</li>
|
||
</ul>
|
||
<p>Turn on <code>Backbone.emulateHTTP</code> in order to send <code>PUT</code> and <code>DELETE</code> requests
|
||
as <code>POST</code>, with a <code>_method</code> parameter containing the true HTTP method,
|
||
as well as all requests with the body as <code>application/x-www-form-urlencoded</code>
|
||
instead of <code>application/json</code> with the model in a param named <code>model</code>.
|
||
Useful when interfacing with server-side languages like <strong>PHP</strong> that make
|
||
it difficult to read the body of <code>PUT</code> requests.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> Backbone.sync = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">method, model, options</span>) </span>{
|
||
<span class="hljs-keyword">var</span> type = methodMap[method];</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-174">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-174">¶</a>
|
||
</div>
|
||
<p>Default options, unless specified.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> _.defaults(options || (options = {}), {
|
||
emulateHTTP: Backbone.emulateHTTP,
|
||
emulateJSON: Backbone.emulateJSON
|
||
});</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-175">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-175">¶</a>
|
||
</div>
|
||
<p>Default JSON-request options.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> params = {type: type, dataType: <span class="hljs-string">'json'</span>};</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-176">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-176">¶</a>
|
||
</div>
|
||
<p>Ensure that we have a URL.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (!options.url) {
|
||
params.url = _.result(model, <span class="hljs-string">'url'</span>) || urlError();
|
||
}</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-177">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-177">¶</a>
|
||
</div>
|
||
<p>Ensure that we have the appropriate request data.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (options.data == <span class="hljs-literal">null</span> && model && (method === <span class="hljs-string">'create'</span> || method === <span class="hljs-string">'update'</span> || method === <span class="hljs-string">'patch'</span>)) {
|
||
params.contentType = <span class="hljs-string">'application/json'</span>;
|
||
params.data = <span class="hljs-built_in">JSON</span>.stringify(options.attrs || model.toJSON(options));
|
||
}</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-178">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-178">¶</a>
|
||
</div>
|
||
<p>For older servers, emulate JSON by encoding the request into an HTML-form.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (options.emulateJSON) {
|
||
params.contentType = <span class="hljs-string">'application/x-www-form-urlencoded'</span>;
|
||
params.data = params.data ? {model: params.data} : {};
|
||
}</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-179">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-179">¶</a>
|
||
</div>
|
||
<p>For older servers, emulate HTTP by mimicking the HTTP method with <code>_method</code>
|
||
And an <code>X-HTTP-Method-Override</code> header.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (options.emulateHTTP && (type === <span class="hljs-string">'PUT'</span> || type === <span class="hljs-string">'DELETE'</span> || type === <span class="hljs-string">'PATCH'</span>)) {
|
||
params.type = <span class="hljs-string">'POST'</span>;
|
||
<span class="hljs-keyword">if</span> (options.emulateJSON) params.data._method = type;
|
||
<span class="hljs-keyword">var</span> beforeSend = options.beforeSend;
|
||
options.beforeSend = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">xhr</span>) </span>{
|
||
xhr.setRequestHeader(<span class="hljs-string">'X-HTTP-Method-Override'</span>, type);
|
||
<span class="hljs-keyword">if</span> (beforeSend) <span class="hljs-keyword">return</span> beforeSend.apply(<span class="hljs-keyword">this</span>, <span class="hljs-built_in">arguments</span>);
|
||
};
|
||
}</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-180">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-180">¶</a>
|
||
</div>
|
||
<p>Don’t process data on a non-GET request.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (params.type !== <span class="hljs-string">'GET'</span> && !options.emulateJSON) {
|
||
params.processData = <span class="hljs-literal">false</span>;
|
||
}</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-181">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-181">¶</a>
|
||
</div>
|
||
<p>Pass along <code>textStatus</code> and <code>errorThrown</code> from jQuery.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> error = options.error;
|
||
options.error = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">xhr, textStatus, errorThrown</span>) </span>{
|
||
options.textStatus = textStatus;
|
||
options.errorThrown = errorThrown;
|
||
<span class="hljs-keyword">if</span> (error) error.call(options.context, xhr, textStatus, errorThrown);
|
||
};</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-182">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-182">¶</a>
|
||
</div>
|
||
<p>Make the request, allowing the user to override any Ajax options.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> xhr = options.xhr = Backbone.ajax(_.extend(params, options));
|
||
model.trigger(<span class="hljs-string">'request'</span>, model, xhr, options);
|
||
<span class="hljs-keyword">return</span> xhr;
|
||
};</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-183">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-183">¶</a>
|
||
</div>
|
||
<p>Map from CRUD to HTTP for our default <code>Backbone.sync</code> implementation.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> methodMap = {
|
||
<span class="hljs-string">'create'</span>: <span class="hljs-string">'POST'</span>,
|
||
<span class="hljs-string">'update'</span>: <span class="hljs-string">'PUT'</span>,
|
||
<span class="hljs-string">'patch'</span>: <span class="hljs-string">'PATCH'</span>,
|
||
<span class="hljs-string">'delete'</span>: <span class="hljs-string">'DELETE'</span>,
|
||
<span class="hljs-string">'read'</span>: <span class="hljs-string">'GET'</span>
|
||
};</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-184">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-184">¶</a>
|
||
</div>
|
||
<p>Set the default implementation of <code>Backbone.ajax</code> to proxy through to <code>$</code>.
|
||
Override this if you’d like to use a different library.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> Backbone.ajax = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
|
||
<span class="hljs-keyword">return</span> Backbone.$.ajax.apply(Backbone.$, <span class="hljs-built_in">arguments</span>);
|
||
};</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-185">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-185">¶</a>
|
||
</div>
|
||
<h2 id="backbone-router">Backbone.Router</h2>
|
||
|
||
</div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-186">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-186">¶</a>
|
||
</div>
|
||
|
||
</div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-187">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-187">¶</a>
|
||
</div>
|
||
<p>Routers map faux-URLs to actions, and fire events when routes are
|
||
matched. Creating a new one sets its <code>routes</code> hash, if not set statically.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> Router = Backbone.Router = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">options</span>) </span>{
|
||
options || (options = {});
|
||
<span class="hljs-keyword">if</span> (options.routes) <span class="hljs-keyword">this</span>.routes = options.routes;
|
||
<span class="hljs-keyword">this</span>._bindRoutes();
|
||
<span class="hljs-keyword">this</span>.initialize.apply(<span class="hljs-keyword">this</span>, <span class="hljs-built_in">arguments</span>);
|
||
};</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-188">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-188">¶</a>
|
||
</div>
|
||
<p>Cached regular expressions for matching named param parts and splatted
|
||
parts of route strings.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> optionalParam = <span class="hljs-regexp">/\((.*?)\)/g</span>;
|
||
<span class="hljs-keyword">var</span> namedParam = <span class="hljs-regexp">/(\(\?)?:\w+/g</span>;
|
||
<span class="hljs-keyword">var</span> splatParam = <span class="hljs-regexp">/\*\w+/g</span>;
|
||
<span class="hljs-keyword">var</span> escapeRegExp = <span class="hljs-regexp">/[\-{}\[\]+?.,\\\^$|#\s]/g</span>;</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-189">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-189">¶</a>
|
||
</div>
|
||
<p>Set up all inheritable <strong>Backbone.Router</strong> properties and methods.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> _.extend(Router.prototype, Events, {</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-190">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-190">¶</a>
|
||
</div>
|
||
<p>Initialize is an empty function by default. Override it with your own
|
||
initialization logic.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> initialize: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>)</span>{},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-191">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-191">¶</a>
|
||
</div>
|
||
<p>Manually bind a single named route to a callback. For example:</p>
|
||
<pre><code><span class="hljs-keyword">this</span>.route(<span class="hljs-string">'search/:query/p:num'</span>, <span class="hljs-string">'search'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">query, num</span>) </span>{
|
||
...
|
||
});
|
||
</code></pre>
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> route: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">route, name, callback</span>) </span>{
|
||
<span class="hljs-keyword">if</span> (!_.isRegExp(route)) route = <span class="hljs-keyword">this</span>._routeToRegExp(route);
|
||
<span class="hljs-keyword">if</span> (_.isFunction(name)) {
|
||
callback = name;
|
||
name = <span class="hljs-string">''</span>;
|
||
}
|
||
<span class="hljs-keyword">if</span> (!callback) callback = <span class="hljs-keyword">this</span>[name];
|
||
<span class="hljs-keyword">var</span> router = <span class="hljs-keyword">this</span>;
|
||
Backbone.history.route(route, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">fragment</span>) </span>{
|
||
<span class="hljs-keyword">var</span> args = router._extractParameters(route, fragment);
|
||
<span class="hljs-keyword">if</span> (router.execute(callback, args, name) !== <span class="hljs-literal">false</span>) {
|
||
router.trigger.apply(router, [<span class="hljs-string">'route:'</span> + name].concat(args));
|
||
router.trigger(<span class="hljs-string">'route'</span>, name, args);
|
||
Backbone.history.trigger(<span class="hljs-string">'route'</span>, router, name, args);
|
||
}
|
||
});
|
||
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-192">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-192">¶</a>
|
||
</div>
|
||
<p>Execute a route handler with the provided parameters. This is an
|
||
excellent place to do pre-route setup or post-route cleanup.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> execute: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">callback, args, name</span>) </span>{
|
||
<span class="hljs-keyword">if</span> (callback) callback.apply(<span class="hljs-keyword">this</span>, args);
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-193">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-193">¶</a>
|
||
</div>
|
||
<p>Simple proxy to <code>Backbone.history</code> to save a fragment into the history.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> navigate: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">fragment, options</span>) </span>{
|
||
Backbone.history.navigate(fragment, options);
|
||
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-194">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-194">¶</a>
|
||
</div>
|
||
<p>Bind all defined routes to <code>Backbone.history</code>. We have to reverse the
|
||
order of the routes here to support behavior where the most general
|
||
routes can be defined at the bottom of the route map.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> _bindRoutes: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
|
||
<span class="hljs-keyword">if</span> (!<span class="hljs-keyword">this</span>.routes) <span class="hljs-keyword">return</span>;
|
||
<span class="hljs-keyword">this</span>.routes = _.result(<span class="hljs-keyword">this</span>, <span class="hljs-string">'routes'</span>);
|
||
<span class="hljs-keyword">var</span> route, routes = _.keys(<span class="hljs-keyword">this</span>.routes);
|
||
<span class="hljs-keyword">while</span> ((route = routes.pop()) != <span class="hljs-literal">null</span>) {
|
||
<span class="hljs-keyword">this</span>.route(route, <span class="hljs-keyword">this</span>.routes[route]);
|
||
}
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-195">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-195">¶</a>
|
||
</div>
|
||
<p>Convert a route string into a regular expression, suitable for matching
|
||
against the current location hash.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> _routeToRegExp: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">route</span>) </span>{
|
||
route = route.replace(escapeRegExp, <span class="hljs-string">'\\$&'</span>)
|
||
.replace(optionalParam, <span class="hljs-string">'(?:$1)?'</span>)
|
||
.replace(namedParam, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">match, optional</span>) </span>{
|
||
<span class="hljs-keyword">return</span> optional ? match : <span class="hljs-string">'([^/?]+)'</span>;
|
||
})
|
||
.replace(splatParam, <span class="hljs-string">'([^?]*?)'</span>);
|
||
<span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">RegExp</span>(<span class="hljs-string">'^'</span> + route + <span class="hljs-string">'(?:\\?([\\s\\S]*))?$'</span>);
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-196">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-196">¶</a>
|
||
</div>
|
||
<p>Given a route, and a URL fragment that it matches, return the array of
|
||
extracted decoded parameters. Empty or unmatched parameters will be
|
||
treated as <code>null</code> to normalize cross-browser behavior.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> _extractParameters: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">route, fragment</span>) </span>{
|
||
<span class="hljs-keyword">var</span> params = route.exec(fragment).slice(<span class="hljs-number">1</span>);
|
||
<span class="hljs-keyword">return</span> _.map(params, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">param, i</span>) </span>{</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-197">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-197">¶</a>
|
||
</div>
|
||
<p>Don’t decode the search params.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (i === params.length - <span class="hljs-number">1</span>) <span class="hljs-keyword">return</span> param || <span class="hljs-literal">null</span>;
|
||
<span class="hljs-keyword">return</span> param ? <span class="hljs-built_in">decodeURIComponent</span>(param) : <span class="hljs-literal">null</span>;
|
||
});
|
||
}
|
||
|
||
});</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-198">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-198">¶</a>
|
||
</div>
|
||
<h2 id="backbone-history">Backbone.History</h2>
|
||
|
||
</div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-199">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-199">¶</a>
|
||
</div>
|
||
|
||
</div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-200">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-200">¶</a>
|
||
</div>
|
||
<p>Handles cross-browser history management, based on either
|
||
<a href="http://diveintohtml5.info/history.html">pushState</a> and real URLs, or
|
||
<a href="https://developer.mozilla.org/en-US/docs/DOM/window.onhashchange">onhashchange</a>
|
||
and URL fragments. If the browser supports neither (old IE, natch),
|
||
falls back to polling.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> History = Backbone.History = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
|
||
<span class="hljs-keyword">this</span>.handlers = [];
|
||
<span class="hljs-keyword">this</span>.checkUrl = _.bind(<span class="hljs-keyword">this</span>.checkUrl, <span class="hljs-keyword">this</span>);</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-201">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-201">¶</a>
|
||
</div>
|
||
<p>Ensure that <code>History</code> can be used outside of the browser.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> <span class="hljs-built_in">window</span> !== <span class="hljs-string">'undefined'</span>) {
|
||
<span class="hljs-keyword">this</span>.location = <span class="hljs-built_in">window</span>.location;
|
||
<span class="hljs-keyword">this</span>.history = <span class="hljs-built_in">window</span>.history;
|
||
}
|
||
};</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-202">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-202">¶</a>
|
||
</div>
|
||
<p>Cached regex for stripping a leading hash/slash and trailing space.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> routeStripper = <span class="hljs-regexp">/^[#\/]|\s+$/g</span>;</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-203">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-203">¶</a>
|
||
</div>
|
||
<p>Cached regex for stripping leading and trailing slashes.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> rootStripper = <span class="hljs-regexp">/^\/+|\/+$/g</span>;</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-204">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-204">¶</a>
|
||
</div>
|
||
<p>Cached regex for stripping urls of hash.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> pathStripper = <span class="hljs-regexp">/#.*$/</span>;</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-205">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-205">¶</a>
|
||
</div>
|
||
<p>Has the history handling already been started?</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> History.started = <span class="hljs-literal">false</span>;</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-206">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-206">¶</a>
|
||
</div>
|
||
<p>Set up all inheritable <strong>Backbone.History</strong> properties and methods.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> _.extend(History.prototype, Events, {</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-207">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-207">¶</a>
|
||
</div>
|
||
<p>The default interval to poll for hash changes, if necessary, is
|
||
twenty times a second.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> interval: <span class="hljs-number">50</span>,</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-208">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-208">¶</a>
|
||
</div>
|
||
<p>Are we at the app root?</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> atRoot: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
|
||
<span class="hljs-keyword">var</span> path = <span class="hljs-keyword">this</span>.location.pathname.replace(<span class="hljs-regexp">/[^\/]$/</span>, <span class="hljs-string">'$&/'</span>);
|
||
<span class="hljs-keyword">return</span> path === <span class="hljs-keyword">this</span>.root && !<span class="hljs-keyword">this</span>.getSearch();
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-209">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-209">¶</a>
|
||
</div>
|
||
<p>Does the pathname match the root?</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> matchRoot: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
|
||
<span class="hljs-keyword">var</span> path = <span class="hljs-keyword">this</span>.decodeFragment(<span class="hljs-keyword">this</span>.location.pathname);
|
||
<span class="hljs-keyword">var</span> rootPath = path.slice(<span class="hljs-number">0</span>, <span class="hljs-keyword">this</span>.root.length - <span class="hljs-number">1</span>) + <span class="hljs-string">'/'</span>;
|
||
<span class="hljs-keyword">return</span> rootPath === <span class="hljs-keyword">this</span>.root;
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-210">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-210">¶</a>
|
||
</div>
|
||
<p>Unicode characters in <code>location.pathname</code> are percent encoded so they’re
|
||
decoded for comparison. <code>%25</code> should not be decoded since it may be part
|
||
of an encoded parameter.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> decodeFragment: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">fragment</span>) </span>{
|
||
<span class="hljs-keyword">return</span> <span class="hljs-built_in">decodeURI</span>(fragment.replace(<span class="hljs-regexp">/%25/g</span>, <span class="hljs-string">'%2525'</span>));
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-211">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-211">¶</a>
|
||
</div>
|
||
<p>In IE6, the hash fragment and search params are incorrect if the
|
||
fragment contains <code>?</code>.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> getSearch: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
|
||
<span class="hljs-keyword">var</span> match = <span class="hljs-keyword">this</span>.location.href.replace(<span class="hljs-regexp">/#.*/</span>, <span class="hljs-string">''</span>).match(<span class="hljs-regexp">/\?.+/</span>);
|
||
<span class="hljs-keyword">return</span> match ? match[<span class="hljs-number">0</span>] : <span class="hljs-string">''</span>;
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-212">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-212">¶</a>
|
||
</div>
|
||
<p>Gets the true hash value. Cannot use location.hash directly due to bug
|
||
in Firefox where location.hash will always be decoded.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> getHash: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">window</span>) </span>{
|
||
<span class="hljs-keyword">var</span> match = (<span class="hljs-built_in">window</span> || <span class="hljs-keyword">this</span>).location.href.match(<span class="hljs-regexp">/#(.*)$/</span>);
|
||
<span class="hljs-keyword">return</span> match ? match[<span class="hljs-number">1</span>] : <span class="hljs-string">''</span>;
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-213">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-213">¶</a>
|
||
</div>
|
||
<p>Get the pathname and search params, without the root.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> getPath: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
|
||
<span class="hljs-keyword">var</span> path = <span class="hljs-keyword">this</span>.decodeFragment(
|
||
<span class="hljs-keyword">this</span>.location.pathname + <span class="hljs-keyword">this</span>.getSearch()
|
||
).slice(<span class="hljs-keyword">this</span>.root.length - <span class="hljs-number">1</span>);
|
||
<span class="hljs-keyword">return</span> path.charAt(<span class="hljs-number">0</span>) === <span class="hljs-string">'/'</span> ? path.slice(<span class="hljs-number">1</span>) : path;
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-214">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-214">¶</a>
|
||
</div>
|
||
<p>Get the cross-browser normalized URL fragment from the path or hash.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> getFragment: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">fragment</span>) </span>{
|
||
<span class="hljs-keyword">if</span> (fragment == <span class="hljs-literal">null</span>) {
|
||
<span class="hljs-keyword">if</span> (<span class="hljs-keyword">this</span>._usePushState || !<span class="hljs-keyword">this</span>._wantsHashChange) {
|
||
fragment = <span class="hljs-keyword">this</span>.getPath();
|
||
} <span class="hljs-keyword">else</span> {
|
||
fragment = <span class="hljs-keyword">this</span>.getHash();
|
||
}
|
||
}
|
||
<span class="hljs-keyword">return</span> fragment.replace(routeStripper, <span class="hljs-string">''</span>);
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-215">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-215">¶</a>
|
||
</div>
|
||
<p>Start the hash change handling, returning <code>true</code> if the current URL matches
|
||
an existing route, and <code>false</code> otherwise.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> start: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">options</span>) </span>{
|
||
<span class="hljs-keyword">if</span> (History.started) <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">'Backbone.history has already been started'</span>);
|
||
History.started = <span class="hljs-literal">true</span>;</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-216">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-216">¶</a>
|
||
</div>
|
||
<p>Figure out the initial configuration. Do we need an iframe?
|
||
Is pushState desired … is it available?</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">this</span>.options = _.extend({root: <span class="hljs-string">'/'</span>}, <span class="hljs-keyword">this</span>.options, options);
|
||
<span class="hljs-keyword">this</span>.root = <span class="hljs-keyword">this</span>.options.root;
|
||
<span class="hljs-keyword">this</span>._wantsHashChange = <span class="hljs-keyword">this</span>.options.hashChange !== <span class="hljs-literal">false</span>;
|
||
<span class="hljs-keyword">this</span>._hasHashChange = <span class="hljs-string">'onhashchange'</span> <span class="hljs-keyword">in</span> <span class="hljs-built_in">window</span> && (<span class="hljs-built_in">document</span>.documentMode === <span class="hljs-keyword">void</span> <span class="hljs-number">0</span> || <span class="hljs-built_in">document</span>.documentMode > <span class="hljs-number">7</span>);
|
||
<span class="hljs-keyword">this</span>._useHashChange = <span class="hljs-keyword">this</span>._wantsHashChange && <span class="hljs-keyword">this</span>._hasHashChange;
|
||
<span class="hljs-keyword">this</span>._wantsPushState = !!<span class="hljs-keyword">this</span>.options.pushState;
|
||
<span class="hljs-keyword">this</span>._hasPushState = !!(<span class="hljs-keyword">this</span>.history && <span class="hljs-keyword">this</span>.history.pushState);
|
||
<span class="hljs-keyword">this</span>._usePushState = <span class="hljs-keyword">this</span>._wantsPushState && <span class="hljs-keyword">this</span>._hasPushState;
|
||
<span class="hljs-keyword">this</span>.fragment = <span class="hljs-keyword">this</span>.getFragment();</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-217">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-217">¶</a>
|
||
</div>
|
||
<p>Normalize root to always include a leading and trailing slash.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">this</span>.root = (<span class="hljs-string">'/'</span> + <span class="hljs-keyword">this</span>.root + <span class="hljs-string">'/'</span>).replace(rootStripper, <span class="hljs-string">'/'</span>);</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-218">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-218">¶</a>
|
||
</div>
|
||
<p>Transition from hashChange to pushState or vice versa if both are
|
||
requested.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (<span class="hljs-keyword">this</span>._wantsHashChange && <span class="hljs-keyword">this</span>._wantsPushState) {</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-219">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-219">¶</a>
|
||
</div>
|
||
<p>If we’ve started off with a route from a <code>pushState</code>-enabled
|
||
browser, but we’re currently in a browser that doesn’t support it…</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (!<span class="hljs-keyword">this</span>._hasPushState && !<span class="hljs-keyword">this</span>.atRoot()) {
|
||
<span class="hljs-keyword">var</span> rootPath = <span class="hljs-keyword">this</span>.root.slice(<span class="hljs-number">0</span>, <span class="hljs-number">-1</span>) || <span class="hljs-string">'/'</span>;
|
||
<span class="hljs-keyword">this</span>.location.replace(rootPath + <span class="hljs-string">'#'</span> + <span class="hljs-keyword">this</span>.getPath());</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-220">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-220">¶</a>
|
||
</div>
|
||
<p>Return immediately as browser will do redirect to new url</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-221">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-221">¶</a>
|
||
</div>
|
||
<p>Or if we’ve started out with a hash-based route, but we’re currently
|
||
in a browser where it could be <code>pushState</code>-based instead…</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (<span class="hljs-keyword">this</span>._hasPushState && <span class="hljs-keyword">this</span>.atRoot()) {
|
||
<span class="hljs-keyword">this</span>.navigate(<span class="hljs-keyword">this</span>.getHash(), {replace: <span class="hljs-literal">true</span>});
|
||
}
|
||
|
||
}</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-222">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-222">¶</a>
|
||
</div>
|
||
<p>Proxy an iframe to handle location events if the browser doesn’t
|
||
support the <code>hashchange</code> event, HTML5 history, or the user wants
|
||
<code>hashChange</code> but not <code>pushState</code>.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (!<span class="hljs-keyword">this</span>._hasHashChange && <span class="hljs-keyword">this</span>._wantsHashChange && !<span class="hljs-keyword">this</span>._usePushState) {
|
||
<span class="hljs-keyword">this</span>.iframe = <span class="hljs-built_in">document</span>.createElement(<span class="hljs-string">'iframe'</span>);
|
||
<span class="hljs-keyword">this</span>.iframe.src = <span class="hljs-string">'javascript:0'</span>;
|
||
<span class="hljs-keyword">this</span>.iframe.style.display = <span class="hljs-string">'none'</span>;
|
||
<span class="hljs-keyword">this</span>.iframe.tabIndex = <span class="hljs-number">-1</span>;
|
||
<span class="hljs-keyword">var</span> body = <span class="hljs-built_in">document</span>.body;</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-223">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-223">¶</a>
|
||
</div>
|
||
<p>Using <code>appendChild</code> will throw on IE < 9 if the document is not ready.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> iWindow = body.insertBefore(<span class="hljs-keyword">this</span>.iframe, body.firstChild).contentWindow;
|
||
iWindow.document.open();
|
||
iWindow.document.close();
|
||
iWindow.location.hash = <span class="hljs-string">'#'</span> + <span class="hljs-keyword">this</span>.fragment;
|
||
}</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-224">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-224">¶</a>
|
||
</div>
|
||
<p>Add a cross-platform <code>addEventListener</code> shim for older browsers.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> addEventListener = <span class="hljs-built_in">window</span>.addEventListener || <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">eventName, listener</span>) </span>{
|
||
<span class="hljs-keyword">return</span> attachEvent(<span class="hljs-string">'on'</span> + eventName, listener);
|
||
};</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-225">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-225">¶</a>
|
||
</div>
|
||
<p>Depending on whether we’re using pushState or hashes, and whether
|
||
‘onhashchange’ is supported, determine how we check the URL state.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (<span class="hljs-keyword">this</span>._usePushState) {
|
||
addEventListener(<span class="hljs-string">'popstate'</span>, <span class="hljs-keyword">this</span>.checkUrl, <span class="hljs-literal">false</span>);
|
||
} <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (<span class="hljs-keyword">this</span>._useHashChange && !<span class="hljs-keyword">this</span>.iframe) {
|
||
addEventListener(<span class="hljs-string">'hashchange'</span>, <span class="hljs-keyword">this</span>.checkUrl, <span class="hljs-literal">false</span>);
|
||
} <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (<span class="hljs-keyword">this</span>._wantsHashChange) {
|
||
<span class="hljs-keyword">this</span>._checkUrlInterval = setInterval(<span class="hljs-keyword">this</span>.checkUrl, <span class="hljs-keyword">this</span>.interval);
|
||
}
|
||
|
||
<span class="hljs-keyword">if</span> (!<span class="hljs-keyword">this</span>.options.silent) <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.loadUrl();
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-226">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-226">¶</a>
|
||
</div>
|
||
<p>Disable Backbone.history, perhaps temporarily. Not useful in a real app,
|
||
but possibly useful for unit testing Routers.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> stop: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-227">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-227">¶</a>
|
||
</div>
|
||
<p>Add a cross-platform <code>removeEventListener</code> shim for older browsers.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> removeEventListener = <span class="hljs-built_in">window</span>.removeEventListener || <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">eventName, listener</span>) </span>{
|
||
<span class="hljs-keyword">return</span> detachEvent(<span class="hljs-string">'on'</span> + eventName, listener);
|
||
};</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-228">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-228">¶</a>
|
||
</div>
|
||
<p>Remove window listeners.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (<span class="hljs-keyword">this</span>._usePushState) {
|
||
removeEventListener(<span class="hljs-string">'popstate'</span>, <span class="hljs-keyword">this</span>.checkUrl, <span class="hljs-literal">false</span>);
|
||
} <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (<span class="hljs-keyword">this</span>._useHashChange && !<span class="hljs-keyword">this</span>.iframe) {
|
||
removeEventListener(<span class="hljs-string">'hashchange'</span>, <span class="hljs-keyword">this</span>.checkUrl, <span class="hljs-literal">false</span>);
|
||
}</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-229">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-229">¶</a>
|
||
</div>
|
||
<p>Clean up the iframe if necessary.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (<span class="hljs-keyword">this</span>.iframe) {
|
||
<span class="hljs-built_in">document</span>.body.removeChild(<span class="hljs-keyword">this</span>.iframe);
|
||
<span class="hljs-keyword">this</span>.iframe = <span class="hljs-literal">null</span>;
|
||
}</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-230">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-230">¶</a>
|
||
</div>
|
||
<p>Some environments will throw when clearing an undefined interval.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (<span class="hljs-keyword">this</span>._checkUrlInterval) clearInterval(<span class="hljs-keyword">this</span>._checkUrlInterval);
|
||
History.started = <span class="hljs-literal">false</span>;
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-231">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-231">¶</a>
|
||
</div>
|
||
<p>Add a route to be tested when the fragment changes. Routes added later
|
||
may override previous routes.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> route: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">route, callback</span>) </span>{
|
||
<span class="hljs-keyword">this</span>.handlers.unshift({route: route, callback: callback});
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-232">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-232">¶</a>
|
||
</div>
|
||
<p>Checks the current URL to see if it has changed, and if it has,
|
||
calls <code>loadUrl</code>, normalizing across the hidden iframe.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> checkUrl: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">e</span>) </span>{
|
||
<span class="hljs-keyword">var</span> current = <span class="hljs-keyword">this</span>.getFragment();</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-233">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-233">¶</a>
|
||
</div>
|
||
<p>If the user pressed the back button, the iframe’s hash will have
|
||
changed and we should use that for comparison.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (current === <span class="hljs-keyword">this</span>.fragment && <span class="hljs-keyword">this</span>.iframe) {
|
||
current = <span class="hljs-keyword">this</span>.getHash(<span class="hljs-keyword">this</span>.iframe.contentWindow);
|
||
}
|
||
|
||
<span class="hljs-keyword">if</span> (current === <span class="hljs-keyword">this</span>.fragment) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
|
||
<span class="hljs-keyword">if</span> (<span class="hljs-keyword">this</span>.iframe) <span class="hljs-keyword">this</span>.navigate(current);
|
||
<span class="hljs-keyword">this</span>.loadUrl();
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-234">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-234">¶</a>
|
||
</div>
|
||
<p>Attempt to load the current URL fragment. If a route succeeds with a
|
||
match, returns <code>true</code>. If no defined routes matches the fragment,
|
||
returns <code>false</code>.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> loadUrl: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">fragment</span>) </span>{</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-235">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-235">¶</a>
|
||
</div>
|
||
<p>If the root doesn’t match, no routes can match either.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (!<span class="hljs-keyword">this</span>.matchRoot()) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
|
||
fragment = <span class="hljs-keyword">this</span>.fragment = <span class="hljs-keyword">this</span>.getFragment(fragment);
|
||
<span class="hljs-keyword">return</span> _.some(<span class="hljs-keyword">this</span>.handlers, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">handler</span>) </span>{
|
||
<span class="hljs-keyword">if</span> (handler.route.test(fragment)) {
|
||
handler.callback(fragment);
|
||
<span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
|
||
}
|
||
});
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-236">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-236">¶</a>
|
||
</div>
|
||
<p>Save a fragment into the hash history, or replace the URL state if the
|
||
‘replace’ option is passed. You are responsible for properly URL-encoding
|
||
the fragment in advance.</p>
|
||
<p>The options object can contain <code>trigger: true</code> if you wish to have the
|
||
route callback be fired (not usually desirable), or <code>replace: true</code>, if
|
||
you wish to modify the current URL without adding an entry to the history.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> navigate: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">fragment, options</span>) </span>{
|
||
<span class="hljs-keyword">if</span> (!History.started) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
|
||
<span class="hljs-keyword">if</span> (!options || options === <span class="hljs-literal">true</span>) options = {trigger: !!options};</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-237">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-237">¶</a>
|
||
</div>
|
||
<p>Normalize the fragment.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> fragment = <span class="hljs-keyword">this</span>.getFragment(fragment || <span class="hljs-string">''</span>);</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-238">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-238">¶</a>
|
||
</div>
|
||
<p>Don’t include a trailing slash on the root.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> rootPath = <span class="hljs-keyword">this</span>.root;
|
||
<span class="hljs-keyword">if</span> (fragment === <span class="hljs-string">''</span> || fragment.charAt(<span class="hljs-number">0</span>) === <span class="hljs-string">'?'</span>) {
|
||
rootPath = rootPath.slice(<span class="hljs-number">0</span>, <span class="hljs-number">-1</span>) || <span class="hljs-string">'/'</span>;
|
||
}
|
||
<span class="hljs-keyword">var</span> url = rootPath + fragment;</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-239">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-239">¶</a>
|
||
</div>
|
||
<p>Strip the hash and decode for matching.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> fragment = <span class="hljs-keyword">this</span>.decodeFragment(fragment.replace(pathStripper, <span class="hljs-string">''</span>));
|
||
|
||
<span class="hljs-keyword">if</span> (<span class="hljs-keyword">this</span>.fragment === fragment) <span class="hljs-keyword">return</span>;
|
||
<span class="hljs-keyword">this</span>.fragment = fragment;</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-240">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-240">¶</a>
|
||
</div>
|
||
<p>If pushState is available, we use it to set the fragment as a real URL.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (<span class="hljs-keyword">this</span>._usePushState) {
|
||
<span class="hljs-keyword">this</span>.history[options.replace ? <span class="hljs-string">'replaceState'</span> : <span class="hljs-string">'pushState'</span>]({}, <span class="hljs-built_in">document</span>.title, url);</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-241">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-241">¶</a>
|
||
</div>
|
||
<p>If hash changes haven’t been explicitly disabled, update the hash
|
||
fragment to store history.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (<span class="hljs-keyword">this</span>._wantsHashChange) {
|
||
<span class="hljs-keyword">this</span>._updateHash(<span class="hljs-keyword">this</span>.location, fragment, options.replace);
|
||
<span class="hljs-keyword">if</span> (<span class="hljs-keyword">this</span>.iframe && fragment !== <span class="hljs-keyword">this</span>.getHash(<span class="hljs-keyword">this</span>.iframe.contentWindow)) {
|
||
<span class="hljs-keyword">var</span> iWindow = <span class="hljs-keyword">this</span>.iframe.contentWindow;</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-242">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-242">¶</a>
|
||
</div>
|
||
<p>Opening and closing the iframe tricks IE7 and earlier to push a
|
||
history entry on hash-tag change. When replace is true, we don’t
|
||
want this.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (!options.replace) {
|
||
iWindow.document.open();
|
||
iWindow.document.close();
|
||
}
|
||
|
||
<span class="hljs-keyword">this</span>._updateHash(iWindow.location, fragment, options.replace);
|
||
}</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-243">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-243">¶</a>
|
||
</div>
|
||
<p>If you’ve told us that you explicitly don’t want fallback hashchange-
|
||
based history, then <code>navigate</code> becomes a page refresh.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> } <span class="hljs-keyword">else</span> {
|
||
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.location.assign(url);
|
||
}
|
||
<span class="hljs-keyword">if</span> (options.trigger) <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.loadUrl(fragment);
|
||
},</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-244">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-244">¶</a>
|
||
</div>
|
||
<p>Update the hash location, either replacing the current entry, or adding
|
||
a new one to the browser history.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> _updateHash: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">location, fragment, replace</span>) </span>{
|
||
<span class="hljs-keyword">if</span> (replace) {
|
||
<span class="hljs-keyword">var</span> href = location.href.replace(<span class="hljs-regexp">/(javascript:|#).*$/</span>, <span class="hljs-string">''</span>);
|
||
location.replace(href + <span class="hljs-string">'#'</span> + fragment);
|
||
} <span class="hljs-keyword">else</span> {</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-245">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-245">¶</a>
|
||
</div>
|
||
<p>Some browsers require that <code>hash</code> contains a leading #.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> location.hash = <span class="hljs-string">'#'</span> + fragment;
|
||
}
|
||
}
|
||
|
||
});</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-246">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-246">¶</a>
|
||
</div>
|
||
<p>Create the default Backbone.history.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> Backbone.history = <span class="hljs-keyword">new</span> History;</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-247">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-247">¶</a>
|
||
</div>
|
||
<h2 id="helpers">Helpers</h2>
|
||
|
||
</div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-248">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-248">¶</a>
|
||
</div>
|
||
|
||
</div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-249">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-249">¶</a>
|
||
</div>
|
||
<p>Helper function to correctly set up the prototype chain for subclasses.
|
||
Similar to <code>goog.inherits</code>, but uses a hash of prototype properties and
|
||
class properties to be extended.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> extend = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">protoProps, staticProps</span>) </span>{
|
||
<span class="hljs-keyword">var</span> parent = <span class="hljs-keyword">this</span>;
|
||
<span class="hljs-keyword">var</span> child;</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-250">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-250">¶</a>
|
||
</div>
|
||
<p>The constructor function for the new subclass is either defined by you
|
||
(the “constructor” property in your <code>extend</code> definition), or defaulted
|
||
by us to simply call the parent constructor.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (protoProps && _.has(protoProps, <span class="hljs-string">'constructor'</span>)) {
|
||
child = protoProps.constructor;
|
||
} <span class="hljs-keyword">else</span> {
|
||
child = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>)</span>{ <span class="hljs-keyword">return</span> parent.apply(<span class="hljs-keyword">this</span>, <span class="hljs-built_in">arguments</span>); };
|
||
}</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-251">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-251">¶</a>
|
||
</div>
|
||
<p>Add static properties to the constructor function, if supplied.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> _.extend(child, parent, staticProps);</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-252">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-252">¶</a>
|
||
</div>
|
||
<p>Set the prototype chain to inherit from <code>parent</code>, without calling
|
||
<code>parent</code>‘s constructor function and add the prototype properties.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> child.prototype = _.create(parent.prototype, protoProps);
|
||
child.prototype.constructor = child;</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-253">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-253">¶</a>
|
||
</div>
|
||
<p>Set a convenience property in case the parent’s prototype is needed
|
||
later.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> child.__super__ = parent.prototype;
|
||
|
||
<span class="hljs-keyword">return</span> child;
|
||
};</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-254">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-254">¶</a>
|
||
</div>
|
||
<p>Set up inheritance for the model, collection, router, view and history.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> Model.extend = Collection.extend = Router.extend = View.extend = History.extend = extend;</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-255">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-255">¶</a>
|
||
</div>
|
||
<p>Throw an error when a URL is needed, and none is supplied.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> urlError = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
|
||
<span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">'A "url" property or function must be specified'</span>);
|
||
};</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-256">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-256">¶</a>
|
||
</div>
|
||
<p>Wrap an optional error callback with a fallback error event.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> wrapError = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">model, options</span>) </span>{
|
||
<span class="hljs-keyword">var</span> error = options.error;
|
||
options.error = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">resp</span>) </span>{
|
||
<span class="hljs-keyword">if</span> (error) error.call(options.context, model, resp, options);
|
||
model.trigger(<span class="hljs-string">'error'</span>, model, resp, options);
|
||
};
|
||
};
|
||
|
||
<span class="hljs-keyword">return</span> Backbone;
|
||
});</pre></div></div>
|
||
|
||
</li>
|
||
|
||
</ul>
|
||
</div>
|
||
</body>
|
||
</html>
|