2
<html xmlns="http://www.w3.org/1999/html">
4
<meta http-equiv="content-type" content="text/html;charset=UTF-8">
5
<meta http-equiv="X-UA-Compatible" content="chrome=1">
6
<meta name="viewport" content="width=device-width">
7
<link rel="icon" href="static/images/favicon.ico">
9
<link href="http://fonts.googleapis.com/css?family=Arimo" rel="stylesheet" type="text/css">
10
<link rel="stylesheet" type="text/css" href="static/css/style.css">
12
<title>Backbone-relational.js</title>
16
document.createElement('header');
17
document.createElement('nav');
18
document.createElement('section');
19
document.createElement('article');
20
document.createElement('aside');
21
document.createElement('footer');
22
document.createElement('hgroup');
28
<a class="toc_title" href="#">
29
Backbone-relational.js <span class="version">(0.8.6)</span>
33
<li class="link_out"><a href="https://github.com/PaulUithol/Backbone-relational">GitHub Repository</a></li>
36
<a class="toc_title" href="#introduction">
40
<a class="toc_title" href="#installation">
44
<a class="toc_title" href="#RelationalModel">
45
Backbone.RelationalModel
50
<a href="#RelationalModel-relations">relations</a>
52
<li><a href="#relations-key">key</a></li>
53
<li><a href="#relations-relatedModel">relatedModel</a></li>
54
<li><a href="#relations-type">type</a></li>
55
<li><a href="#relations-includeInJSON">includeInJSON</a></li>
56
<li><a href="#relations-autoFetch">autoFetch</a></li>
57
<li><a href="#relations-collectionType">collectionType</a></li>
58
<li><a href="#relations-collectionKey">collectionKey</a></li>
59
<li><a href="#relations-collectionOptions">collectionOptions</a></li>
60
<li><a href="#relations-createModels">createModels</a></li>
61
<li><a href="#relations-keySource">keySource</a></li>
62
<li><a href="#relations-keyDestination">keyDestination</a></li>
63
<li><a href="#relations-parse">parse</a></li>
64
<li><a href="#relations-reverseRelation">reverseRelation</a></li>
69
<li><a href="#RelationalModel-subModelTypes">subModelTypes</a></li>
70
<li><a href="#RelationalModel-subModelTypeAttribute">subModelTypeAttribute</a></li>
73
<li><a href="#RelationalModel-getRelation">getRelation</a></li>
74
<li><a href="#RelationalModel-getRelations">getRelations</a></li>
75
<li><a href="#RelationalModel-fetchRelated">fetchRelated</a></li>
76
<li><a href="#RelationalModel-set">set</a></li>
77
<li><a href="#RelationalModel-toJSON">toJSON</a></li>
80
<li><a href="#RelationalModel-setup">setup</a></li>
81
<li><a href="#RelationalModel-build">build</a></li>
82
<li><a href="#RelationalModel-findOrCreate">findOrCreate</a></li>
83
<li><a href="#RelationalModel-find">find</a></li>
86
<li><a href="#RelationalModel-events"><strong>Catalog of Events</strong></a></li>
89
<a class="toc_title" href="#Relation">
94
<li><a href="#Relation-HasOne">HasOne</a></li>
95
<li><a href="#Relation-HasMany">HasMany</a></li>
98
<a class="toc_title" href="#Store">
103
<li><a href="#Store-addModelScope">addModelScope</a></li>
104
<li><a href="#Store-removeModelScope">removeModelScope</a></li>
105
<li><a href="#Store-reset">reset</a></li>
108
<a class="toc_title" href="#examples">
112
<a class="toc_title" href="#change-log">
116
<a class="toc_title" href="#under-the-hood">
121
<div class="container">
124
Backbone-relational.js
128
When developing any medium to large-scale web application, you often get to the point where
129
an action by a user can cause a number of different models to change on the client and the server.
132
You can try to keep updating both sides of a relation manually for every action, and individually call
133
<a href="http://backbonejs.org/#Model-save">save()</a> or <a href="http://backbonejs.org/#Model-fetch">fetch()</a>
134
on each of the changed models to sync with the server, but that quickly turns into a tedious process and
135
results in multiple requests.
136
Instead, we can configure relationships between our models, and sync the model and all of its related models with a single
137
<a href="http://backbonejs.org/#Model-save">save()</a> or <a href="http://backbonejs.org/#Model-fetch">fetch()</a>.
140
Backbone-relational is hosted on <a href="https://github.com/PaulUithol/Backbone-relational">GitHub</a>,
141
and is available under the <a href="https://github.com/PaulUithol/Backbone-relational/blob/master/LICENSE.txt">MIT license</a>.
145
<section id="downloads">
147
Downloads & Dependencies
148
<span style="padding-left: 7px; font-size:11px; font-weight: normal;" class="interface">(Right-click, and use
154
<td><a class="punch" href="https://raw.github.com/PaulUithol/Backbone-relational/0.8.6/backbone-relational.js">Latest Release (0.8.6)</a></td>
155
<td class="text"><i>~66kb. Full source, uncompressed, lots of comments.</i></td>
158
<td><a class="punch" href="https://raw.github.com/PaulUithol/Backbone-relational/master/backbone-relational.js">Development Version</a></td>
163
Backbone-relational depends on <a href="http://backbonejs.org/">Backbone.js</a> <small>(>= 1.0.0)</small>,
164
which itself requires <a href="http://underscorejs.org">Underscore.js</a> <small>(> 1.4.4)</small> and
165
<a href="http://jquery.com">jQuery</a> <small>(> 1.7.0)</small> or
166
<a href="http://zeptojs.com/">Zepto</a>.
170
<section id="introduction">
171
<h2>Introduction</h2>
174
Backbone-relational.js provides one-to-one, one-to-many and many-to-one relations
175
between models for Backbone. To use relations, extend <a href="#RelationalModel"><strong>Backbone.RelationalModel</strong></a>
176
(instead of a regular <a href="http://backbonejs.org/#Model">Backbone.Model</a>) and define a
177
<a href="#RelationalModel-relations"><q>relations</q></a> property, containing an array of option objects.
178
Each relation must define (at least) the <a href="#relations-type"><q>type</q></a>, <a href="#relations-key"><q>key</q></a>,
179
and <a href="#relations-relatedModel"><q>relatedModel</q></a>. Available relation types are
180
<a href="#Relation-HasOne"><q>Backbone.HasOne</q></a> and <a href="#Relation-HasMany"><q>Backbone.HasMany</q></a>.
184
Backbone-relational's main features include:
189
Bidirectional relations, which notify related models of changes through events.
192
Control how relations are serialized using the <a href="#relations-includeInJSON"><q>includeInJSON</q></a> option.
195
Automatically convert nested objects in a model's attributes into model instances using the
196
<a href="#relations-createModels"><q>createModels</q></a> option.
199
Lazily retrieve a set of related models through the <a href="#RelationalModel-fetchRelated"><q>fetchRelated</q></a>
203
Determine the type of HasMany collections with <a href="#relations-collectionType"><q>collectionType</q></a>.
208
You can also bind new events to a <strong>Backbone.RelationalModel</strong> for an:
213
<strong>addition</strong> to a HasMany relation with <a href="#RelationalModel-events">add:<key></a>.
216
<strong>removal</strong> from a HasMany relation with <a href="#RelationalModel-events">remove:<key></a>.
219
<strong>reset</strong> of a HasMany relation with <a href="#RelationalModel-events">reset:<key></a>.
222
<strong>changes</strong> to the contents of a HasMany or HasOne relations with <a href="#RelationalModel-events">change:
228
<section id="installation">
229
<h2>Installation</h2>
232
Backbone-relational depends on <a href="http://backbonejs.org/">Backbone.js</a> (and thus on
233
<a href="http://underscorejs.org">Underscore.js</a>). Include Backbone-relational right after Backbone
237
<pre class="language-markup"><code class="language-markup"><!--
238
--><script type="text/javascript" src="./js/underscore.js"></script>
239
<!-- --><script type="text/javascript" src="./js/backbone.js"></script>
240
<!-- --><script type="text/javascript" src="./js/backbone-relational.js"></script>
244
<section id="RelationalModel">
246
Backbone.RelationalModel
250
When using Backbone-relational, each model defining (or receiving) <q>relations</q> must extend
251
<strong>Backbone.RelationalModel</strong> in order to function. <strong>Backbone.RelationalModel</strong>
252
introduces a couple of new methods, events and properties. It's important to know which are properties,
253
which are methods of an instance, and which operate on the type itself.
254
These three subcategories are detailed below.
258
<strong>Properties</strong> can be defined when extending Backbone.RelationalModel, or a subclass thereof.
262
<li><a href="#RelationalModel-relations">relations</a></li>
263
<li><a href="#RelationalModel-subModelTypes">subModelTypes</a></li>
264
<li><a href="#RelationalModel-subModelTypeAttribute">subModelTypeAttribute</a></li>
268
<strong>Instance methods</strong> operate on an instance of a type.
272
<li><a href="#RelationalModel-getRelation">getRelation</a></li>
273
<li><a href="#RelationalModel-getRelations">getRelations</a></li>
274
<li><a href="#RelationalModel-fetchRelated">fetchRelated</a></li>
275
<li><a href="#RelationalModel-set">set</a></li>
276
<li><a href="#RelationalModel-toJSON">toJSON</a></li>
280
<strong>Static methods</strong> operate on the type itself, as opposed to operating on model instances.
284
<li><a href="#RelationalModel-setup">setup</a></li>
285
<li><a href="#RelationalModel-build">build</a></li>
286
<li><a href="#RelationalModel-findOrCreate">findOrCreate</a></li>
287
<li><a href="#RelationalModel-find">find</a></li>
290
<h3 id="RelationalModel-properties">
294
<h4 class="code" id="RelationalModel-relations">
295
relations<code>relation[]</code>
298
A <strong>Backbone.RelationalModel</strong> may contain an array of relation definitions. Each relation supports a number of
299
options, of which <a href="#relations-relatedModel"><q>relatedModel</q></a>, <a href="#relations-key"><q>key</q></a> and
300
<a href="#relations-type"><q>type</q></a> are mandatory. A relation could look like the following:
303
<pre class="language-javascript"><code id="example-zoo" class="language-javascript runnable"><!--
304
-->Zoo = Backbone.RelationalModel.extend({
306
type: Backbone.HasMany,
308
relatedModel: 'Animal',
309
collectionType: 'AnimalCollection',
313
// 'relatedModel' is automatically set to 'Zoo'; the 'relationType' to 'HasOne'.
318
Animal = Backbone.RelationalModel.extend({
322
AnimalCollection = Backbone.Collection.extend({
326
// We've now created a fully managed relation. When you add or remove model from `zoo.animals`,
327
// or update `animal.livesIn`, the other side of the relation will automatically be updated.
328
var artis = new Zoo( { name: 'Artis' } );
329
var lion = new Animal( { species: 'Lion', livesIn: artis } );
331
// `animals` in `artis` now contains `lion`
332
alert( artis.get( 'animals' ).pluck( 'species' ) );
334
<pre class="language-javascript nomargin"><code class="language-javascript runnable" data-setup="#example-zoo"><!--
335
-->var amersfoort = new Zoo( { name: 'Dierenpark Amersfoort', animals: [ lion ] } );
337
// `lion` now livesIn `amersfoort`, and `animals` in `artis` no longer contains `lion`
338
alert( lion.get( 'livesIn' ).get( 'name' ) + ', ' + artis.get( 'animals' ).length );
341
<section id="relations-key">
343
key<code>relation.key</code>
346
Required. A string that references an attribute name on <a href="#relations-relatedModel"><q>relatedModel</q></a>.
349
<h4 class="code" id="relations-relatedModel">
350
relatedModel<code>relation.relatedModel</code>
353
Required. A string that can be resolved to an object on the global scope, or a reference to a
354
<strong>Backbone.RelationalModel</strong>. Also see <a href="#Store-addModelScope"><q>addModelScope</q></a>.
358
<section id="relations-type">
360
type<code>relation.type</code>
363
Required. A string that references a <a href="#Relation"><q>Backbone.Relation</q></a> type by name ("HasOne" or "HasMany"),
364
or a direct reference to a relation type.
367
You can model a one-to-one or a many-to-one relationship by declaring <q>type</q> as the string "HasOne", or by
368
directly referencing <a href="#Relation-HasOne"><q>Backbone.HasOne</q></a>. A HasOne relation contains a single
369
<strong>Backbone.RelationalModel</strong>. The default <q>reverseRelation.type</q> for a "HasOne" relation is
370
"HasMany". This can be set to "HasOne" instead, to create a one-to-one relation.
373
You can model a one-to-many relationship by declaring <q>type</q> as the string "HasMany", or by directly
374
referencing <a href="#Relation-HasMany"><q>Backbone.HasMany</q></a>. A HasMany relation contains a Backbone.Collection,
375
containing zero or more <strong>Backbone.RelationalModel</strong>s. The default <q>reverseRelation.type</q>
376
for a HasMany relation is HasOne; this is the only option here, since many-to-many is not supported directly.
379
It is possible model a many-to-many relationship using two <a href="#Relation-HasMany"><q>Backbone.HasMany</q></a>
380
relations, with a link model in between:
384
<pre class="language-javascript"><code class="language-javascript" id="example-job"><!--
385
-->Person = Backbone.RelationalModel.extend({
396
// A link object between 'Person' and 'Company'
397
Job = Backbone.RelationalModel.extend({
404
Company = Backbone.RelationalModel.extend({
416
<section id="relations-includeInJSON">
418
includeInJSON<code>relation.includeInJSON</code>
421
A boolean, a string referencing one of the model's attributes, or an array of strings referencing model
422
attributes. Default: <q>true</q>.
425
Determines how the contents of a relation will be serialized following a call to the
426
<a href="#RelationalModel-toJSON"><q>toJSON</q></a> method. If you specify a:
431
<strong>Boolean</strong>: a value of true serializes the full set of attributes on the related model(s).
432
Set to false to exclude the relation completely.
435
<strong>String</strong>: include a single attribute from the related model(s). For example, 'name', or
436
<q>Backbone.Model.prototype.idAttribute</q> to include ids.
439
<strong>String[]</strong>: includes the specified attributes from the related model(s).
444
Specifying <q>true</q> will cascade, meaning the relations of nested model will get serialized as well,
445
until either a different value is found for <q>includeInJSON</q> or we encounter a model that has already
450
<section id="relations-autoFetch">
452
autoFetch<code>relation.autoFetch</code>
455
A boolean or an object. Default: <q>false</q>.
458
If this property is set to <q>true</q>, when a model is instantiated the related model is
459
automatically fetched using <a href="#RelationalModel-fetchRelated"><q>fetchRelated</q></a>. The
460
value of the property can also be an object. In that case the object is passed to
461
<a href="#RelationalModel-fetchRelated"><q>fetchRelated</q></a> as the options parameter.
464
Note that <q>autoFetch</q> operates independently from other `fetch` operations,
465
including those that may have fetched the current model.
469
<pre class="language-javascript"><code class="language-javascript"><!--
470
-->var Shop = Backbone.RelationalModel.extend({
473
type: Backbone.HasMany,
475
relatedModel: 'Customer',
479
type: Backbone.HasOne,
481
relatedModel: 'Address',
483
success: function( model, response ) {
486
error: function( model, response ) {
495
<section id="relations-collectionType">
497
collectionType<code>relation.collectionType</code>
500
A string that can be resolved to an object type on the global scope, or a reference to a
501
<strong>Backbone.Collection</strong> type.
504
Determine the type of collections used for a HasMany relation. If you define a
505
url(models<Backbone.Model[]>) function on the specified collection, this enables
506
<a href="#RelationalModel-fetchRelated"><q>fetchRelated</q></a> to fetch all missing models in one request, instead of
507
firing a separate request for each.
510
<h4 class="code" id="relations-collectionKey">
511
collectionKey<code>relation.collectionKey</code>
514
A string or a boolean. Default: <q>true</q>.
517
Used to create a back reference from the <strong>Backbone.Collection</strong> used for a HasMany relation to the model on
518
the other side of this relation. By default, the relation's key attribute will be used to create a reference to
519
the RelationalModel instance from the generated collection. If you set <q>collectionKey</q> to a string,
520
it will use that string as the reference to the RelationalModel, rather than the
521
relation's key attribute. If you don't want this behavior at all, set <q>collectionKey</q> to <q>false</q>
522
(or any falsy value) and this reference will not be created.
526
<section id="relations-collectionOptions">
528
collectionOptions<code>relation.collectionOptions</code>
531
An options hash, or a function that accepts an instance of a <strong>Backbone.RelationalModel</strong> and returns an options
535
Used to provide options for the initialization of the collection in the 'Many'-end of a HasMany relation. Can be
536
an options hash or a function that should take the instance in the 'One'-end of the 'HasMany' relation and return
541
<section id="relations-createModels">
543
createModels<code>relation.createModels</code>
546
A boolean. Default: <q>true</q>.
549
Specifies whether models will be created from nested objects or not.
553
<section id="relations-keySource">
555
keySource<code>relation.keySource</code>
558
A string that references an attribute to deserialize data for <a href="#relations-relatedModel"><q>relatedModel</q></a> from.
561
Used to override key when determining what data to use when (de)serializing a relation, since the data backing
562
your relations may use different naming conventions. For example, a Rails backend may provide the keys suffixed
563
with <q>_id</q> or <q>_ids</q>. The behavior for <q>keySource</q> corresponds to the following rules:
566
When a relation is instantiated, the contents of the <q>keySource</q> are used as it's initial data. The
567
application uses the regular key attribute to interface with the relation and the models in it; the
568
<q>keySource</q> is not available as an attribute for the model. So you may be provided with data containing
569
<q>animal_ids</q>, while you want to access this relation as <q>zoo.get('animals')</q>.
572
Note that setting <q>keySource</q> will set <a href="#relations-keyDestination"><q>keyDestination</q></a>
573
to the same value, if it isn't specified itself.
574
This means that when saving zoo, the animals attribute will be serialized back into the <q>animal_ids</q> key.
577
WARNING: when using a keySource, you should not use that attribute name for other purposes.
581
<section id="relations-keyDestination">
583
keyDestination<code>relation.keyDestination</code>
586
A string that references an attribute to serialize <a href="#relations-relatedModel"><q>relatedModel</q></a> into.
589
Used to override key (and <a href="#relations-keySource"><q>keySource</q></a>) when determining what attribute to be
590
written into when serializing a relation, since the server backing your relations may use different naming
591
conventions. For example, a Rails backend may expect the keys to be suffixed with _attributes for nested
595
When calling <a href="#RelationalModel-toJSON"><q>toJSON</q></a> on a model (either via
596
<strong>Backbone.Sync</strong>, or directly), the data in the key attribute is transformed and assigned to the
597
<q>keyDestination</q>.
600
So you may want a relation to be serialized into the animals_attributes key, while you want to access this
601
relation as <q>zoo.get( 'animals' );</q>.
604
WARNING: when using a <q>keyDestination</q>, you should not use that attribute name for other purposes.
608
<pre class="language-javascript"><code class="language-javascript runnable" data-setup="#example-zoo"><!--
609
-->var FarmAnimal = Animal.extend();
611
// This `Farm` is confused, like legacy stuff can be. It wants its data back on a completely
612
// different key than it supplies it on. We want to use a different one in our app as well.
613
var Farm = Backbone.RelationalModel.extend({
615
type: Backbone.HasMany,
617
keySource: 'livestock',
618
keyDestination: 'pets',
619
relatedModel: FarmAnimal,
622
includeInJSON: 'name'
627
// Create a `Farm`; parse `species`, add to `animals`, output goes to `pets`.
628
var farm = new Farm( { name: 'Old MacDonald', livestock: [ { species: 'Sheep' } ] } );
629
farm.get( 'animals' ).add( { species: 'Cow' } );
630
alert( JSON.stringify( farm.toJSON(), null, 4 ) );
633
<section id="relations-parse">
635
parse<code>relation.parse</code>
638
A boolean. Default: <q>false</q>.
641
If you have a relation where the models should be parsed when data is being set, specify `parse: true`.
645
<section id="relations-reverseRelation">
647
reverseRelation<code>relation.reverseRelation</code>
650
An object specifying the relation pointing back to this model from <a href="#relations-relatedModel"><q>relatedModel</q></a>.
653
If the relation should be bidirectional, specify the details for the reverse relation here. It's only mandatory
654
to supply a <a href="#relations-key"><q>key</q></a>; <a href="#relations-relatedModel"><q>relatedModel</q></a> is automatically
655
set. The default type for a <q>reverseRelation</q> is HasMany for a
656
HasOne relation (which can be overridden to HasOne in order to create a one-to-one relation), and HasOne for a
657
HasMany relation. In this case, you cannot create a <q>reverseRelation</q> with
658
type HasMany as well; please see Many-to-many relations on how to model these type of relations.
661
Note that if you define a relation (plus a reverseRelation) on a model, but don't actually create an instance
662
of that model, it is possible <q>initializeRelations</q> will never get called, and the reverseRelation
663
will not be initialized. This can happen when <q>extend</q> has been overridden, or redefined as in CoffeeScript.
664
See <a href="#RelationalModel-setup">setup</a>.
668
<section id="RelationalModel-subModelTypes">
670
subModelTypes<code>relationalModel.subModelTypes(attributes<object>, [options<object>])</code>
673
An object. Default: <q>{}</q>.
676
A mapping that defines what submodels exist for the model (the superModel) on which
677
<q>subModelTypes</q> is defined. The keys are used to match the
678
<a href="#RelationalModel-subModelTypeAttribute"><q>subModelTypeAttribute</q></a> when deserializing, and the values
679
determine what type of submodel should be created for a key. When building model instances from data, we need to
680
determine what kind of object we're dealing with in order to create instances of the right subModel type. This
681
is done by finding the model for which the key is equal to the value of the
682
<a href="#RelationalModel-subModelTypeAttribute"><q>subModelTypeAttribute</q></a> attribute on the passed in data.
685
Each subModel is considered to be a proper submodel of its superclass (the model type you're extending), with a
686
shared id pool. This means that when looking for an object of the supermodel's type, objects of a submodel's type
687
can be returned as well, as long as the id matches. In effect, any relations pointing to the supermodel will look
688
for instances of it's submodels as well.
692
<pre class="language-javascript"><code class="language-javascript runnable" data-setup="#example-zoo"><!--
693
-->Mammal = Animal.extend({
695
'primate': 'Primate',
696
'carnivore': 'Carnivore'
700
Primate = Mammal.extend();
701
Carnivore = Mammal.extend();
703
MammalCollection = AnimalCollection.extend({
707
// Create a collection that contains a 'Primate' and a 'Carnivore'.
708
var mammals = new MammalCollection([
709
{ id: 3, species: 'chimp', type: 'primate' },
710
{ id: 5, species: 'panther', type: 'carnivore' }
713
var chimp = mammals.get( 3 );
715
alert( 'chimp is an animal? ' + ( chimp instanceof Animal ) + '\n' +
716
'chimp is a carnivore? ' + ( chimp instanceof Carnivore ) + '\n' +
717
'chimp is a primate? ' + ( chimp instanceof Primate ) );
721
Suppose that we have an Mammal model and a Primate model extending Mammal. If we have a Primate object with id 3,
722
this object will be returned when we have a relation pointing to a Mammal with id 3, as Primate is regarded a
723
specific kind of Mammal; it's just a Mammal with possibly some primate-specific properties or methods.
726
Note that this means that there cannot be any overlap in ids between instances of Mammal and Primate, as the
727
Primate with id 3 will be the Mammal with id 3.
731
<section id="RelationalModel-subModelTypeAttribute">
733
subModelTypeAttribute<code>relationalModel.subModelTypeAttribute</code>
736
A string. Default: <q>type</q>.
739
The <q>subModelTypeAttribute</q> is a references an attribute on the data
740
used to instantiate <a href="#relations-relatedModel"><q>relatedModel</q></a>. The attribute that will be checked to
741
determine the type of model that should be built when a raw object of attributes is set as the related value,
742
and if the <a href="#relations-relatedModel"><q>relatedModel</q></a> has one or more submodels.
746
<h3 id="RelationalModel-instance-methods">
750
<section id="RelationalModel-getRelation">
752
getRelation<code>relationModel.getRelation(name<string>)</code>
755
Returns: <q>Backbone.Relation</q> A single initialized relation on the model.
759
<section id="RelationalModel-getRelations">
761
getRelations<code>relationModel.getRelations()</code>
764
Returns: <q>Backbone.Relation[]</q> The set of initialized relations on the model.
768
<section id="RelationalModel-fetchRelated">
770
fetchRelated<code>relationalModel.fetchRelated(key<string>, [options<object>], [update<boolean>])</code>
773
Returns: <q>deferred[]</q> An array of request objects.
776
Fetch models from the server that were referenced in the model's attributes, but have not been found/created yet.
777
This can be used specifically for lazy-loading scenarios. Setting update to true guarantees that the model will
778
be fetched from the server and any model that already exists in the store will be updated with the retrieved data.
779
The options object specifies options to be passed to <a href="http://backbonejs.org/#Sync">Backbone.Sync</a>.
782
By default, a separate request will be fired for each additional model that is to be fetched from the server.
783
However, if your server/API supports it, you can fetch the set of models in one request by specifying a
784
collectionType for the relation you call fetchRelated on. The <a href="#relations-collectionType"><q>collectionType</q></a>
785
should have an overridden <a href="http://backbonejs.org/#Collection-url"><q>url</q></a>
786
method that allows it to construct a url for an array of models. See <a href="#example-person">this example</a>
787
or <a href="https://github.com/PaulUithol/backbone-tastypie">Backbone-tastypie</a> for an example.
791
<section id="RelationalModel-set">
793
set<code>set(key<string>, value, [options<object>]) <strong>or</strong> set(attributes<object>, [options<object>])</code>
796
Returns: <q>Backbone.RelationalModel</q> The model instance.
799
The <q>set</q> method is overridden so that setting a value on an "relational" attribute will update that relation.
800
This is especially important to keep in mind for <q>HasMany</q> relations (which are backed by a <q>Backbone.Collection</q>).
801
For these, calling <q>set</q> can be thought of as being equivalent to calling <q>update</q> on the collection itself,
802
including how the options are handled.
805
Additional <q>options</q> for a <q>HasMany</q> relation:
809
<dd>Default: <q>true</q>. If true, models specified in the arguments but not yet present in the relation will be added to the relation.</dd>
810
<dt><q>merge</q></dt>
811
<dd>Default: <q>true</q>. If true, existing models will be updated with the given attributes.</dd>
812
<dt><q>remove</q></dt>
813
<dd>Default: <q>true</q>. If true, models present in the relation but not specified in the arguments will be removed.</dd>
817
<section id="RelationalModel-toJSON">
819
toJSON<code>relationModel.toJSON(name<string>)</code>
822
Returns: <q>Object</q> The JSON representation of the model.
823
See <a href="http://backbonejs.org/#Model-toJSON">Backbone.Model.toJSON</a>.
826
The regular <q>toJSON</q> function has been overridden and modified to serialize (nested) relations
827
according to their <a href="#relations-includeInJSON"><q>includeInJSON</q></a>, <a href="#relations-keySource"><q>keySource</q></a>,
828
and <a href="#relations-keyDestination"><q>keyDestination</q></a> options.
832
<h3 id="RelationalModel-static-methods">
836
<section id="RelationalModel-setup">
838
setup<code>relationModel.setup()</code>
841
Returns: <q>Backbone.RelationalModel.constuctor</q> The type.
844
Initialize the relations and submodels for the model type. Normally, this happens automatically, but it doesn't if
845
you're using CoffeeScript and using the syntax <q>class MyModel extends Backbone.RelationalModel</q> instead of
846
the JavaScript equivalent of <q>MyModel = Backbone.RelationalModel.extend()</q>.
849
This has advantages in CoffeeScript, but it also means that <q>Backbone.Model.extend</q> will not get called.
850
Instead, CoffeeScript generates piece of code that would normally achieve the same. However, <q>extend</q> is also
851
the method that Backbone-relational overrides to set up relations as you're defining your <q>Backbone.RelationalModel</q> subclass.
854
In this case, you should call <q>setup</q> manually after defining your subclass CoffeeScript-style. For example:
857
Note: this is a static method. It operate on the model type itself, not on an instance.
861
<pre class="language-javascript"><code class="language-javascript"><!--
862
-->class MyModel extends Backbone.RelationalModel
870
<section id="RelationalModel-build">
872
build<code>relationalModel.build(attributes<object>, [options<object>])</code>
875
Returns: <q>Backbone.RelationalModel</q> A model instance.
878
Create an instance of a model, taking into account what submodels have been defined.
881
Note: this is a static method. It operate on the model type itself, not on an instance.
885
<section id="RelationalModel-findOrCreate">
888
<code>relationalModel.findOrCreate(attributes<string|number|object>, [options<object>])</code>
891
Returns: <q>Backbone.RelationalModel</q> A model instance.
894
Search for a model instance in the <a href="#Store">Backbone.Relational.store</a>, and return the model if found.
895
If no model is found, a new model will be created if <q>options.create</q> is <q>true</q>.
898
Accepted <q>options</q>:
901
<dt><q>create</q></dt>
902
<dd>Default: <q>true</q>. If true, a new model will be created if an instance matching <q>attributes</q> isn't found in the store.</dd>
903
<dt><q>merge</q></dt>
904
<dd>Default: <q>true</q>. If true, a found model will be updated with <q>attributes</q> (if <q>attributes</q> is an <q>object</q>).</dd>
905
<dt><q>parse</q></dt>
906
<dd>Default: <q>false</q>. If true, <q>attributes</q> will be parsed first. Please note this will cause <q>Model.parse</q> to be called
907
as a function (<q>this</q> will not point to a model), instead of as a method.</dd>
910
Note: this is a static method. It operate on the model type itself, not on an instance.
914
<section id="RelationalModel-find">
917
<code>relationalModel.findOrCreate(attributes<string|number|object>, [options<object>])</code>
920
Returns: <q>Backbone.RelationalModel</q> A model instance.
923
A shortcut for <a href="#RelationalModel-findOrCreate"><q>findOrCreate</q></a> that uses <q>create: false</q>.
924
Accepts the same options as <q>findOrCreate</q> (except for <q>create</q>).
927
Note: this is a static method. It operate on the model type itself, not on an instance.
931
<section id="RelationalModel-events">
936
Backbone-relational makes a couple of additional events available to you, on top of the events already found in Backbone.
941
An <strong>"add"</strong> event is triggered on addition to a HasMany relation. Bind to:<br/>
942
<q>add:<key></q> →<code>function(addedModel<Backbone.Model>, related<Backbone.Collection>)</code>
945
A <strong>"remove"</strong> event is triggered on removal from a HasMany relation. Bind to:<br/>
946
<q>remove:<key></q> →<code>function(removedModel<Backbone.Model>, related<Backbone.Collection>)</code>
949
A <strong>"change"</strong> event is triggered on changes to the contents of both HasOne and HasMany relations. Bind to:<br/>
950
<q>change:<key></q> →<code>function(model<Backbone.Model>, related<Backbone.Model|Backbone.Collection>)</code>
956
<section id="Relation">
957
<h2 >Backbone.Relation</h2>
959
Each <a href="#RelationalModel-relations">relation</a> definition on a model is used to create in instance of a <q>Backbone.Relation</q>; either
960
a <q>Backbone.HasOne</q> or a <q>Backbone.HasMany</q>.
963
<h4 class="code" id="Relation-HasOne">
967
Defines a <strong>HasOne</strong> relation. When defining a <a href="#relations-reverseRelation">reverseRelation</a>, the default type
968
will be <strong>HasMany</strong>. However, this can also be set to <strong>HasOne</strong> to define a one-to-one relation.
971
<h4 class="code" id="Relation-HasMany">
975
Defines a <strong>HasMany</strong> relation. When defining a <a href="#relations-reverseRelation">reverseRelation</a>, the type
976
will be <strong>HasOne</strong>.
981
<h2 >Backbone.Store</h2>
983
<strong>Backbone.Store</strong> is a global model cache. Per application, one instance is created (much like <q>Backbone.History</q>),
984
which is accessible as <q>Backbone.Relational.store</q>.
987
<h4 class="code" id="Store-addModelScope">
988
addModelScope<code>Backbone.Relational.store.addModelScope( scope<object> )</code>
991
Add a namespace on which models and collections are defined. This is especially useful when working in an
992
environment without a shared global scope (like <q>window</q> is in a browser), where you'll need to tell
993
the <q>store</q> where your models are defined, so it can resolve them to create and maintain relations.
996
<h4 class="code" id="Store-removeModelScope">
997
removeModelScope<code>Backbone.Relational.store.removeModelScope()</code>
1000
Remove a scope. This allows you to remove a scope you added previously, or to remove the default 'global'
1001
scope (<q>window</q> in the browser) scope to prevent Backbone-relational from resolving objects on it.
1004
<h4 class="code" id="Store-reset">
1005
reset<code>Backbone.Relational.store.reset()</code>
1008
Reset the <q>store</q> to it's original state. This will disable relations for all models created up to this point,
1009
remove added model scopes, and removed all internal store collections.
1013
<section id="examples">
1016
<a href="http://antoviaque.org/docs/tutorials/backbone-relational-tutorial/">A tutorial by antoviaque</a>,
1017
and the <a href="https://github.com/antoviaque/backbone-relational-tutorial">accompanying git repository</a>.
1020
A basic working example to get you started:
1023
<pre class="language-javascript"><code id="example-person-run1" class="language-javascript runnable" data-setup="#example-person"><!--
1024
-->var paul = new Person({
1027
user: { id: 'user-1', login: 'dude', email: 'me@gmail.com' }
1030
// A User object is automatically created from the JSON; so 'login' returns 'dude'.
1031
paul.get('user').get('login');
1033
var ourHouse = new House({
1035
location: 'in the middle of the street',
1036
occupants: ['person-1', 'person-2', 'person-5']
1039
// 'ourHouse.occupants' is turned into a Backbone.Collection of Persons.
1040
// The first person in 'ourHouse.occupants' will point to 'paul'.
1041
ourHouse.get('occupants').at(0); // === paul
1043
// If a collection is created from a HasMany relation, it contains a reference
1044
// back to the originator of the relation
1045
ourHouse.get('occupants').livesIn; // === ourHouse
1047
// The `occupants` relation on 'House' has been defined as a HasMany, with a reverse relation
1048
// to `livesIn` on 'Person'. So, 'paul.livesIn' will automatically point back to 'ourHouse'.
1049
paul.get('livesIn'); // === ourHouse
1051
// You can control which relations get serialized to JSON, using the 'includeInJSON'
1052
// property on a Relation. Also, each object will only get serialized once to prevent loops.
1053
alert( JSON.stringify( paul.get('user').toJSON(), null, '\t' ) );
1055
<pre class="language-javascript nomargin"><code id="example-person-run2" class="language-javascript runnable" data-setup="#example-person-run1"><!--
1056
-->// Load occupants 'person-2' and 'person-5', which don't exist yet, from the server
1057
ourHouse.fetchRelated( 'occupants' );
1059
// Use the `add` and `remove` events to listen for additions/removals on a HasMany relation.
1060
// Here, we listen for changes to `ourHouse.occupants`.
1062
.on( 'add:occupants', function( model, coll ) {
1063
console.log( 'add %o', model );
1064
// Do something. Create a View?
1066
.on( 'remove:occupants', function( model, coll ) {
1067
console.log( 'remove %o', model );
1068
// Do somehting. Destroy a View?
1071
// Use the 'update' event to listen for changes on a HasOne relation (like 'Person.livesIn').
1072
paul.on( 'change:livesIn', function( model, attr ) {
1073
console.log( 'change `livesIn` to %o', attr );
1076
// Modifying either side of a bi-directional relation updates the other side automatically.
1077
// Take `paul` out or `ourHouse`; this triggers `remove:occupants` on `ourHouse`,
1078
// and `change:livesIn` on `paul`
1079
ourHouse.get( 'occupants' ).remove( paul );
1081
alert( 'paul.livesIn=' + paul.get( 'livesIn' ) );
1083
<pre class="language-javascript nomargin"><code id="example-person-run3" class="language-javascript runnable" data-setup="#example-person-run2"><!--
1084
-->// Move into `theirHouse`; triggers 'add:occupants' on ourHouse, and 'change:livesIn' on paul
1085
theirHouse = new House( { id: 'house-2' } );
1086
paul.set( { 'livesIn': theirHouse } );
1088
alert( 'theirHouse.occupants=' + theirHouse.get( 'occupants' ).pluck( 'name' ) );
1091
<p>This is achieved using the following relations and models:</p>
1093
<pre class="language-javascript"><code class="language-javascript" id="example-person"><!--
1094
-->House = Backbone.RelationalModel.extend({
1095
// The 'relations' property, on the House's prototype. Initialized separately for each
1096
// instance of House. Each relation must define (as a minimum) the 'type', 'key' and
1097
// 'relatedModel'. Options include 'includeInJSON', 'createModels' and 'reverseRelation'.
1100
type: Backbone.HasMany, // Use the type, or the string 'HasOne' or 'HasMany'.
1102
relatedModel: 'Person',
1103
includeInJSON: Backbone.Model.prototype.idAttribute,
1104
collectionType: 'PersonCollection',
1112
Person = Backbone.RelationalModel.extend({
1114
{ // Create a (recursive) one-to-one relationship
1115
type: Backbone.HasOne,
1117
relatedModel: 'User',
1119
type: Backbone.HasOne,
1125
initialize: function() {
1126
// do whatever you want :)
1130
PersonCollection = Backbone.Collection.extend({
1131
url: function( models ) {
1132
// Logic to create a url for the whole collection, or a set of models.
1133
// See the tests, or Backbone-tastypie, for an example.
1134
return '/person/' + ( models ? 'set/' + _.pluck( models, 'id' ).join(';') + '/' : '' );
1138
User = Backbone.RelationalModel.extend();
1142
<section id="change-log">
1147
<span class="date">(future)</span> –
1148
<a href="https://github.com/PaulUithol/Backbone-relational/compare/0.8.6...master">diff</a> –
1149
<a href="https://raw.github.com/PaulUithol/Backbone-relational/master/backbone-relational.js">download</a>
1157
<span class="date">(16 August 2013)</span> –
1158
<a href="https://github.com/PaulUithol/Backbone-relational/compare/0.8.5...0.8.6">diff</a> –
1159
<a href="https://raw.github.com/PaulUithol/Backbone-relational/master/backbone-relational.js">download</a>
1164
<a href="https://github.com/PaulUithol/Backbone-relational/pull/322"><q>#322</q></a>:
1165
Remove <q>keySource</q> after a <q>set</q> as well.
1168
<a href="https://github.com/PaulUithol/Backbone-relational/pull/345"><q>#345</q></a>:
1169
Add <a href="#RelationalModel-find"><q>find</q></a>, a shortcut to <q>findOrCreate</q> with <q>create: false</q>
1172
<a href="https://github.com/PaulUithol/Backbone-relational/pull/345"><q>#345</q></a>:
1173
Add lodash compatibility (doesn't have an explicit <q>findWhere</q>).
1176
<a href="https://github.com/PaulUithol/Backbone-relational/pull/349"><q>#349</q></a>:
1177
Event ordering: maintain the originally intended order when process gets called more than once.
1180
<a href="https://github.com/PaulUithol/Backbone-relational/pull/362"><q>#362</q></a>:
1181
Add support for deep <q>subModelType</q> hierarchies.
1184
<a href="https://github.com/PaulUithol/Backbone-relational/pull/380"><q>#380</q></a>:
1185
AFix <q>pop</q> on an empty collection.
1188
<a href="https://github.com/PaulUithol/Backbone-relational/pull/370"><q>#370</q></a>:
1189
<q>relations</q> can now be a property or a function.
1192
<a href="https://github.com/PaulUithol/Backbone-relational/commit/7f1dc51a820aa4a5e22303177cffbbc8e7c53d47"><q>7f1dc51</q></a>:
1193
<q>relatedModel</q> and <q>collectionType</q> can now be defined as a function as well.
1199
<span class="date">(10 April 2013)</span> –
1200
<a href="https://github.com/PaulUithol/Backbone-relational/compare/0.8.0...0.8.5">diff</a> –
1201
<a href="https://raw.github.com/PaulUithol/Backbone-relational/0.8.5/backbone-relational.js">download</a>
1205
<li>Supports Backbone 1.0.0</li>
1207
<a href="https://github.com/PaulUithol/Backbone-relational/issues/191"><q>#191</q></a>:
1208
if <q>includeInJSON</q> is equal to the model's <q>idAttribute</q>, "missing" models will be included
1209
in the JSON to avoid data loss.
1212
<a href="https://github.com/PaulUithol/Backbone-relational/issues/201"><q>#201</q></a>:
1213
add <q>Backbone.Store.removeModelScope</q> method
1216
<a href="https://github.com/PaulUithol/Backbone-relational/issues/273"><q>#273</q></a>:
1217
improve merging of relations between super/subModels.
1220
<a href="https://github.com/PaulUithol/Backbone-relational/issues/295"><q>#295</q></a>:
1221
check (and error on) duplicate ids when explicitly setting the <q>idAttribute</q>.
1224
<a href="https://github.com/PaulUithol/Backbone-relational/issues/320"><q>#320</q></a>:
1225
use <q>merge: true</q> by default on <q>Collection.reset</q>.
1231
<span class="date">5 March 2013</span> –
1232
<a href="https://github.com/PaulUithol/Backbone-relational/compare/0.7.1...0.8.0">diff</a> –
1233
<a href="https://raw.github.com/PaulUithol/Backbone-relational/0.8.0/backbone-relational.js">download</a>
1238
General performance improvements, refactored <q>HasMany.onChange</q> to eliminate unnecessary events.
1241
Implemented the <q>add</q>, <q>merge</q> and <q>remove</q> options on <q>Collection.add</q> when working with RelationalModels.
1242
This also works when using <a href="#RelationalModel-set"><q>set</q></a> to change the key on nested relations.
1245
The <q>update</q> option on <a href="#RelationalModel-findOrCreate"><q>findOrCreate</q></a> has been
1246
renamed to <q>merge</q>, since it's behavior corresponds with <q>merge</q> on <q>Collection.add</q>
1247
(and not with <q>update</q> on <q>Collection.reset</q>).
1250
The <q>update:<key></q> event has been removed, in favor of handling everything using "standard"
1251
<q>change:<key></q> events.
1254
<a href="#RelationalModel-findOrCreate"><q>findOrCreate</q></a> now takes a <q>parse</q> option,
1255
analogous to the Backbone.Model constructor. It defaults to <q>false</q>.
1257
<li>Added a <a href="#relations-parse"><q>parse</q></a> option to relations.</li>
1262
<span class="date">17 Januari 2013</span> –
1263
<a href="https://github.com/PaulUithol/Backbone-relational/compare/0.7.0...0.7.1">diff</a> –
1264
<a href="https://raw.github.com/PaulUithol/Backbone-relational/0.7.1/backbone-relational.js">download</a>
1268
<li>Compatible with Backbone >= 0.9.10</li>
1269
<li>Implemented the <a href="#relations-autoFetch"><q>autoFetch</q></a> property for relations.</li>
1270
<li>Added the <q>update</q> option to <a href="#RelationalModel-findOrCreate"><q>findOrCreate</q></a>.</li>
1275
<span class="date">18 December 2012</span> –
1276
<a href="https://github.com/PaulUithol/Backbone-relational/compare/0.6.0...0.7.0">diff</a> –
1277
<a href="https://raw.github.com/PaulUithol/Backbone-relational/0.7.0/backbone-relational.js">download</a>
1281
<li>Compatible with Backbone >= 0.9.9</li>
1283
<a href="https://github.com/PaulUithol/Backbone-relational/issues/180"><q>#180</q></a>: no longer allow
1284
multiple instances of RelationalModels with the same type, and the same <q>id</q>.
1290
<span class="date">02 August 2012</span> –
1291
<a href="https://github.com/PaulUithol/Backbone-relational/compare/0.5.0...0.6.0">diff</a> –
1292
<a href="https://raw.github.com/PaulUithol/Backbone-relational/0.6.0/backbone-relational.js">download</a>
1297
<a href="https://github.com/PaulUithol/Backbone-relational/issues/60"><q>#60</q></a>: <q>keySource</q> option
1301
<q>keyDestination</q> option added to relations.
1304
<q>collectionOptions</q> option added to relations.
1307
Added support for super/sub models.
1310
Added <q>Backbone.Store.addModelScope</q>.
1316
<span class="date">17 February 2012</span> –
1317
<a href="https://github.com/PaulUithol/Backbone-relational/compare/0.4.0...0.5.0">diff</a> –
1318
<a href="https://raw.github.com/PaulUithol/Backbone-relational/0.5.0/backbone-relational.js">download</a>
1323
Update nested models properly on <q>Collection.add</q>.
1326
<q>collectionKey</q> options added to relations.
1329
Support new Backbone syntax for <q>set</q> (with separate key, value arguments).
1332
Initialize reverseRelations on definition, instead of on creation of the first model.
1338
<span class="date">23 July 2011</span> –
1339
<a href="https://github.com/PaulUithol/Backbone-relational/compare/37affc3d...0.4.0">diff</a> –
1340
<a href="https://raw.github.com/PaulUithol/Backbone-relational/0.4.0/backbone-relational.js">download</a>
1345
<q>update<key></q> event added
1348
Override <q>Backbone.Collection._add</q> and <q>Backbone.Collection._remove</q> so relations update properly.
1351
Queue <q>change</q> and <q>change<key></q> events, so they won't fire before relations are updated.
1354
Added the <q>Backbone.RelationalModel.updateRelations</q> method.
1360
<span class="date">11 April 2011</span> –
1361
<a href="https://github.com/PaulUithol/Backbone-relational/commit/37affc3d9cbf8b9ae2a1701a3a9e7782cd606a6f#diff-1">commit</a> –
1362
<a href="https://raw.github.com/PaulUithol/Backbone-relational/37affc3d9cbf8b9ae2a1701a3a9e7782cd606a6f/backbone-relational.js">download</a>
1366
The original version of Backbone-relational! This already contained much of the basics: <q>HasOne</q> and <q>HasMany</q>
1367
relations (including <q>reverseRelation</q>), <q>Backbone.RelationalModel</q> and <q>Backbone.Store</q>.
1371
<section id="under-the-hood">
1372
<h2 >Under the Hood</h2>
1373
<h3>The model Store</h3>
1375
Each <strong>Backbone.RelationalModel</strong> registers itself with <strong>Backbone.Relational.Store</strong>
1376
upon creation, and is removed from the <q>store</q> when destroyed. When creating or updating an
1377
attribute that is a key in a relation, removed related objects are notified of their
1378
removal, and new related objects are looked up in the Store.
1381
Backbone-relational only allows the existence of one model instance for each model type <q>id</q>.
1382
This check is there to enforce there will only be one version of a model with a certain id at any given time
1383
(which is also the reason for the existence of Backbone.Relational.Store). This is necessary to enforce
1384
consistency and integrity of relations.
1387
If multiple versions were allowed, inadvertently manipulating or performing a save or destroy
1388
on another version of that model (which is still around on the client, and can for example still be bound
1389
to one or more views in your application, either on purpose or inadvertently) would save it's state to the
1390
server, killing it's relations, and the server response would set the same (incorrect) data on the 'current'
1391
version of the model on the client. By then, you'd be in trouble.
1394
Therefore, Backbone-relational simply does not allow this situation to occur. This is much safer than
1395
putting the burden on the developer to always make sure every older version of a model is completely
1396
decoupled from every other part of your application.
1397
It might be annoying to get an error every now and then, and sometimes inconvenient to have to use the
1398
factory method <q>findOrCreate</q>, but it's much better than subtle bugs that can lead to major data loss
1399
later on in the life cycle of your application.
1401
<h3>Event queuing</h3>
1403
Most of Backbone's default events are queued by Backbone-relational. This can complicate debugging since
1404
it 'breaks' the call stack, but is a necessary part of the abstraction offered by it.
1407
The event queuing kicks in every time (nested) relations need to be updated as the result of calling a
1408
Backbone method that modifies a model's attributes: on creation, and on <q>set</q>, <q>unset</q>, and <q>clear</q>.
1411
The basic problem is that when manipulating relations, you only want the events to fire once ALL relations
1412
have been updated; also those on models one, two, or more relations away. For example, when you have an
1413
event listener on <q>add</q>, you want to be able to use the model you receive as the first argument
1414
and it's relations fully instead of getting raw JS objects:
1417
<pre class="language-javascript"><code class="language-javascript runnable" data-setup="#example-job"><!--
1418
-->var p = new Person( { id: 'p1', name: 'Larry Page' } );
1420
p.on( 'add:jobs', function( job ) {
1421
// Here, you want the correct person and company to be set on job, instead of plain js.
1422
alert( job.get( 'person' ).get( 'name' ) + ' @ ' + job.get( 'company' ).get( 'name' ) );
1425
p.get( 'jobs' ).add( { company: { name: 'Google' }, person: p.id } );
1429
To achieve this, Backbone's events are prevented from firing <i>immediately</i> when <q>add</q>
1430
is called, but are delayed until the all (nested) relations have reached a stable state again. Events are
1431
then fired at the first available opportunity; as soon as the last model updating its relations unblocks
1432
the <q>Backbone.Relational.eventQueue</q>.
1437
<div class="scripts">
1438
<script type="text/javascript" src="test/lib/jquery-1.9.1.js"></script>
1439
<script type="text/javascript" src="test/lib/underscore.js"></script>
1440
<script type="text/javascript" src="test/lib/backbone.js"></script>
1441
<script type="text/javascript" src="backbone-relational.js"></script>
1442
<script type="text/javascript" src="static/js/prism.js"></script>
1443
<script type="text/javascript">
1444
// Set up the "play" buttons for each runnable code example.
1446
// Run a piece of example code. If an element has a `data-setup` attribute,
1447
// the element referred to gets executed first.
1448
function run( codeElem, silenceAlerts ) {
1449
codeElem = $( codeElem );
1451
var setup = codeElem.data( 'setup' );
1457
if ( silenceAlerts === true ) {
1458
var _alert = window.alert;
1459
window.alert = $.noop;
1462
// Grab the code, and eval it. Nasty twist: remove all `var` statement at the start of a line;
1463
// this will make all eval'ed vars global, so vars from scripts used as setup can be used
1464
// by those that need 'em.
1465
var code = $( codeElem ).text();
1466
code = code.replace( /(^|\n)(var )/g, '\n' );
1467
//console.log( 'Executing:\n %s', code );
1470
if ( silenceAlerts === true ) {
1471
window.alert = _alert;
1475
$( '.runnable' ).each( function() {
1476
var code = $( this );
1478
// Add a `runnable` button to each runnable piece of code
1479
var button = '<div class="run" title="Run"><a class="button orange">►</a></div>';
1480
$( button ).insertBefore( code ).bind( 'click', function() {
1481
Backbone.Relational.store.reset();