server/php/basic/public_html/static/lib/backbone-relational/backbone-relational.js
author ymh <ymh.work@gmail.com>
Fri, 22 May 2015 17:48:14 +0200
changeset 442 adb907bba956
child 498 08d121184a38
permissions -rw-r--r--
add server php example
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
442
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
     1
/* vim: set tabstop=4 softtabstop=4 shiftwidth=4 noexpandtab: */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
     2
/**
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
     3
 * Backbone-relational.js 0.9.0
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
     4
 * (c) 2011-2014 Paul Uithol and contributors (https://github.com/PaulUithol/Backbone-relational/graphs/contributors)
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
     5
 *
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
     6
 * Backbone-relational may be freely distributed under the MIT license; see the accompanying LICENSE.txt.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
     7
 * For details and documentation: https://github.com/PaulUithol/Backbone-relational.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
     8
 * Depends on Backbone (and thus on Underscore as well): https://github.com/documentcloud/backbone.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
     9
 *
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    10
 * Example:
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    11
 *
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    12
	Zoo = Backbone.RelationalModel.extend({
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    13
		relations: [ {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    14
			type: Backbone.HasMany,
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    15
			key: 'animals',
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    16
			relatedModel: 'Animal',
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    17
			reverseRelation: {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    18
				key: 'livesIn',
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    19
				includeInJSON: 'id'
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    20
				// 'relatedModel' is automatically set to 'Zoo'; the 'relationType' to 'HasOne'.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    21
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    22
		} ],
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    23
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    24
		toString: function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    25
			return this.get( 'name' );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    26
		}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    27
	});
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    28
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    29
	Animal = Backbone.RelationalModel.extend({
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    30
		toString: function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    31
			return this.get( 'species' );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    32
		}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    33
	});
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    34
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    35
	// Creating the zoo will give it a collection with one animal in it: the monkey.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    36
	// The animal created after that has a relation `livesIn` that points to the zoo it's currently associated with.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    37
	// If you instantiate (or fetch) the zebra later, it will automatically be added.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    38
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    39
	var zoo = new Zoo({
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    40
		name: 'Artis',
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    41
		animals: [ { id: 'monkey-1', species: 'Chimp' }, 'lion-1', 'zebra-1' ]
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    42
	});
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    43
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    44
	var lion = new Animal( { id: 'lion-1', species: 'Lion' } ),
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    45
		monkey = zoo.get( 'animals' ).first(),
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    46
		sameZoo = lion.get( 'livesIn' );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    47
 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    48
( function( root, factory ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    49
	// Set up Backbone-relational for the environment. Start with AMD.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    50
	if ( typeof define === 'function' && define.amd ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    51
		define( [ 'exports', 'backbone', 'underscore' ], factory );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    52
	}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    53
	// Next for Node.js or CommonJS.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    54
	else if ( typeof exports !== 'undefined' ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    55
		factory( exports, require( 'backbone' ), require( 'underscore' ) );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    56
	}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    57
	// Finally, as a browser global. Use `root` here as it references `window`.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    58
	else {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    59
		factory( root, root.Backbone, root._ );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    60
	}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    61
}( this, function( exports, Backbone, _ ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    62
	"use strict";
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    63
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    64
	Backbone.Relational = {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    65
		showWarnings: true
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    66
	};
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    67
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    68
	/**
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    69
	 * Semaphore mixin; can be used as both binary and counting.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    70
	 **/
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    71
	Backbone.Semaphore = {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    72
		_permitsAvailable: null,
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    73
		_permitsUsed: 0,
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    74
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    75
		acquire: function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    76
			if ( this._permitsAvailable && this._permitsUsed >= this._permitsAvailable ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    77
				throw new Error( 'Max permits acquired' );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    78
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    79
			else {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    80
				this._permitsUsed++;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    81
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    82
		},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    83
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    84
		release: function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    85
			if ( this._permitsUsed === 0 ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    86
				throw new Error( 'All permits released' );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    87
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    88
			else {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    89
				this._permitsUsed--;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    90
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    91
		},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    92
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    93
		isLocked: function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    94
			return this._permitsUsed > 0;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    95
		},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    96
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    97
		setAvailablePermits: function( amount ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    98
			if ( this._permitsUsed > amount ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    99
				throw new Error( 'Available permits cannot be less than used permits' );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   100
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   101
			this._permitsAvailable = amount;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   102
		}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   103
	};
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   104
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   105
	/**
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   106
	 * A BlockingQueue that accumulates items while blocked (via 'block'),
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   107
	 * and processes them when unblocked (via 'unblock').
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   108
	 * Process can also be called manually (via 'process').
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   109
	 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   110
	Backbone.BlockingQueue = function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   111
		this._queue = [];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   112
	};
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   113
	_.extend( Backbone.BlockingQueue.prototype, Backbone.Semaphore, {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   114
		_queue: null,
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   115
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   116
		add: function( func ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   117
			if ( this.isBlocked() ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   118
				this._queue.push( func );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   119
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   120
			else {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   121
				func();
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   122
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   123
		},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   124
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   125
		// Some of the queued events may trigger other blocking events. By
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   126
		// copying the queue here it allows queued events to process closer to
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   127
		// the natural order.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   128
		//
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   129
		// queue events [ 'A', 'B', 'C' ]
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   130
		// A handler of 'B' triggers 'D' and 'E'
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   131
		// By copying `this._queue` this executes:
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   132
		// [ 'A', 'B', 'D', 'E', 'C' ]
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   133
		// The same order the would have executed if they didn't have to be
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   134
		// delayed and queued.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   135
		process: function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   136
			var queue = this._queue;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   137
			this._queue = [];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   138
			while ( queue && queue.length ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   139
				queue.shift()();
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   140
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   141
		},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   142
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   143
		block: function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   144
			this.acquire();
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   145
		},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   146
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   147
		unblock: function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   148
			this.release();
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   149
			if ( !this.isBlocked() ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   150
				this.process();
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   151
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   152
		},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   153
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   154
		isBlocked: function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   155
			return this.isLocked();
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   156
		}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   157
	});
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   158
	/**
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   159
	 * Global event queue. Accumulates external events ('add:<key>', 'remove:<key>' and 'change:<key>')
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   160
	 * until the top-level object is fully initialized (see 'Backbone.RelationalModel').
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   161
	 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   162
	Backbone.Relational.eventQueue = new Backbone.BlockingQueue();
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   163
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   164
	/**
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   165
	 * Backbone.Store keeps track of all created (and destruction of) Backbone.RelationalModel.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   166
	 * Handles lookup for relations.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   167
	 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   168
	Backbone.Store = function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   169
		this._collections = [];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   170
		this._reverseRelations = [];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   171
		this._orphanRelations = [];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   172
		this._subModels = [];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   173
		this._modelScopes = [ exports ];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   174
	};
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   175
	_.extend( Backbone.Store.prototype, Backbone.Events, {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   176
		/**
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   177
		 * Create a new `Relation`.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   178
		 * @param {Backbone.RelationalModel} [model]
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   179
		 * @param {Object} relation
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   180
		 * @param {Object} [options]
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   181
		 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   182
		initializeRelation: function( model, relation, options ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   183
			var type = !_.isString( relation.type ) ? relation.type : Backbone[ relation.type ] || this.getObjectByName( relation.type );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   184
			if ( type && type.prototype instanceof Backbone.Relation ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   185
				var rel = new type( model, relation, options ); // Also pushes the new Relation into `model._relations`
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   186
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   187
			else {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   188
				Backbone.Relational.showWarnings && typeof console !== 'undefined' && console.warn( 'Relation=%o; missing or invalid relation type!', relation );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   189
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   190
		},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   191
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   192
		/**
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   193
		 * Add a scope for `getObjectByName` to look for model types by name.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   194
		 * @param {Object} scope
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   195
		 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   196
		addModelScope: function( scope ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   197
			this._modelScopes.push( scope );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   198
		},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   199
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   200
		/**
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   201
		 * Remove a scope.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   202
		 * @param {Object} scope
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   203
		 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   204
		removeModelScope: function( scope ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   205
			this._modelScopes = _.without( this._modelScopes, scope );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   206
		},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   207
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   208
		/**
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   209
		 * Add a set of subModelTypes to the store, that can be used to resolve the '_superModel'
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   210
		 * for a model later in 'setupSuperModel'.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   211
		 *
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   212
		 * @param {Backbone.RelationalModel} subModelTypes
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   213
		 * @param {Backbone.RelationalModel} superModelType
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   214
		 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   215
		addSubModels: function( subModelTypes, superModelType ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   216
			this._subModels.push({
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   217
				'superModelType': superModelType,
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   218
				'subModels': subModelTypes
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   219
			});
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   220
		},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   221
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   222
		/**
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   223
		 * Check if the given modelType is registered as another model's subModel. If so, add it to the super model's
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   224
		 * '_subModels', and set the modelType's '_superModel', '_subModelTypeName', and '_subModelTypeAttribute'.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   225
		 *
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   226
		 * @param {Backbone.RelationalModel} modelType
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   227
		 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   228
		setupSuperModel: function( modelType ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   229
			_.find( this._subModels, function( subModelDef ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   230
				return _.filter( subModelDef.subModels || [], function( subModelTypeName, typeValue ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   231
					var subModelType = this.getObjectByName( subModelTypeName );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   232
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   233
					if ( modelType === subModelType ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   234
						// Set 'modelType' as a child of the found superModel
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   235
						subModelDef.superModelType._subModels[ typeValue ] = modelType;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   236
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   237
						// Set '_superModel', '_subModelTypeValue', and '_subModelTypeAttribute' on 'modelType'.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   238
						modelType._superModel = subModelDef.superModelType;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   239
						modelType._subModelTypeValue = typeValue;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   240
						modelType._subModelTypeAttribute = subModelDef.superModelType.prototype.subModelTypeAttribute;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   241
						return true;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   242
					}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   243
				}, this ).length;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   244
			}, this );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   245
		},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   246
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   247
		/**
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   248
		 * Add a reverse relation. Is added to the 'relations' property on model's prototype, and to
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   249
		 * existing instances of 'model' in the store as well.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   250
		 * @param {Object} relation
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   251
		 * @param {Backbone.RelationalModel} relation.model
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   252
		 * @param {String} relation.type
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   253
		 * @param {String} relation.key
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   254
		 * @param {String|Object} relation.relatedModel
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   255
		 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   256
		addReverseRelation: function( relation ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   257
			var exists = _.any( this._reverseRelations, function( rel ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   258
				return _.all( relation || [], function( val, key ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   259
					return val === rel[ key ];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   260
				});
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   261
			});
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   262
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   263
			if ( !exists && relation.model && relation.type ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   264
				this._reverseRelations.push( relation );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   265
				this._addRelation( relation.model, relation );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   266
				this.retroFitRelation( relation );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   267
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   268
		},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   269
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   270
		/**
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   271
		 * Deposit a `relation` for which the `relatedModel` can't be resolved at the moment.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   272
		 *
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   273
		 * @param {Object} relation
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   274
		 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   275
		addOrphanRelation: function( relation ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   276
			var exists = _.any( this._orphanRelations, function( rel ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   277
				return _.all( relation || [], function( val, key ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   278
					return val === rel[ key ];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   279
				});
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   280
			});
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   281
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   282
			if ( !exists && relation.model && relation.type ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   283
				this._orphanRelations.push( relation );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   284
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   285
		},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   286
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   287
		/**
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   288
		 * Try to initialize any `_orphanRelation`s
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   289
		 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   290
		processOrphanRelations: function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   291
			// Make sure to operate on a copy since we're removing while iterating
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   292
			_.each( this._orphanRelations.slice( 0 ), function( rel ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   293
				var relatedModel = Backbone.Relational.store.getObjectByName( rel.relatedModel );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   294
				if ( relatedModel ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   295
					this.initializeRelation( null, rel );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   296
					this._orphanRelations = _.without( this._orphanRelations, rel );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   297
				}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   298
			}, this );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   299
		},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   300
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   301
		/**
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   302
		 *
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   303
		 * @param {Backbone.RelationalModel.constructor} type
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   304
		 * @param {Object} relation
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   305
		 * @private
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   306
		 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   307
		_addRelation: function( type, relation ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   308
			if ( !type.prototype.relations ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   309
				type.prototype.relations = [];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   310
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   311
			type.prototype.relations.push( relation );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   312
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   313
			_.each( type._subModels || [], function( subModel ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   314
				this._addRelation( subModel, relation );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   315
			}, this );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   316
		},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   317
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   318
		/**
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   319
		 * Add a 'relation' to all existing instances of 'relation.model' in the store
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   320
		 * @param {Object} relation
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   321
		 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   322
		retroFitRelation: function( relation ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   323
			var coll = this.getCollection( relation.model, false );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   324
			coll && coll.each( function( model ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   325
				if ( !( model instanceof relation.model ) ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   326
					return;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   327
				}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   328
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   329
				var rel = new relation.type( model, relation );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   330
			}, this );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   331
		},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   332
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   333
		/**
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   334
		 * Find the Store's collection for a certain type of model.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   335
		 * @param {Backbone.RelationalModel} type
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   336
		 * @param {Boolean} [create=true] Should a collection be created if none is found?
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   337
		 * @return {Backbone.Collection} A collection if found (or applicable for 'model'), or null
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   338
		 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   339
		getCollection: function( type, create ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   340
			if ( type instanceof Backbone.RelationalModel ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   341
				type = type.constructor;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   342
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   343
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   344
			var rootModel = type;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   345
			while ( rootModel._superModel ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   346
				rootModel = rootModel._superModel;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   347
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   348
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   349
			var coll = _.find( this._collections, function( item ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   350
				return item.model === rootModel;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   351
			});
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   352
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   353
			if ( !coll && create !== false ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   354
				coll = this._createCollection( rootModel );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   355
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   356
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   357
			return coll;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   358
		},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   359
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   360
		/**
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   361
		 * Find a model type on one of the modelScopes by name. Names are split on dots.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   362
		 * @param {String} name
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   363
		 * @return {Object}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   364
		 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   365
		getObjectByName: function( name ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   366
			var parts = name.split( '.' ),
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   367
				type = null;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   368
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   369
			_.find( this._modelScopes, function( scope ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   370
				type = _.reduce( parts || [], function( memo, val ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   371
					return memo ? memo[ val ] : undefined;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   372
				}, scope );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   373
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   374
				if ( type && type !== scope ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   375
					return true;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   376
				}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   377
			}, this );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   378
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   379
			return type;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   380
		},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   381
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   382
		_createCollection: function( type ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   383
			var coll;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   384
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   385
			// If 'type' is an instance, take its constructor
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   386
			if ( type instanceof Backbone.RelationalModel ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   387
				type = type.constructor;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   388
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   389
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   390
			// Type should inherit from Backbone.RelationalModel.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   391
			if ( type.prototype instanceof Backbone.RelationalModel ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   392
				coll = new Backbone.Collection();
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   393
				coll.model = type;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   394
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   395
				this._collections.push( coll );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   396
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   397
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   398
			return coll;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   399
		},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   400
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   401
		/**
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   402
		 * Find the attribute that is to be used as the `id` on a given object
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   403
		 * @param type
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   404
		 * @param {String|Number|Object|Backbone.RelationalModel} item
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   405
		 * @return {String|Number}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   406
		 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   407
		resolveIdForItem: function( type, item ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   408
			var id = _.isString( item ) || _.isNumber( item ) ? item : null;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   409
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   410
			if ( id === null ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   411
				if ( item instanceof Backbone.RelationalModel ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   412
					id = item.id;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   413
				}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   414
				else if ( _.isObject( item ) ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   415
					id = item[ type.prototype.idAttribute ];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   416
				}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   417
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   418
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   419
			// Make all falsy values `null` (except for 0, which could be an id.. see '/issues/179')
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   420
			if ( !id && id !== 0 ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   421
				id = null;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   422
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   423
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   424
			return id;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   425
		},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   426
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   427
		/**
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   428
		 * Find a specific model of a certain `type` in the store
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   429
		 * @param type
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   430
		 * @param {String|Number|Object|Backbone.RelationalModel} item
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   431
		 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   432
		find: function( type, item ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   433
			var id = this.resolveIdForItem( type, item ),
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   434
				coll = this.getCollection( type );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   435
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   436
			// Because the found object could be of any of the type's superModel
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   437
			// types, only return it if it's actually of the type asked for.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   438
			if ( coll ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   439
				var obj = coll.get( id );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   440
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   441
				if ( obj instanceof type ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   442
					return obj;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   443
				}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   444
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   445
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   446
			return null;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   447
		},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   448
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   449
		/**
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   450
		 * Add a 'model' to its appropriate collection. Retain the original contents of 'model.collection'.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   451
		 * @param {Backbone.RelationalModel} model
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   452
		 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   453
		register: function( model ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   454
			var coll = this.getCollection( model );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   455
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   456
			if ( coll ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   457
				var modelColl = model.collection;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   458
				coll.add( model );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   459
				model.collection = modelColl;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   460
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   461
		},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   462
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   463
		/**
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   464
		 * Check if the given model may use the given `id`
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   465
		 * @param model
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   466
		 * @param [id]
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   467
		 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   468
		checkId: function( model, id ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   469
			var coll = this.getCollection( model ),
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   470
				duplicate = coll && coll.get( id );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   471
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   472
			if ( duplicate && model !== duplicate ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   473
				if ( Backbone.Relational.showWarnings && typeof console !== 'undefined' ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   474
					console.warn( 'Duplicate id! Old RelationalModel=%o, new RelationalModel=%o', duplicate, model );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   475
				}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   476
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   477
				throw new Error( "Cannot instantiate more than one Backbone.RelationalModel with the same id per type!" );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   478
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   479
		},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   480
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   481
		/**
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   482
		 * Explicitly update a model's id in its store collection
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   483
		 * @param {Backbone.RelationalModel} model
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   484
		 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   485
		update: function( model ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   486
			var coll = this.getCollection( model );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   487
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   488
			// Register a model if it isn't yet (which happens if it was created without an id).
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   489
			if ( !coll.contains( model ) ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   490
				this.register( model );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   491
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   492
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   493
			// This triggers updating the lookup indices kept in a collection
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   494
			coll._onModelEvent( 'change:' + model.idAttribute, model, coll );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   495
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   496
			// Trigger an event on model so related models (having the model's new id in their keyContents) can add it.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   497
			model.trigger( 'relational:change:id', model, coll );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   498
		},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   499
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   500
		/**
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   501
		 * Unregister from the store: a specific model, a collection, or a model type.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   502
		 * @param {Backbone.RelationalModel|Backbone.RelationalModel.constructor|Backbone.Collection} type
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   503
		 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   504
		unregister: function( type ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   505
			var coll,
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   506
				models;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   507
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   508
			if ( type instanceof Backbone.Model ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   509
				coll = this.getCollection( type );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   510
				models = [ type ];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   511
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   512
			else if ( type instanceof Backbone.Collection ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   513
				coll = this.getCollection( type.model );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   514
				models = _.clone( type.models );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   515
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   516
			else {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   517
				coll = this.getCollection( type );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   518
				models = _.clone( coll.models );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   519
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   520
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   521
			_.each( models, function( model ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   522
				this.stopListening( model );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   523
				_.invoke( model.getRelations(), 'stopListening' );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   524
			}, this );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   525
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   526
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   527
			// If we've unregistered an entire store collection, reset the collection (which is much faster).
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   528
			// Otherwise, remove each model one by one.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   529
			if ( _.contains( this._collections, type ) ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   530
				coll.reset( [] );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   531
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   532
			else {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   533
				_.each( models, function( model ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   534
					if ( coll.get( model ) ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   535
						coll.remove( model );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   536
					}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   537
					else {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   538
						coll.trigger( 'relational:remove', model, coll );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   539
					}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   540
				}, this );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   541
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   542
		},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   543
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   544
		/**
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   545
		 * Reset the `store` to it's original state. The `reverseRelations` are kept though, since attempting to
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   546
		 * re-initialize these on models would lead to a large amount of warnings.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   547
		 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   548
		reset: function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   549
			this.stopListening();
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   550
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   551
			// Unregister each collection to remove event listeners
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   552
			_.each( this._collections, function( coll ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   553
				this.unregister( coll );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   554
			}, this );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   555
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   556
			this._collections = [];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   557
			this._subModels = [];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   558
			this._modelScopes = [ exports ];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   559
		}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   560
	});
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   561
	Backbone.Relational.store = new Backbone.Store();
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   562
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   563
	/**
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   564
	 * The main Relation class, from which 'HasOne' and 'HasMany' inherit. Internally, 'relational:<key>' events
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   565
	 * are used to regulate addition and removal of models from relations.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   566
	 *
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   567
	 * @param {Backbone.RelationalModel} [instance] Model that this relation is created for. If no model is supplied,
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   568
	 *      Relation just tries to instantiate it's `reverseRelation` if specified, and bails out after that.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   569
	 * @param {Object} options
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   570
	 * @param {string} options.key
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   571
	 * @param {Backbone.RelationalModel.constructor} options.relatedModel
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   572
	 * @param {Boolean|String} [options.includeInJSON=true] Serialize the given attribute for related model(s)' in toJSON, or just their ids.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   573
	 * @param {Boolean} [options.createModels=true] Create objects from the contents of keys if the object is not found in Backbone.store.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   574
	 * @param {Object} [options.reverseRelation] Specify a bi-directional relation. If provided, Relation will reciprocate
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   575
	 *    the relation to the 'relatedModel'. Required and optional properties match 'options', except that it also needs
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   576
	 *    {Backbone.Relation|String} type ('HasOne' or 'HasMany').
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   577
	 * @param {Object} opts
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   578
	 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   579
	Backbone.Relation = function( instance, options, opts ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   580
		this.instance = instance;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   581
		// Make sure 'options' is sane, and fill with defaults from subclasses and this object's prototype
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   582
		options = _.isObject( options ) ? options : {};
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   583
		this.reverseRelation = _.defaults( options.reverseRelation || {}, this.options.reverseRelation );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   584
		this.options = _.defaults( options, this.options, Backbone.Relation.prototype.options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   585
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   586
		this.reverseRelation.type = !_.isString( this.reverseRelation.type ) ? this.reverseRelation.type :
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   587
			Backbone[ this.reverseRelation.type ] || Backbone.Relational.store.getObjectByName( this.reverseRelation.type );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   588
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   589
		this.key = this.options.key;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   590
		this.keySource = this.options.keySource || this.key;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   591
		this.keyDestination = this.options.keyDestination || this.keySource || this.key;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   592
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   593
		this.model = this.options.model || this.instance.constructor;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   594
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   595
		this.relatedModel = this.options.relatedModel;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   596
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   597
		// No 'relatedModel' is interpreted as self-referential
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   598
		if ( _.isUndefined( this.relatedModel ) ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   599
			this.relatedModel = this.model;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   600
		}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   601
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   602
		// Otherwise, try to resolve the given value to an object
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   603
		if ( _.isFunction( this.relatedModel ) && !( this.relatedModel.prototype instanceof Backbone.RelationalModel ) ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   604
			this.relatedModel = _.result( this, 'relatedModel' );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   605
		}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   606
		if ( _.isString( this.relatedModel ) ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   607
			this.relatedModel = Backbone.Relational.store.getObjectByName( this.relatedModel );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   608
		}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   609
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   610
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   611
		if ( !this.checkPreconditions() ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   612
			return;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   613
		}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   614
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   615
		// Add the reverse relation on 'relatedModel' to the store's reverseRelations
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   616
		if ( !this.options.isAutoRelation && this.reverseRelation.type && this.reverseRelation.key ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   617
			Backbone.Relational.store.addReverseRelation( _.defaults( {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   618
					isAutoRelation: true,
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   619
					model: this.relatedModel,
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   620
					relatedModel: this.model,
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   621
					reverseRelation: this.options // current relation is the 'reverseRelation' for its own reverseRelation
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   622
				},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   623
				this.reverseRelation // Take further properties from this.reverseRelation (type, key, etc.)
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   624
			) );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   625
		}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   626
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   627
		if ( instance ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   628
			var contentKey = this.keySource;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   629
			if ( contentKey !== this.key && _.isObject( this.instance.get( this.key ) ) ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   630
				contentKey = this.key;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   631
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   632
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   633
			this.setKeyContents( this.instance.get( contentKey ) );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   634
			this.relatedCollection = Backbone.Relational.store.getCollection( this.relatedModel );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   635
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   636
			// Explicitly clear 'keySource', to prevent a leaky abstraction if 'keySource' differs from 'key'.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   637
			if ( this.keySource !== this.key ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   638
				delete this.instance.attributes[ this.keySource ];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   639
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   640
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   641
			// Add this Relation to instance._relations
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   642
			this.instance._relations[ this.key ] = this;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   643
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   644
			this.initialize( opts );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   645
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   646
			if ( this.options.autoFetch ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   647
				this.instance.getAsync( this.key, _.isObject( this.options.autoFetch ) ? this.options.autoFetch : {} );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   648
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   649
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   650
			// When 'relatedModel' are created or destroyed, check if it affects this relation.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   651
			this.listenTo( this.instance, 'destroy', this.destroy )
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   652
				.listenTo( this.relatedCollection, 'relational:add relational:change:id', this.tryAddRelated )
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   653
				.listenTo( this.relatedCollection, 'relational:remove', this.removeRelated );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   654
		}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   655
	};
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   656
	// Fix inheritance :\
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   657
	Backbone.Relation.extend = Backbone.Model.extend;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   658
	// Set up all inheritable **Backbone.Relation** properties and methods.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   659
	_.extend( Backbone.Relation.prototype, Backbone.Events, Backbone.Semaphore, {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   660
		options: {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   661
			createModels: true,
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   662
			includeInJSON: true,
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   663
			isAutoRelation: false,
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   664
			autoFetch: false,
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   665
			parse: false
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   666
		},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   667
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   668
		instance: null,
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   669
		key: null,
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   670
		keyContents: null,
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   671
		relatedModel: null,
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   672
		relatedCollection: null,
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   673
		reverseRelation: null,
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   674
		related: null,
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   675
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   676
		/**
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   677
		 * Check several pre-conditions.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   678
		 * @return {Boolean} True if pre-conditions are satisfied, false if they're not.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   679
		 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   680
		checkPreconditions: function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   681
			var i = this.instance,
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   682
				k = this.key,
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   683
				m = this.model,
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   684
				rm = this.relatedModel,
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   685
				warn = Backbone.Relational.showWarnings && typeof console !== 'undefined';
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   686
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   687
			if ( !m || !k || !rm ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   688
				warn && console.warn( 'Relation=%o: missing model, key or relatedModel (%o, %o, %o).', this, m, k, rm );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   689
				return false;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   690
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   691
			// Check if the type in 'model' inherits from Backbone.RelationalModel
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   692
			if ( !( m.prototype instanceof Backbone.RelationalModel ) ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   693
				warn && console.warn( 'Relation=%o: model does not inherit from Backbone.RelationalModel (%o).', this, i );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   694
				return false;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   695
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   696
			// Check if the type in 'relatedModel' inherits from Backbone.RelationalModel
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   697
			if ( !( rm.prototype instanceof Backbone.RelationalModel ) ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   698
				warn && console.warn( 'Relation=%o: relatedModel does not inherit from Backbone.RelationalModel (%o).', this, rm );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   699
				return false;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   700
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   701
			// Check if this is not a HasMany, and the reverse relation is HasMany as well
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   702
			if ( this instanceof Backbone.HasMany && this.reverseRelation.type === Backbone.HasMany ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   703
				warn && console.warn( 'Relation=%o: relation is a HasMany, and the reverseRelation is HasMany as well.', this );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   704
				return false;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   705
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   706
			// Check if we're not attempting to create a relationship on a `key` that's already used.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   707
			if ( i && _.keys( i._relations ).length ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   708
				var existing = _.find( i._relations, function( rel ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   709
					return rel.key === k;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   710
				}, this );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   711
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   712
				if ( existing ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   713
					warn && console.warn( 'Cannot create relation=%o on %o for model=%o: already taken by relation=%o.',
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   714
						this, k, i, existing );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   715
					return false;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   716
				}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   717
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   718
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   719
			return true;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   720
		},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   721
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   722
		/**
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   723
		 * Set the related model(s) for this relation
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   724
		 * @param {Backbone.Model|Backbone.Collection} related
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   725
		 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   726
		setRelated: function( related ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   727
			this.related = related;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   728
			this.instance.attributes[ this.key ] = related;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   729
		},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   730
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   731
		/**
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   732
		 * Determine if a relation (on a different RelationalModel) is the reverse
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   733
		 * relation of the current one.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   734
		 * @param {Backbone.Relation} relation
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   735
		 * @return {Boolean}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   736
		 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   737
		_isReverseRelation: function( relation ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   738
			return relation.instance instanceof this.relatedModel && this.reverseRelation.key === relation.key &&
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   739
				this.key === relation.reverseRelation.key;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   740
		},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   741
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   742
		/**
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   743
		 * Get the reverse relations (pointing back to 'this.key' on 'this.instance') for the currently related model(s).
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   744
		 * @param {Backbone.RelationalModel} [model] Get the reverse relations for a specific model.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   745
		 *    If not specified, 'this.related' is used.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   746
		 * @return {Backbone.Relation[]}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   747
		 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   748
		getReverseRelations: function( model ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   749
			var reverseRelations = [];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   750
			// Iterate over 'model', 'this.related.models' (if this.related is a Backbone.Collection), or wrap 'this.related' in an array.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   751
			var models = !_.isUndefined( model ) ? [ model ] : this.related && ( this.related.models || [ this.related ] ),
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   752
				relations = null,
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   753
				relation = null;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   754
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   755
			for( var i = 0; i < ( models || [] ).length; i++ ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   756
				relations = models[ i ].getRelations() || [];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   757
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   758
				for( var j = 0; j < relations.length; j++ ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   759
					relation = relations[ j ];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   760
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   761
					if ( this._isReverseRelation( relation ) ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   762
						reverseRelations.push( relation );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   763
					}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   764
				}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   765
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   766
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   767
			return reverseRelations;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   768
		},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   769
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   770
		/**
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   771
		 * When `this.instance` is destroyed, cleanup our relations.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   772
		 * Get reverse relation, call removeRelated on each.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   773
		 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   774
		destroy: function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   775
			this.stopListening();
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   776
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   777
			if ( this instanceof Backbone.HasOne ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   778
				this.setRelated( null );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   779
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   780
			else if ( this instanceof Backbone.HasMany ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   781
				this.setRelated( this._prepareCollection() );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   782
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   783
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   784
			_.each( this.getReverseRelations(), function( relation ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   785
				relation.removeRelated( this.instance );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   786
			}, this );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   787
		}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   788
	});
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   789
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   790
	Backbone.HasOne = Backbone.Relation.extend({
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   791
		options: {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   792
			reverseRelation: { type: 'HasMany' }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   793
		},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   794
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   795
		initialize: function( opts ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   796
			this.listenTo( this.instance, 'relational:change:' + this.key, this.onChange );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   797
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   798
			var related = this.findRelated( opts );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   799
			this.setRelated( related );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   800
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   801
			// Notify new 'related' object of the new relation.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   802
			_.each( this.getReverseRelations(), function( relation ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   803
				relation.addRelated( this.instance, opts );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   804
			}, this );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   805
		},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   806
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   807
		/**
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   808
		 * Find related Models.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   809
		 * @param {Object} [options]
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   810
		 * @return {Backbone.Model}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   811
		 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   812
		findRelated: function( options ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   813
			var related = null;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   814
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   815
			options = _.defaults( { parse: this.options.parse }, options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   816
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   817
			if ( this.keyContents instanceof this.relatedModel ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   818
				related = this.keyContents;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   819
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   820
			else if ( this.keyContents || this.keyContents === 0 ) { // since 0 can be a valid `id` as well
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   821
				var opts = _.defaults( { create: this.options.createModels }, options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   822
				related = this.relatedModel.findOrCreate( this.keyContents, opts );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   823
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   824
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   825
			// Nullify `keyId` if we have a related model; in case it was already part of the relation
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   826
			if ( related ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   827
				this.keyId = null;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   828
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   829
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   830
			return related;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   831
		},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   832
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   833
		/**
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   834
		 * Normalize and reduce `keyContents` to an `id`, for easier comparison
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   835
		 * @param {String|Number|Backbone.Model} keyContents
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   836
		 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   837
		setKeyContents: function( keyContents ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   838
			this.keyContents = keyContents;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   839
			this.keyId = Backbone.Relational.store.resolveIdForItem( this.relatedModel, this.keyContents );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   840
		},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   841
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   842
		/**
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   843
		 * Event handler for `change:<key>`.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   844
		 * If the key is changed, notify old & new reverse relations and initialize the new relation.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   845
		 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   846
		onChange: function( model, attr, options ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   847
			// Don't accept recursive calls to onChange (like onChange->findRelated->findOrCreate->initializeRelations->addRelated->onChange)
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   848
			if ( this.isLocked() ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   849
				return;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   850
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   851
			this.acquire();
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   852
			options = options ? _.clone( options ) : {};
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   853
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   854
			// 'options.__related' is set by 'addRelated'/'removeRelated'. If it is set, the change
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   855
			// is the result of a call from a relation. If it's not, the change is the result of
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   856
			// a 'set' call on this.instance.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   857
			var changed = _.isUndefined( options.__related ),
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   858
				oldRelated = changed ? this.related : options.__related;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   859
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   860
			if ( changed ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   861
				this.setKeyContents( attr );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   862
				var related = this.findRelated( options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   863
				this.setRelated( related );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   864
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   865
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   866
			// Notify old 'related' object of the terminated relation
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   867
			if ( oldRelated && this.related !== oldRelated ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   868
				_.each( this.getReverseRelations( oldRelated ), function( relation ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   869
					relation.removeRelated( this.instance, null, options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   870
				}, this );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   871
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   872
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   873
			// Notify new 'related' object of the new relation. Note we do re-apply even if this.related is oldRelated;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   874
			// that can be necessary for bi-directional relations if 'this.instance' was created after 'this.related'.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   875
			// In that case, 'this.instance' will already know 'this.related', but the reverse might not exist yet.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   876
			_.each( this.getReverseRelations(), function( relation ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   877
				relation.addRelated( this.instance, options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   878
			}, this );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   879
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   880
			// Fire the 'change:<key>' event if 'related' was updated
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   881
			if ( !options.silent && this.related !== oldRelated ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   882
				var dit = this;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   883
				this.changed = true;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   884
				Backbone.Relational.eventQueue.add( function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   885
					dit.instance.trigger( 'change:' + dit.key, dit.instance, dit.related, options, true );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   886
					dit.changed = false;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   887
				});
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   888
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   889
			this.release();
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   890
		},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   891
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   892
		/**
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   893
		 * If a new 'this.relatedModel' appears in the 'store', try to match it to the last set 'keyContents'
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   894
		 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   895
		tryAddRelated: function( model, coll, options ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   896
			if ( ( this.keyId || this.keyId === 0 ) && model.id === this.keyId ) { // since 0 can be a valid `id` as well
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   897
				this.addRelated( model, options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   898
				this.keyId = null;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   899
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   900
		},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   901
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   902
		addRelated: function( model, options ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   903
			// Allow 'model' to set up its relations before proceeding.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   904
			// (which can result in a call to 'addRelated' from a relation of 'model')
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   905
			var dit = this;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   906
			model.queue( function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   907
				if ( model !== dit.related ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   908
					var oldRelated = dit.related || null;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   909
					dit.setRelated( model );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   910
					dit.onChange( dit.instance, model, _.defaults( { __related: oldRelated }, options ) );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   911
				}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   912
			});
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   913
		},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   914
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   915
		removeRelated: function( model, coll, options ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   916
			if ( !this.related ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   917
				return;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   918
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   919
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   920
			if ( model === this.related ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   921
				var oldRelated = this.related || null;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   922
				this.setRelated( null );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   923
				this.onChange( this.instance, model, _.defaults( { __related: oldRelated }, options ) );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   924
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   925
		}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   926
	});
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   927
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   928
	Backbone.HasMany = Backbone.Relation.extend({
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   929
		collectionType: null,
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   930
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   931
		options: {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   932
			reverseRelation: { type: 'HasOne' },
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   933
			collectionType: Backbone.Collection,
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   934
			collectionKey: true,
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   935
			collectionOptions: {}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   936
		},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   937
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   938
		initialize: function( opts ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   939
			this.listenTo( this.instance, 'relational:change:' + this.key, this.onChange );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   940
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   941
			// Handle a custom 'collectionType'
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   942
			this.collectionType = this.options.collectionType;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   943
			if ( _.isFunction( this.collectionType ) && this.collectionType !== Backbone.Collection && !( this.collectionType.prototype instanceof Backbone.Collection ) ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   944
				this.collectionType = _.result( this, 'collectionType' );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   945
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   946
			if ( _.isString( this.collectionType ) ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   947
				this.collectionType = Backbone.Relational.store.getObjectByName( this.collectionType );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   948
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   949
			if ( this.collectionType !== Backbone.Collection && !( this.collectionType.prototype instanceof Backbone.Collection ) ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   950
				throw new Error( '`collectionType` must inherit from Backbone.Collection' );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   951
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   952
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   953
			var related = this.findRelated( opts );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   954
			this.setRelated( related );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   955
		},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   956
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   957
		/**
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   958
		 * Bind events and setup collectionKeys for a collection that is to be used as the backing store for a HasMany.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   959
		 * If no 'collection' is supplied, a new collection will be created of the specified 'collectionType' option.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   960
		 * @param {Backbone.Collection} [collection]
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   961
		 * @return {Backbone.Collection}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   962
		 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   963
		_prepareCollection: function( collection ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   964
			if ( this.related ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   965
				this.stopListening( this.related );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   966
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   967
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   968
			if ( !collection || !( collection instanceof Backbone.Collection ) ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   969
				var options = _.isFunction( this.options.collectionOptions ) ?
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   970
					this.options.collectionOptions( this.instance ) : this.options.collectionOptions;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   971
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   972
				collection = new this.collectionType( null, options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   973
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   974
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   975
			collection.model = this.relatedModel;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   976
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   977
			if ( this.options.collectionKey ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   978
				var key = this.options.collectionKey === true ? this.options.reverseRelation.key : this.options.collectionKey;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   979
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   980
				if ( collection[ key ] && collection[ key ] !== this.instance ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   981
					if ( Backbone.Relational.showWarnings && typeof console !== 'undefined' ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   982
						console.warn( 'Relation=%o; collectionKey=%s already exists on collection=%o', this, key, this.options.collectionKey );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   983
					}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   984
				}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   985
				else if ( key ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   986
					collection[ key ] = this.instance;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   987
				}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   988
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   989
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   990
			this.listenTo( collection, 'relational:add', this.handleAddition )
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   991
				.listenTo( collection, 'relational:remove', this.handleRemoval )
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   992
				.listenTo( collection, 'relational:reset', this.handleReset );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   993
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   994
			return collection;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   995
		},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   996
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   997
		/**
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   998
		 * Find related Models.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   999
		 * @param {Object} [options]
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1000
		 * @return {Backbone.Collection}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1001
		 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1002
		findRelated: function( options ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1003
			var related = null;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1004
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1005
			options = _.defaults( { parse: this.options.parse }, options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1006
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1007
			// Replace 'this.related' by 'this.keyContents' if it is a Backbone.Collection
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1008
			if ( this.keyContents instanceof Backbone.Collection ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1009
				this._prepareCollection( this.keyContents );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1010
				related = this.keyContents;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1011
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1012
			// Otherwise, 'this.keyContents' should be an array of related object ids.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1013
			// Re-use the current 'this.related' if it is a Backbone.Collection; otherwise, create a new collection.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1014
			else {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1015
				var toAdd = [];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1016
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1017
				_.each( this.keyContents, function( attributes ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1018
					var model = null;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1019
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1020
					if ( attributes instanceof this.relatedModel ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1021
						model = attributes;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1022
					}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1023
					else {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1024
						// If `merge` is true, update models here, instead of during update.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1025
						model = this.relatedModel.findOrCreate( attributes,
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1026
							_.extend( { merge: true }, options, { create: this.options.createModels } )
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1027
						);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1028
					}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1029
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1030
					model && toAdd.push( model );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1031
				}, this );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1032
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1033
				if ( this.related instanceof Backbone.Collection ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1034
					related = this.related;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1035
				}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1036
				else {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1037
					related = this._prepareCollection();
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1038
				}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1039
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1040
				// By now, both `merge` and `parse` will already have been executed for models if they were specified.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1041
				// Disable them to prevent additional calls.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1042
				related.set( toAdd, _.defaults( { merge: false, parse: false }, options ) );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1043
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1044
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1045
			// Remove entries from `keyIds` that were already part of the relation (and are thus 'unchanged')
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1046
			this.keyIds = _.difference( this.keyIds, _.pluck( related.models, 'id' ) );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1047
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1048
			return related;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1049
		},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1050
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1051
		/**
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1052
		 * Normalize and reduce `keyContents` to a list of `ids`, for easier comparison
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1053
		 * @param {String|Number|String[]|Number[]|Backbone.Collection} keyContents
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1054
		 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1055
		setKeyContents: function( keyContents ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1056
			this.keyContents = keyContents instanceof Backbone.Collection ? keyContents : null;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1057
			this.keyIds = [];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1058
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1059
			if ( !this.keyContents && ( keyContents || keyContents === 0 ) ) { // since 0 can be a valid `id` as well
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1060
				// Handle cases the an API/user supplies just an Object/id instead of an Array
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1061
				this.keyContents = _.isArray( keyContents ) ? keyContents : [ keyContents ];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1062
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1063
				_.each( this.keyContents, function( item ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1064
					var itemId = Backbone.Relational.store.resolveIdForItem( this.relatedModel, item );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1065
					if ( itemId || itemId === 0 ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1066
						this.keyIds.push( itemId );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1067
					}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1068
				}, this );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1069
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1070
		},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1071
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1072
		/**
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1073
		 * Event handler for `change:<key>`.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1074
		 * If the contents of the key are changed, notify old & new reverse relations and initialize the new relation.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1075
		 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1076
		onChange: function( model, attr, options ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1077
			options = options ? _.clone( options ) : {};
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1078
			this.setKeyContents( attr );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1079
			this.changed = false;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1080
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1081
			var related = this.findRelated( options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1082
			this.setRelated( related );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1083
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1084
			if ( !options.silent ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1085
				var dit = this;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1086
				Backbone.Relational.eventQueue.add( function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1087
					// The `changed` flag can be set in `handleAddition` or `handleRemoval`
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1088
					if ( dit.changed ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1089
						dit.instance.trigger( 'change:' + dit.key, dit.instance, dit.related, options, true );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1090
						dit.changed = false;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1091
					}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1092
				});
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1093
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1094
		},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1095
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1096
		/**
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1097
		 * When a model is added to a 'HasMany', trigger 'add' on 'this.instance' and notify reverse relations.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1098
		 * (should be 'HasOne', must set 'this.instance' as their related).
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1099
		 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1100
		handleAddition: function( model, coll, options ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1101
			//console.debug('handleAddition called; args=%o', arguments);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1102
			options = options ? _.clone( options ) : {};
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1103
			this.changed = true;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1104
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1105
			_.each( this.getReverseRelations( model ), function( relation ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1106
				relation.addRelated( this.instance, options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1107
			}, this );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1108
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1109
			// Only trigger 'add' once the newly added model is initialized (so, has its relations set up)
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1110
			var dit = this;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1111
			!options.silent && Backbone.Relational.eventQueue.add( function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1112
				dit.instance.trigger( 'add:' + dit.key, model, dit.related, options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1113
			});
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1114
		},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1115
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1116
		/**
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1117
		 * When a model is removed from a 'HasMany', trigger 'remove' on 'this.instance' and notify reverse relations.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1118
		 * (should be 'HasOne', which should be nullified)
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1119
		 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1120
		handleRemoval: function( model, coll, options ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1121
			//console.debug('handleRemoval called; args=%o', arguments);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1122
			options = options ? _.clone( options ) : {};
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1123
			this.changed = true;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1124
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1125
			_.each( this.getReverseRelations( model ), function( relation ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1126
				relation.removeRelated( this.instance, null, options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1127
			}, this );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1128
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1129
			var dit = this;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1130
			!options.silent && Backbone.Relational.eventQueue.add( function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1131
				dit.instance.trigger( 'remove:' + dit.key, model, dit.related, options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1132
			});
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1133
		},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1134
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1135
		handleReset: function( coll, options ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1136
			var dit = this;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1137
			options = options ? _.clone( options ) : {};
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1138
			!options.silent && Backbone.Relational.eventQueue.add( function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1139
				dit.instance.trigger( 'reset:' + dit.key, dit.related, options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1140
			});
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1141
		},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1142
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1143
		tryAddRelated: function( model, coll, options ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1144
			var item = _.contains( this.keyIds, model.id );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1145
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1146
			if ( item ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1147
				this.addRelated( model, options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1148
				this.keyIds = _.without( this.keyIds, model.id );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1149
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1150
		},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1151
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1152
		addRelated: function( model, options ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1153
			// Allow 'model' to set up its relations before proceeding.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1154
			// (which can result in a call to 'addRelated' from a relation of 'model')
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1155
			var dit = this;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1156
			model.queue( function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1157
				if ( dit.related && !dit.related.get( model ) ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1158
					dit.related.add( model, _.defaults( { parse: false }, options ) );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1159
				}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1160
			});
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1161
		},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1162
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1163
		removeRelated: function( model, coll, options ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1164
			if ( this.related.get( model ) ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1165
				this.related.remove( model, options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1166
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1167
		}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1168
	});
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1169
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1170
	/**
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1171
	 * A type of Backbone.Model that also maintains relations to other models and collections.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1172
	 * New events when compared to the original:
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1173
	 *  - 'add:<key>' (model, related collection, options)
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1174
	 *  - 'remove:<key>' (model, related collection, options)
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1175
	 *  - 'change:<key>' (model, related model or collection, options)
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1176
	 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1177
	Backbone.RelationalModel = Backbone.Model.extend({
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1178
		relations: null, // Relation descriptions on the prototype
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1179
		_relations: null, // Relation instances
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1180
		_isInitialized: false,
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1181
		_deferProcessing: false,
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1182
		_queue: null,
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1183
		_attributeChangeFired: false, // Keeps track of `change` event firing under some conditions (like nested `set`s)
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1184
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1185
		subModelTypeAttribute: 'type',
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1186
		subModelTypes: null,
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1187
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1188
		constructor: function( attributes, options ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1189
			// Nasty hack, for cases like 'model.get( <HasMany key> ).add( item )'.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1190
			// Defer 'processQueue', so that when 'Relation.createModels' is used we trigger 'HasMany'
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1191
			// collection events only after the model is really fully set up.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1192
			// Example: event for "p.on( 'add:jobs' )" -> "p.get('jobs').add( { company: c.id, person: p.id } )".
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1193
			if ( options && options.collection ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1194
				var dit = this,
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1195
					collection = this.collection = options.collection;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1196
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1197
				// Prevent `collection` from cascading down to nested models; they shouldn't go into this `if` clause.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1198
				delete options.collection;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1199
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1200
				this._deferProcessing = true;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1201
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1202
				var processQueue = function( model ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1203
					if ( model === dit ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1204
						dit._deferProcessing = false;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1205
						dit.processQueue();
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1206
						collection.off( 'relational:add', processQueue );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1207
					}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1208
				};
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1209
				collection.on( 'relational:add', processQueue );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1210
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1211
				// So we do process the queue eventually, regardless of whether this model actually gets added to 'options.collection'.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1212
				_.defer( function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1213
					processQueue( dit );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1214
				});
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1215
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1216
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1217
			Backbone.Relational.store.processOrphanRelations();
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1218
			Backbone.Relational.store.listenTo( this, 'relational:unregister', Backbone.Relational.store.unregister );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1219
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1220
			this._queue = new Backbone.BlockingQueue();
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1221
			this._queue.block();
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1222
			Backbone.Relational.eventQueue.block();
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1223
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1224
			try {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1225
				Backbone.Model.apply( this, arguments );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1226
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1227
			finally {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1228
				// Try to run the global queue holding external events
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1229
				Backbone.Relational.eventQueue.unblock();
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1230
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1231
		},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1232
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1233
		/**
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1234
		 * Override 'trigger' to queue 'change' and 'change:*' events
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1235
		 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1236
		trigger: function( eventName ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1237
			if ( eventName.length > 5 && eventName.indexOf( 'change' ) === 0 ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1238
				var dit = this,
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1239
					args = arguments;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1240
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1241
				if ( !Backbone.Relational.eventQueue.isLocked() ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1242
					// If we're not in a more complicated nested scenario, fire the change event right away
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1243
					Backbone.Model.prototype.trigger.apply( dit, args );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1244
				}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1245
				else {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1246
					Backbone.Relational.eventQueue.add( function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1247
						// Determine if the `change` event is still valid, now that all relations are populated
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1248
						var changed = true;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1249
						if ( eventName === 'change' ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1250
							// `hasChanged` may have gotten reset by nested calls to `set`.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1251
							changed = dit.hasChanged() || dit._attributeChangeFired;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1252
							dit._attributeChangeFired = false;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1253
						}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1254
						else {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1255
							var attr = eventName.slice( 7 ),
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1256
								rel = dit.getRelation( attr );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1257
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1258
							if ( rel ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1259
								// If `attr` is a relation, `change:attr` get triggered from `Relation.onChange`.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1260
								// These take precedence over `change:attr` events triggered by `Model.set`.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1261
								// The relation sets a fourth attribute to `true`. If this attribute is present,
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1262
								// continue triggering this event; otherwise, it's from `Model.set` and should be stopped.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1263
								changed = ( args[ 4 ] === true );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1264
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1265
								// If this event was triggered by a relation, set the right value in `this.changed`
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1266
								// (a Collection or Model instead of raw data).
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1267
								if ( changed ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1268
									dit.changed[ attr ] = args[ 2 ];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1269
								}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1270
								// Otherwise, this event is from `Model.set`. If the relation doesn't report a change,
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1271
								// remove attr from `dit.changed` so `hasChanged` doesn't take it into account.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1272
								else if ( !rel.changed ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1273
									delete dit.changed[ attr ];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1274
								}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1275
							}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1276
							else if ( changed ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1277
								dit._attributeChangeFired = true;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1278
							}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1279
						}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1280
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1281
						changed && Backbone.Model.prototype.trigger.apply( dit, args );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1282
					});
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1283
				}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1284
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1285
			else if ( eventName === 'destroy' ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1286
				Backbone.Model.prototype.trigger.apply( this, arguments );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1287
				Backbone.Relational.store.unregister( this );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1288
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1289
			else {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1290
				Backbone.Model.prototype.trigger.apply( this, arguments );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1291
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1292
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1293
			return this;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1294
		},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1295
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1296
		/**
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1297
		 * Initialize Relations present in this.relations; determine the type (HasOne/HasMany), then creates a new instance.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1298
		 * Invoked in the first call so 'set' (which is made from the Backbone.Model constructor).
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1299
		 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1300
		initializeRelations: function( options ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1301
			this.acquire(); // Setting up relations often also involve calls to 'set', and we only want to enter this function once
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1302
			this._relations = {};
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1303
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1304
			_.each( this.relations || [], function( rel ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1305
				Backbone.Relational.store.initializeRelation( this, rel, options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1306
			}, this );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1307
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1308
			this._isInitialized = true;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1309
			this.release();
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1310
			this.processQueue();
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1311
		},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1312
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1313
		/**
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1314
		 * When new values are set, notify this model's relations (also if options.silent is set).
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1315
		 * (called from `set`; Relation.setRelated locks this model before calling 'set' on it to prevent loops)
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1316
		 * @param {Object} [changedAttrs]
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1317
		 * @param {Object} [options]
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1318
		 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1319
		updateRelations: function( changedAttrs, options ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1320
			if ( this._isInitialized && !this.isLocked() ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1321
				_.each( this._relations, function( rel ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1322
					if ( !changedAttrs || ( rel.keySource in changedAttrs || rel.key in changedAttrs ) ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1323
						// Fetch data in `rel.keySource` if data got set in there, or `rel.key` otherwise
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1324
						var value = this.attributes[ rel.keySource ] || this.attributes[ rel.key ],
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1325
							attr = changedAttrs && ( changedAttrs[ rel.keySource ] || changedAttrs[ rel.key ] );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1326
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1327
						// Update a relation if its value differs from this model's attributes, or it's been explicitly nullified.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1328
						// Which can also happen before the originally intended related model has been found (`val` is null).
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1329
						if ( rel.related !== value || ( value === null && attr === null ) ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1330
							this.trigger( 'relational:change:' + rel.key, this, value, options || {} );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1331
						}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1332
					}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1333
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1334
					// Explicitly clear 'keySource', to prevent a leaky abstraction if 'keySource' differs from 'key'.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1335
					if ( rel.keySource !== rel.key ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1336
						delete this.attributes[ rel.keySource ];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1337
					}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1338
				}, this );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1339
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1340
		},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1341
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1342
		/**
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1343
		 * Either add to the queue (if we're not initialized yet), or execute right away.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1344
		 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1345
		queue: function( func ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1346
			this._queue.add( func );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1347
		},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1348
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1349
		/**
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1350
		 * Process _queue
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1351
		 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1352
		processQueue: function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1353
			if ( this._isInitialized && !this._deferProcessing && this._queue.isBlocked() ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1354
				this._queue.unblock();
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1355
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1356
		},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1357
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1358
		/**
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1359
		 * Get a specific relation.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1360
		 * @param {string} attr The relation key to look for.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1361
		 * @return {Backbone.Relation} An instance of 'Backbone.Relation', if a relation was found for 'attr', or null.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1362
		 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1363
		getRelation: function( attr ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1364
			return this._relations[ attr ];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1365
		},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1366
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1367
		/**
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1368
		 * Get all of the created relations.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1369
		 * @return {Backbone.Relation[]}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1370
		 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1371
		getRelations: function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1372
			return _.values( this._relations );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1373
		},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1374
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1375
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1376
		/**
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1377
		 * Get a list of ids that will be fetched on a call to `getAsync`.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1378
		 * @param {string|Backbone.Relation} attr The relation key to fetch models for.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1379
		 * @param [refresh=false] Add ids for models that are already in the relation, refreshing them?
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1380
		 * @return {Array} An array of ids that need to be fetched.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1381
		 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1382
		getIdsToFetch: function( attr, refresh ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1383
			var rel = attr instanceof Backbone.Relation ? attr : this.getRelation( attr ),
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1384
				ids = rel ? ( rel.keyIds && rel.keyIds.slice( 0 ) ) || ( ( rel.keyId || rel.keyId === 0 ) ? [ rel.keyId ] : [] ) : [];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1385
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1386
			// On `refresh`, add the ids for current models in the relation to `idsToFetch`
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1387
			if ( refresh ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1388
				var models = rel.related && ( rel.related.models || [ rel.related ] );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1389
				_.each( models, function( model ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1390
					if ( model.id || model.id === 0 ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1391
						ids.push( model.id );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1392
					}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1393
				});
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1394
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1395
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1396
			return ids;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1397
		},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1398
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1399
		/**
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1400
		 * Get related objects. Returns a single promise, which can either resolve immediately (if the related model[s])
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1401
		 * are already present locally, or after fetching the contents of the requested attribute.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1402
		 * @param {string} attr The relation key to fetch models for.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1403
		 * @param {Object} [options] Options for 'Backbone.Model.fetch' and 'Backbone.sync'.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1404
		 * @param {Boolean} [options.refresh=false] Fetch existing models from the server as well (in order to update them).
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1405
		 * @return {jQuery.Deferred} A jQuery promise object. When resolved, its `done` callback will be called with
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1406
		 *  contents of `attr`.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1407
		 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1408
		getAsync: function( attr, options ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1409
			// Set default `options` for fetch
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1410
			options = _.extend( { add: true, remove: false, refresh: false }, options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1411
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1412
			var dit = this,
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1413
				requests = [],
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1414
				rel = this.getRelation( attr ),
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1415
				idsToFetch = rel && this.getIdsToFetch( rel, options.refresh ),
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1416
				coll = rel.related instanceof Backbone.Collection ? rel.related : rel.relatedCollection;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1417
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1418
			if ( idsToFetch && idsToFetch.length ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1419
				var models = [],
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1420
					createdModels = [],
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1421
					setUrl,
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1422
					createModels = function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1423
						// Find (or create) a model for each one that is to be fetched
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1424
						models = _.map( idsToFetch, function( id ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1425
							var model = rel.relatedModel.findModel( id );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1426
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1427
							if ( !model ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1428
								var attrs = {};
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1429
								attrs[ rel.relatedModel.prototype.idAttribute ] = id;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1430
								model = rel.relatedModel.findOrCreate( attrs, options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1431
								createdModels.push( model );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1432
							}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1433
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1434
							return model;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1435
						}, this );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1436
					};
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1437
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1438
				// Try if the 'collection' can provide a url to fetch a set of models in one request.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1439
				// This assumes that when 'Backbone.Collection.url' is a function, it can handle building of set urls.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1440
				// To make sure it can, test if the url we got by supplying a list of models to fetch is different from
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1441
				// the one supplied for the default fetch action (without args to 'url').
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1442
				if ( coll instanceof Backbone.Collection && _.isFunction( coll.url ) ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1443
					var defaultUrl = coll.url();
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1444
					setUrl = coll.url( idsToFetch );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1445
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1446
					if ( setUrl === defaultUrl ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1447
						createModels();
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1448
						setUrl = coll.url( models );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1449
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1450
						if ( setUrl === defaultUrl ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1451
							setUrl = null;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1452
						}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1453
					}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1454
				}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1455
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1456
				if ( setUrl ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1457
					// Do a single request to fetch all models
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1458
					var opts = _.defaults(
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1459
						{
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1460
							error: function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1461
								_.each( createdModels, function( model ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1462
									model.trigger( 'destroy', model, model.collection, options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1463
								});
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1464
								
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1465
								options.error && options.error.apply( models, arguments );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1466
							},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1467
							url: setUrl
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1468
						},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1469
						options
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1470
					);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1471
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1472
					requests = [ coll.fetch( opts ) ];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1473
				}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1474
				else {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1475
					// Make a request per model to fetch
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1476
					if  ( !models.length ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1477
						createModels();
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1478
					}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1479
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1480
					requests = _.map( models, function( model ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1481
						var opts = _.defaults(
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1482
							{
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1483
								error: function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1484
									if ( _.contains( createdModels, model ) ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1485
										model.trigger( 'destroy', model, model.collection, options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1486
									}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1487
									options.error && options.error.apply( models, arguments );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1488
								}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1489
							},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1490
							options
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1491
						);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1492
						return model.fetch( opts );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1493
					}, this );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1494
				}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1495
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1496
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1497
			return $.when.apply( null, requests ).then(
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1498
				function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1499
					return Backbone.Model.prototype.get.call( dit, attr );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1500
				}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1501
			);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1502
		},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1503
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1504
		set: function( key, value, options ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1505
			Backbone.Relational.eventQueue.block();
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1506
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1507
			// Duplicate backbone's behavior to allow separate key/value parameters, instead of a single 'attributes' object
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1508
			var attributes,
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1509
				result;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1510
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1511
			if ( _.isObject( key ) || key == null ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1512
				attributes = key;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1513
				options = value;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1514
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1515
			else {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1516
				attributes = {};
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1517
				attributes[ key ] = value;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1518
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1519
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1520
			try {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1521
				var id = this.id,
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1522
					newId = attributes && this.idAttribute in attributes && attributes[ this.idAttribute ];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1523
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1524
				// Check if we're not setting a duplicate id before actually calling `set`.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1525
				Backbone.Relational.store.checkId( this, newId );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1526
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1527
				result = Backbone.Model.prototype.set.apply( this, arguments );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1528
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1529
				// Ideal place to set up relations, if this is the first time we're here for this model
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1530
				if ( !this._isInitialized && !this.isLocked() ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1531
					this.constructor.initializeModelHierarchy();
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1532
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1533
					// Only register models that have an id. A model will be registered when/if it gets an id later on.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1534
					if ( newId || newId === 0 ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1535
						Backbone.Relational.store.register( this );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1536
					}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1537
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1538
					this.initializeRelations( options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1539
				}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1540
				// The store should know about an `id` update asap
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1541
				else if ( newId && newId !== id ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1542
					Backbone.Relational.store.update( this );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1543
				}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1544
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1545
				if ( attributes ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1546
					this.updateRelations( attributes, options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1547
				}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1548
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1549
			finally {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1550
				// Try to run the global queue holding external events
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1551
				Backbone.Relational.eventQueue.unblock();
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1552
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1553
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1554
			return result;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1555
		},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1556
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1557
		clone: function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1558
			var attributes = _.clone( this.attributes );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1559
			if ( !_.isUndefined( attributes[ this.idAttribute ] ) ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1560
				attributes[ this.idAttribute ] = null;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1561
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1562
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1563
			_.each( this.getRelations(), function( rel ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1564
				delete attributes[ rel.key ];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1565
			});
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1566
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1567
			return new this.constructor( attributes );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1568
		},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1569
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1570
		/**
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1571
		 * Convert relations to JSON, omits them when required
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1572
		 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1573
		toJSON: function( options ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1574
			// If this Model has already been fully serialized in this branch once, return to avoid loops
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1575
			if ( this.isLocked() ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1576
				return this.id;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1577
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1578
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1579
			this.acquire();
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1580
			var json = Backbone.Model.prototype.toJSON.call( this, options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1581
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1582
			if ( this.constructor._superModel && !( this.constructor._subModelTypeAttribute in json ) ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1583
				json[ this.constructor._subModelTypeAttribute ] = this.constructor._subModelTypeValue;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1584
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1585
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1586
			_.each( this._relations, function( rel ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1587
				var related = json[ rel.key ],
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1588
					includeInJSON = rel.options.includeInJSON,
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1589
					value = null;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1590
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1591
				if ( includeInJSON === true ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1592
					if ( related && _.isFunction( related.toJSON ) ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1593
						value = related.toJSON( options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1594
					}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1595
				}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1596
				else if ( _.isString( includeInJSON ) ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1597
					if ( related instanceof Backbone.Collection ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1598
						value = related.pluck( includeInJSON );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1599
					}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1600
					else if ( related instanceof Backbone.Model ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1601
						value = related.get( includeInJSON );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1602
					}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1603
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1604
					// Add ids for 'unfound' models if includeInJSON is equal to (only) the relatedModel's `idAttribute`
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1605
					if ( includeInJSON === rel.relatedModel.prototype.idAttribute ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1606
						if ( rel instanceof Backbone.HasMany ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1607
							value = value.concat( rel.keyIds );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1608
						}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1609
						else if ( rel instanceof Backbone.HasOne ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1610
							value = value || rel.keyId;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1611
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1612
							if ( !value && !_.isObject( rel.keyContents ) ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1613
								value = rel.keyContents || null;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1614
							}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1615
						}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1616
					}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1617
				}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1618
				else if ( _.isArray( includeInJSON ) ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1619
					if ( related instanceof Backbone.Collection ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1620
						value = [];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1621
						related.each( function( model ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1622
							var curJson = {};
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1623
							_.each( includeInJSON, function( key ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1624
								curJson[ key ] = model.get( key );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1625
							});
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1626
							value.push( curJson );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1627
						});
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1628
					}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1629
					else if ( related instanceof Backbone.Model ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1630
						value = {};
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1631
						_.each( includeInJSON, function( key ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1632
							value[ key ] = related.get( key );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1633
						});
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1634
					}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1635
				}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1636
				else {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1637
					delete json[ rel.key ];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1638
				}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1639
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1640
				// In case of `wait: true`, Backbone will simply push whatever's passed into `save` into attributes.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1641
				// We'll want to get this information into the JSON, even if it doesn't conform to our normal
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1642
				// expectations of what's contained in it (no model/collection for a relation, etc).
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1643
				if ( value === null && options && options.wait ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1644
					value = related;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1645
				}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1646
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1647
				if ( includeInJSON ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1648
					json[ rel.keyDestination ] = value;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1649
				}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1650
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1651
				if ( rel.keyDestination !== rel.key ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1652
					delete json[ rel.key ];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1653
				}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1654
			});
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1655
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1656
			this.release();
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1657
			return json;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1658
		}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1659
	},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1660
	{
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1661
		/**
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1662
		 *
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1663
		 * @param superModel
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1664
		 * @returns {Backbone.RelationalModel.constructor}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1665
		 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1666
		setup: function( superModel ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1667
			// We don't want to share a relations array with a parent, as this will cause problems with reverse
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1668
			// relations. Since `relations` may also be a property or function, only use slice if we have an array.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1669
			this.prototype.relations = ( this.prototype.relations || [] ).slice( 0 );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1670
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1671
			this._subModels = {};
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1672
			this._superModel = null;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1673
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1674
			// If this model has 'subModelTypes' itself, remember them in the store
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1675
			if ( this.prototype.hasOwnProperty( 'subModelTypes' ) ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1676
				Backbone.Relational.store.addSubModels( this.prototype.subModelTypes, this );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1677
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1678
			// The 'subModelTypes' property should not be inherited, so reset it.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1679
			else {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1680
				this.prototype.subModelTypes = null;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1681
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1682
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1683
			// Initialize all reverseRelations that belong to this new model.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1684
			_.each( this.prototype.relations || [], function( rel ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1685
				if ( !rel.model ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1686
					rel.model = this;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1687
				}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1688
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1689
				if ( rel.reverseRelation && rel.model === this ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1690
					var preInitialize = true;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1691
					if ( _.isString( rel.relatedModel ) ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1692
						/**
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1693
						 * The related model might not be defined for two reasons
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1694
						 *  1. it is related to itself
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1695
						 *  2. it never gets defined, e.g. a typo
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1696
						 *  3. the model hasn't been defined yet, but will be later
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1697
						 * In neither of these cases do we need to pre-initialize reverse relations.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1698
						 * However, for 3. (which is, to us, indistinguishable from 2.), we do need to attempt
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1699
						 * setting up this relation again later, in case the related model is defined later.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1700
						 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1701
						var relatedModel = Backbone.Relational.store.getObjectByName( rel.relatedModel );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1702
						preInitialize = relatedModel && ( relatedModel.prototype instanceof Backbone.RelationalModel );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1703
					}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1704
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1705
					if ( preInitialize ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1706
						Backbone.Relational.store.initializeRelation( null, rel );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1707
					}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1708
					else if ( _.isString( rel.relatedModel ) ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1709
						Backbone.Relational.store.addOrphanRelation( rel );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1710
					}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1711
				}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1712
			}, this );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1713
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1714
			return this;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1715
		},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1716
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1717
		/**
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1718
		 * Create a 'Backbone.Model' instance based on 'attributes'.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1719
		 * @param {Object} attributes
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1720
		 * @param {Object} [options]
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1721
		 * @return {Backbone.Model}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1722
		 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1723
		build: function( attributes, options ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1724
			// 'build' is a possible entrypoint; it's possible no model hierarchy has been determined yet.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1725
			this.initializeModelHierarchy();
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1726
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1727
			// Determine what type of (sub)model should be built if applicable.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1728
			var model = this._findSubModelType( this, attributes ) || this;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1729
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1730
			return new model( attributes, options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1731
		},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1732
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1733
		/**
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1734
		 * Determines what type of (sub)model should be built if applicable.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1735
		 * Looks up the proper subModelType in 'this._subModels', recursing into
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1736
		 * types until a match is found.  Returns the applicable 'Backbone.Model'
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1737
		 * or null if no match is found.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1738
		 * @param {Backbone.Model} type
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1739
		 * @param {Object} attributes
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1740
		 * @return {Backbone.Model}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1741
		 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1742
		_findSubModelType: function( type, attributes ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1743
			if ( type._subModels && type.prototype.subModelTypeAttribute in attributes ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1744
				var subModelTypeAttribute = attributes[ type.prototype.subModelTypeAttribute ];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1745
				var subModelType = type._subModels[ subModelTypeAttribute ];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1746
				if ( subModelType ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1747
					return subModelType;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1748
				}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1749
				else {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1750
					// Recurse into subModelTypes to find a match
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1751
					for ( subModelTypeAttribute in type._subModels ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1752
						subModelType = this._findSubModelType( type._subModels[ subModelTypeAttribute ], attributes );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1753
						if ( subModelType ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1754
							return subModelType;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1755
						}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1756
					}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1757
				}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1758
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1759
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1760
			return null;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1761
		},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1762
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1763
		/**
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1764
		 *
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1765
		 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1766
		initializeModelHierarchy: function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1767
			// Inherit any relations that have been defined in the parent model.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1768
			this.inheritRelations();
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1769
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1770
			// If we came here through 'build' for a model that has 'subModelTypes' then try to initialize the ones that
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1771
			// haven't been resolved yet.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1772
			if ( this.prototype.subModelTypes ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1773
				var resolvedSubModels = _.keys( this._subModels );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1774
				var unresolvedSubModels = _.omit( this.prototype.subModelTypes, resolvedSubModels );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1775
				_.each( unresolvedSubModels, function( subModelTypeName ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1776
					var subModelType = Backbone.Relational.store.getObjectByName( subModelTypeName );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1777
					subModelType && subModelType.initializeModelHierarchy();
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1778
				});
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1779
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1780
		},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1781
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1782
		inheritRelations: function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1783
			// Bail out if we've been here before.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1784
			if ( !_.isUndefined( this._superModel ) && !_.isNull( this._superModel ) ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1785
				return;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1786
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1787
			// Try to initialize the _superModel.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1788
			Backbone.Relational.store.setupSuperModel( this );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1789
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1790
			// If a superModel has been found, copy relations from the _superModel if they haven't been inherited automatically
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1791
			// (due to a redefinition of 'relations').
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1792
			if ( this._superModel ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1793
				// The _superModel needs a chance to initialize its own inherited relations before we attempt to inherit relations
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1794
				// from the _superModel. You don't want to call 'initializeModelHierarchy' because that could cause sub-models of
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1795
				// this class to inherit their relations before this class has had chance to inherit it's relations.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1796
				this._superModel.inheritRelations();
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1797
				if ( this._superModel.prototype.relations ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1798
					// Find relations that exist on the '_superModel', but not yet on this model.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1799
					var inheritedRelations = _.filter( this._superModel.prototype.relations || [], function( superRel ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1800
						return !_.any( this.prototype.relations || [], function( rel ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1801
							return superRel.relatedModel === rel.relatedModel && superRel.key === rel.key;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1802
						}, this );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1803
					}, this );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1804
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1805
					this.prototype.relations = inheritedRelations.concat( this.prototype.relations );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1806
				}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1807
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1808
			// Otherwise, make sure we don't get here again for this type by making '_superModel' false so we fail the
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1809
			// isUndefined/isNull check next time.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1810
			else {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1811
				this._superModel = false;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1812
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1813
		},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1814
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1815
		/**
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1816
		 * Find an instance of `this` type in 'Backbone.Relational.store'.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1817
		 * A new model is created if no matching model is found, `attributes` is an object, and `options.create` is true.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1818
		 * - If `attributes` is a string or a number, `findOrCreate` will query the `store` and return a model if found.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1819
		 * - If `attributes` is an object and is found in the store, the model will be updated with `attributes` unless `options.merge` is `false`.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1820
		 * @param {Object|String|Number} attributes Either a model's id, or the attributes used to create or update a model.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1821
		 * @param {Object} [options]
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1822
		 * @param {Boolean} [options.create=true]
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1823
		 * @param {Boolean} [options.merge=true]
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1824
		 * @param {Boolean} [options.parse=false]
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1825
		 * @return {Backbone.RelationalModel}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1826
		 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1827
		findOrCreate: function( attributes, options ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1828
			options || ( options = {} );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1829
			var parsedAttributes = ( _.isObject( attributes ) && options.parse && this.prototype.parse ) ?
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1830
				this.prototype.parse( _.clone( attributes ) ) : attributes;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1831
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1832
			// If specified, use a custom `find` function to match up existing models to the given attributes.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1833
			// Otherwise, try to find an instance of 'this' model type in the store
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1834
			var model = this.findModel( parsedAttributes );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1835
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1836
			// If we found an instance, update it with the data in 'item' (unless 'options.merge' is false).
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1837
			// If not, create an instance (unless 'options.create' is false).
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1838
			if ( _.isObject( attributes ) ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1839
				if ( model && options.merge !== false ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1840
					// Make sure `options.collection` and `options.url` doesn't cascade to nested models
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1841
					delete options.collection;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1842
					delete options.url;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1843
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1844
					model.set( parsedAttributes, options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1845
				}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1846
				else if ( !model && options.create !== false ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1847
					model = this.build( parsedAttributes, _.defaults( { parse: false }, options ) );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1848
				}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1849
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1850
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1851
			return model;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1852
		},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1853
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1854
		/**
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1855
		 * Find an instance of `this` type in 'Backbone.Relational.store'.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1856
		 * - If `attributes` is a string or a number, `find` will query the `store` and return a model if found.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1857
		 * - If `attributes` is an object and is found in the store, the model will be updated with `attributes` unless `options.merge` is `false`.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1858
		 * @param {Object|String|Number} attributes Either a model's id, or the attributes used to create or update a model.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1859
		 * @param {Object} [options]
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1860
		 * @param {Boolean} [options.merge=true]
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1861
		 * @param {Boolean} [options.parse=false]
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1862
		 * @return {Backbone.RelationalModel}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1863
		 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1864
		find: function( attributes, options ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1865
			options || ( options = {} );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1866
			options.create = false;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1867
			return this.findOrCreate( attributes, options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1868
		},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1869
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1870
		/**
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1871
		 * A hook to override the matching when updating (or creating) a model.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1872
		 * The default implementation is to look up the model by id in the store.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1873
		 * @param {Object} attributes
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1874
		 * @returns {Backbone.RelationalModel}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1875
		 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1876
		findModel: function( attributes ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1877
			return Backbone.Relational.store.find( this, attributes );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1878
		}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1879
	});
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1880
	_.extend( Backbone.RelationalModel.prototype, Backbone.Semaphore );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1881
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1882
	/**
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1883
	 * Override Backbone.Collection._prepareModel, so objects will be built using the correct type
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1884
	 * if the collection.model has subModels.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1885
	 * Attempts to find a model for `attrs` in Backbone.store through `findOrCreate`
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1886
	 * (which sets the new properties on it if found), or instantiates a new model.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1887
	 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1888
	Backbone.Collection.prototype.__prepareModel = Backbone.Collection.prototype._prepareModel;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1889
	Backbone.Collection.prototype._prepareModel = function( attrs, options ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1890
		var model;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1891
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1892
		if ( attrs instanceof Backbone.Model ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1893
			if ( !attrs.collection ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1894
				attrs.collection = this;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1895
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1896
			model = attrs;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1897
		}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1898
		else {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1899
			options = options ? _.clone( options ) : {};
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1900
			options.collection = this;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1901
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1902
			if ( typeof this.model.findOrCreate !== 'undefined' ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1903
				model = this.model.findOrCreate( attrs, options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1904
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1905
			else {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1906
				model = new this.model( attrs, options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1907
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1908
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1909
			if ( model && model.validationError ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1910
				this.trigger( 'invalid', this, attrs, options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1911
				model = false;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1912
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1913
		}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1914
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1915
		return model;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1916
	};
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1917
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1918
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1919
	/**
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1920
	 * Override Backbone.Collection.set, so we'll create objects from attributes where required,
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1921
	 * and update the existing models. Also, trigger 'relational:add'.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1922
	 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1923
	var set = Backbone.Collection.prototype.__set = Backbone.Collection.prototype.set;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1924
	Backbone.Collection.prototype.set = function( models, options ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1925
		// Short-circuit if this Collection doesn't hold RelationalModels
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1926
		if ( !( this.model.prototype instanceof Backbone.RelationalModel ) ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1927
			return set.call( this, models, options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1928
		}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1929
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1930
		if ( options && options.parse ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1931
			models = this.parse( models, options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1932
		}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1933
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1934
		var singular = !_.isArray( models ),
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1935
			newModels = [],
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1936
			toAdd = [],
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1937
			model = null;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1938
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1939
		models = singular ? ( models ? [ models ] : [] ) : _.clone( models );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1940
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1941
		//console.debug( 'calling add on coll=%o; model=%o, options=%o', this, models, options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1942
		for ( var i = 0; i < models.length; i++ ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1943
			model = models[i];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1944
			if ( !( model instanceof Backbone.Model ) ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1945
				model = Backbone.Collection.prototype._prepareModel.call( this, model, options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1946
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1947
			if ( model ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1948
				toAdd.push( model );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1949
				if ( !( this.get( model ) || this.get( model.cid ) ) ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1950
					newModels.push( model );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1951
				}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1952
				// If we arrive in `add` while performing a `set` (after a create, so the model gains an `id`),
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1953
				// we may get here before `_onModelEvent` has had the chance to update `_byId`.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1954
				else if ( model.id !== null && model.id !== undefined ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1955
					this._byId[ model.id ] = model;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1956
				}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1957
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1958
		}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1959
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1960
		// Add 'models' in a single batch, so the original add will only be called once (and thus 'sort', etc).
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1961
		// If `parse` was specified, the collection and contained models have been parsed now.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1962
		toAdd = singular ? ( toAdd.length ? toAdd[ 0 ] : null ) : toAdd;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1963
		var result = set.call( this, toAdd, _.defaults( { merge: false, parse: false }, options ) );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1964
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1965
		for ( i = 0; i < newModels.length; i++ ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1966
			model = newModels[i];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1967
			// Fire a `relational:add` event for any model in `newModels` that has actually been added to the collection.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1968
			if ( this.get( model ) || this.get( model.cid ) ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1969
				this.trigger( 'relational:add', model, this, options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1970
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1971
		}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1972
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1973
		return result;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1974
	};
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1975
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1976
	/**
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1977
	 * Override 'Backbone.Collection.remove' to trigger 'relational:remove'.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1978
	 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1979
	var remove = Backbone.Collection.prototype.__remove = Backbone.Collection.prototype.remove;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1980
	Backbone.Collection.prototype.remove = function( models, options ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1981
		// Short-circuit if this Collection doesn't hold RelationalModels
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1982
		if ( !( this.model.prototype instanceof Backbone.RelationalModel ) ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1983
			return remove.call( this, models, options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1984
		}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1985
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1986
		var singular = !_.isArray( models ),
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1987
			toRemove = [];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1988
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1989
		models = singular ? ( models ? [ models ] : [] ) : _.clone( models );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1990
		options || ( options = {} );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1991
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1992
		//console.debug('calling remove on coll=%o; models=%o, options=%o', this, models, options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1993
		_.each( models, function( model ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1994
			model = this.get( model ) || ( model && this.get( model.cid ) );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1995
			model && toRemove.push( model );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1996
		}, this );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1997
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1998
		var result = remove.call( this, singular ? ( toRemove.length ? toRemove[ 0 ] : null ) : toRemove, options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1999
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2000
		_.each( toRemove, function( model ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2001
			this.trigger( 'relational:remove', model, this, options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2002
		}, this );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2003
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2004
		return result;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2005
	};
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2006
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2007
	/**
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2008
	 * Override 'Backbone.Collection.reset' to trigger 'relational:reset'.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2009
	 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2010
	var reset = Backbone.Collection.prototype.__reset = Backbone.Collection.prototype.reset;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2011
	Backbone.Collection.prototype.reset = function( models, options ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2012
		options = _.extend( { merge: true }, options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2013
		var result = reset.call( this, models, options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2014
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2015
		if ( this.model.prototype instanceof Backbone.RelationalModel ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2016
			this.trigger( 'relational:reset', this, options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2017
		}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2018
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2019
		return result;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2020
	};
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2021
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2022
	/**
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2023
	 * Override 'Backbone.Collection.sort' to trigger 'relational:reset'.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2024
	 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2025
	var sort = Backbone.Collection.prototype.__sort = Backbone.Collection.prototype.sort;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2026
	Backbone.Collection.prototype.sort = function( options ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2027
		var result = sort.call( this, options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2028
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2029
		if ( this.model.prototype instanceof Backbone.RelationalModel ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2030
			this.trigger( 'relational:reset', this, options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2031
		}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2032
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2033
		return result;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2034
	};
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2035
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2036
	/**
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2037
	 * Override 'Backbone.Collection.trigger' so 'add', 'remove' and 'reset' events are queued until relations
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2038
	 * are ready.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2039
	 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2040
	var trigger = Backbone.Collection.prototype.__trigger = Backbone.Collection.prototype.trigger;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2041
	Backbone.Collection.prototype.trigger = function( eventName ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2042
		// Short-circuit if this Collection doesn't hold RelationalModels
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2043
		if ( !( this.model.prototype instanceof Backbone.RelationalModel ) ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2044
			return trigger.apply( this, arguments );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2045
		}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2046
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2047
		if ( eventName === 'add' || eventName === 'remove' || eventName === 'reset' || eventName === 'sort' ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2048
			var dit = this,
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2049
				args = arguments;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2050
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2051
			if ( _.isObject( args[ 3 ] ) ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2052
				args = _.toArray( args );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2053
				// the fourth argument is the option object.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2054
				// we need to clone it, as it could be modified while we wait on the eventQueue to be unblocked
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2055
				args[ 3 ] = _.clone( args[ 3 ] );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2056
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2057
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2058
			Backbone.Relational.eventQueue.add( function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2059
				trigger.apply( dit, args );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2060
			});
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2061
		}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2062
		else {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2063
			trigger.apply( this, arguments );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2064
		}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2065
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2066
		return this;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2067
	};
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2068
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2069
	// Override .extend() to automatically call .setup()
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2070
	Backbone.RelationalModel.extend = function( protoProps, classProps ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2071
		var child = Backbone.Model.extend.call( this, protoProps, classProps );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2072
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2073
		child.setup( this );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2074
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2075
		return child;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2076
	};
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2077
}));