server/php/basic/public_html/static/lib/backbone-relational/backbone-relational.js
author durandn
Thu, 21 Apr 2016 15:18:19 +0200
changeset 605 13d355fd09bf
parent 498 08d121184a38
permissions -rw-r--r--
updated uri to allow optional trailing slash on single resource URIs (django automatic redirects don't carry over the Authorization header that can sometimes be needed, for instance with OAuth)
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
/**
498
08d121184a38 upgrade libs
ymh <ymh.work@gmail.com>
parents: 442
diff changeset
     3
 * Backbone-relational.js 0.10.0
442
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.
498
08d121184a38 upgrade libs
ymh <ymh.work@gmail.com>
parents: 442
diff changeset
  1025
						model = ( _.isObject( attributes ) && options.parse && this.relatedModel.prototype.parse ) ?
08d121184a38 upgrade libs
ymh <ymh.work@gmail.com>
parents: 442
diff changeset
  1026
							this.relatedModel.prototype.parse( _.clone( attributes ), options ) : attributes;
442
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
					model && toAdd.push( model );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1030
				}, this );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1031
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1032
				if ( this.related instanceof Backbone.Collection ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1033
					related = this.related;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1034
				}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1035
				else {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1036
					related = this._prepareCollection();
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1037
				}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1038
498
08d121184a38 upgrade libs
ymh <ymh.work@gmail.com>
parents: 442
diff changeset
  1039
				// By now, `parse` will already have been executed just above for models if specified.
08d121184a38 upgrade libs
ymh <ymh.work@gmail.com>
parents: 442
diff changeset
  1040
				// Disable to prevent additional calls.
08d121184a38 upgrade libs
ymh <ymh.work@gmail.com>
parents: 442
diff changeset
  1041
				related.set( toAdd, _.defaults( { parse: false }, options ) );
442
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1042
			}
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
			// 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
  1045
			this.keyIds = _.difference( this.keyIds, _.pluck( related.models, 'id' ) );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1046
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1047
			return related;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1048
		},
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
		 * 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
  1052
		 * @param {String|Number|String[]|Number[]|Backbone.Collection} keyContents
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1053
		 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1054
		setKeyContents: function( keyContents ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1055
			this.keyContents = keyContents instanceof Backbone.Collection ? keyContents : null;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1056
			this.keyIds = [];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1057
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1058
			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
  1059
				// 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
  1060
				this.keyContents = _.isArray( keyContents ) ? keyContents : [ keyContents ];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1061
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1062
				_.each( this.keyContents, function( item ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1063
					var itemId = Backbone.Relational.store.resolveIdForItem( this.relatedModel, item );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1064
					if ( itemId || itemId === 0 ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1065
						this.keyIds.push( itemId );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1066
					}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1067
				}, this );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1068
			}
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
		 * Event handler for `change:<key>`.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1073
		 * 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
  1074
		 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1075
		onChange: function( model, attr, options ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1076
			options = options ? _.clone( options ) : {};
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1077
			this.setKeyContents( attr );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1078
			this.changed = false;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1079
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1080
			var related = this.findRelated( options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1081
			this.setRelated( related );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1082
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1083
			if ( !options.silent ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1084
				var dit = this;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1085
				Backbone.Relational.eventQueue.add( function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1086
					// The `changed` flag can be set in `handleAddition` or `handleRemoval`
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1087
					if ( dit.changed ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1088
						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
  1089
						dit.changed = false;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1090
					}
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
		 * 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
  1097
		 * (should be 'HasOne', must set 'this.instance' as their related).
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1098
		 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1099
		handleAddition: function( model, coll, options ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1100
			//console.debug('handleAddition called; args=%o', arguments);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1101
			options = options ? _.clone( options ) : {};
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1102
			this.changed = true;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1103
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1104
			_.each( this.getReverseRelations( model ), function( relation ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1105
				relation.addRelated( this.instance, options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1106
			}, this );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1107
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1108
			// 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
  1109
			var dit = this;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1110
			!options.silent && Backbone.Relational.eventQueue.add( function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1111
				dit.instance.trigger( 'add:' + dit.key, model, dit.related, options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1112
			});
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
		 * 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
  1117
		 * (should be 'HasOne', which should be nullified)
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1118
		 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1119
		handleRemoval: function( model, coll, options ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1120
			//console.debug('handleRemoval called; args=%o', arguments);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1121
			options = options ? _.clone( options ) : {};
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1122
			this.changed = true;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1123
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1124
			_.each( this.getReverseRelations( model ), function( relation ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1125
				relation.removeRelated( this.instance, null, options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1126
			}, this );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1127
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1128
			var dit = this;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1129
			!options.silent && Backbone.Relational.eventQueue.add( function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1130
				dit.instance.trigger( 'remove:' + dit.key, model, dit.related, options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1131
			});
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
		handleReset: function( coll, options ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1135
			var dit = this;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1136
			options = options ? _.clone( options ) : {};
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1137
			!options.silent && Backbone.Relational.eventQueue.add( function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1138
				dit.instance.trigger( 'reset:' + dit.key, dit.related, options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1139
			});
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
		tryAddRelated: function( model, coll, options ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1143
			var item = _.contains( this.keyIds, model.id );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1144
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1145
			if ( item ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1146
				this.addRelated( model, options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1147
				this.keyIds = _.without( this.keyIds, model.id );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1148
			}
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
		addRelated: function( model, options ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1152
			// Allow 'model' to set up its relations before proceeding.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1153
			// (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
  1154
			var dit = this;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1155
			model.queue( function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1156
				if ( dit.related && !dit.related.get( model ) ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1157
					dit.related.add( model, _.defaults( { parse: false }, options ) );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1158
				}
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
		removeRelated: function( model, coll, options ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1163
			if ( this.related.get( model ) ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1164
				this.related.remove( model, options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1165
			}
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
	 * 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
  1171
	 * New events when compared to the original:
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1172
	 *  - 'add:<key>' (model, related collection, options)
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1173
	 *  - 'remove:<key>' (model, related collection, options)
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1174
	 *  - 'change:<key>' (model, related model or collection, options)
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1175
	 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1176
	Backbone.RelationalModel = Backbone.Model.extend({
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1177
		relations: null, // Relation descriptions on the prototype
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1178
		_relations: null, // Relation instances
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1179
		_isInitialized: false,
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1180
		_deferProcessing: false,
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1181
		_queue: null,
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1182
		_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
  1183
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1184
		subModelTypeAttribute: 'type',
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1185
		subModelTypes: null,
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1186
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1187
		constructor: function( attributes, options ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1188
			// Nasty hack, for cases like 'model.get( <HasMany key> ).add( item )'.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1189
			// 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
  1190
			// collection events only after the model is really fully set up.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1191
			// 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
  1192
			if ( options && options.collection ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1193
				var dit = this,
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1194
					collection = this.collection = options.collection;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1195
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1196
				// 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
  1197
				delete options.collection;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1198
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1199
				this._deferProcessing = true;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1200
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1201
				var processQueue = function( model ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1202
					if ( model === dit ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1203
						dit._deferProcessing = false;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1204
						dit.processQueue();
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1205
						collection.off( 'relational:add', processQueue );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1206
					}
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
				collection.on( 'relational:add', processQueue );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1209
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1210
				// 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
  1211
				_.defer( function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1212
					processQueue( dit );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1213
				});
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
			Backbone.Relational.store.processOrphanRelations();
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1217
			Backbone.Relational.store.listenTo( this, 'relational:unregister', Backbone.Relational.store.unregister );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1218
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1219
			this._queue = new Backbone.BlockingQueue();
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1220
			this._queue.block();
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1221
			Backbone.Relational.eventQueue.block();
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1222
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1223
			try {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1224
				Backbone.Model.apply( this, arguments );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1225
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1226
			finally {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1227
				// Try to run the global queue holding external events
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1228
				Backbone.Relational.eventQueue.unblock();
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1229
			}
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
		 * Override 'trigger' to queue 'change' and 'change:*' events
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1234
		 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1235
		trigger: function( eventName ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1236
			if ( eventName.length > 5 && eventName.indexOf( 'change' ) === 0 ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1237
				var dit = this,
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1238
					args = arguments;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1239
498
08d121184a38 upgrade libs
ymh <ymh.work@gmail.com>
parents: 442
diff changeset
  1240
				if ( !Backbone.Relational.eventQueue.isBlocked() ) {
442
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1241
					// 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
  1242
					Backbone.Model.prototype.trigger.apply( dit, args );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1243
				}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1244
				else {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1245
					Backbone.Relational.eventQueue.add( function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1246
						// 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
  1247
						var changed = true;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1248
						if ( eventName === 'change' ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1249
							// `hasChanged` may have gotten reset by nested calls to `set`.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1250
							changed = dit.hasChanged() || dit._attributeChangeFired;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1251
							dit._attributeChangeFired = false;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1252
						}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1253
						else {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1254
							var attr = eventName.slice( 7 ),
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1255
								rel = dit.getRelation( attr );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1256
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1257
							if ( rel ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1258
								// 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
  1259
								// These take precedence over `change:attr` events triggered by `Model.set`.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1260
								// 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
  1261
								// 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
  1262
								changed = ( args[ 4 ] === true );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1263
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1264
								// 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
  1265
								// (a Collection or Model instead of raw data).
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1266
								if ( changed ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1267
									dit.changed[ attr ] = args[ 2 ];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1268
								}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1269
								// 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
  1270
								// 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
  1271
								else if ( !rel.changed ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1272
									delete dit.changed[ attr ];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1273
								}
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
							else if ( changed ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1276
								dit._attributeChangeFired = true;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1277
							}
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
						changed && Backbone.Model.prototype.trigger.apply( dit, args );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1281
					});
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
			else if ( eventName === 'destroy' ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1285
				Backbone.Model.prototype.trigger.apply( this, arguments );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1286
				Backbone.Relational.store.unregister( this );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1287
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1288
			else {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1289
				Backbone.Model.prototype.trigger.apply( this, arguments );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1290
			}
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
			return this;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1293
		},
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
		 * 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
  1297
		 * 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
  1298
		 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1299
		initializeRelations: function( options ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1300
			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
  1301
			this._relations = {};
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1302
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1303
			_.each( this.relations || [], function( rel ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1304
				Backbone.Relational.store.initializeRelation( this, rel, options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1305
			}, this );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1306
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1307
			this._isInitialized = true;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1308
			this.release();
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1309
			this.processQueue();
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1310
		},
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
		 * 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
  1314
		 * (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
  1315
		 * @param {Object} [changedAttrs]
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1316
		 * @param {Object} [options]
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1317
		 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1318
		updateRelations: function( changedAttrs, options ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1319
			if ( this._isInitialized && !this.isLocked() ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1320
				_.each( this._relations, function( rel ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1321
					if ( !changedAttrs || ( rel.keySource in changedAttrs || rel.key in changedAttrs ) ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1322
						// 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
  1323
						var value = this.attributes[ rel.keySource ] || this.attributes[ rel.key ],
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1324
							attr = changedAttrs && ( changedAttrs[ rel.keySource ] || changedAttrs[ rel.key ] );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1325
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1326
						// 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
  1327
						// 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
  1328
						if ( rel.related !== value || ( value === null && attr === null ) ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1329
							this.trigger( 'relational:change:' + rel.key, this, value, options || {} );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1330
						}
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
					// 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
  1334
					if ( rel.keySource !== rel.key ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1335
						delete this.attributes[ rel.keySource ];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1336
					}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1337
				}, this );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1338
			}
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
		 * 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
  1343
		 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1344
		queue: function( func ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1345
			this._queue.add( func );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1346
		},
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
		 * Process _queue
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1350
		 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1351
		processQueue: function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1352
			if ( this._isInitialized && !this._deferProcessing && this._queue.isBlocked() ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1353
				this._queue.unblock();
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1354
			}
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
		 * Get a specific relation.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1359
		 * @param {string} attr The relation key to look for.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1360
		 * @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
  1361
		 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1362
		getRelation: function( attr ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1363
			return this._relations[ attr ];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1364
		},
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
		 * Get all of the created relations.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1368
		 * @return {Backbone.Relation[]}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1369
		 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1370
		getRelations: function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1371
			return _.values( this._relations );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1372
		},
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
		 * 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
  1377
		 * @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
  1378
		 * @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
  1379
		 * @return {Array} An array of ids that need to be fetched.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1380
		 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1381
		getIdsToFetch: function( attr, refresh ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1382
			var rel = attr instanceof Backbone.Relation ? attr : this.getRelation( attr ),
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1383
				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
  1384
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1385
			// 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
  1386
			if ( refresh ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1387
				var models = rel.related && ( rel.related.models || [ rel.related ] );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1388
				_.each( models, function( model ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1389
					if ( model.id || model.id === 0 ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1390
						ids.push( model.id );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1391
					}
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
			return ids;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1396
		},
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
		 * 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
  1400
		 * 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
  1401
		 * @param {string} attr The relation key to fetch models for.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1402
		 * @param {Object} [options] Options for 'Backbone.Model.fetch' and 'Backbone.sync'.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1403
		 * @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
  1404
		 * @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
  1405
		 *  contents of `attr`.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1406
		 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1407
		getAsync: function( attr, options ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1408
			// Set default `options` for fetch
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1409
			options = _.extend( { add: true, remove: false, refresh: false }, options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1410
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1411
			var dit = this,
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1412
				requests = [],
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1413
				rel = this.getRelation( attr ),
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1414
				idsToFetch = rel && this.getIdsToFetch( rel, options.refresh ),
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1415
				coll = rel.related instanceof Backbone.Collection ? rel.related : rel.relatedCollection;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1416
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1417
			if ( idsToFetch && idsToFetch.length ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1418
				var models = [],
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1419
					createdModels = [],
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1420
					setUrl,
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1421
					createModels = function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1422
						// 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
  1423
						models = _.map( idsToFetch, function( id ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1424
							var model = rel.relatedModel.findModel( id );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1425
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1426
							if ( !model ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1427
								var attrs = {};
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1428
								attrs[ rel.relatedModel.prototype.idAttribute ] = id;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1429
								model = rel.relatedModel.findOrCreate( attrs, options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1430
								createdModels.push( model );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1431
							}
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
							return model;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1434
						}, this );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1435
					};
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
				// 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
  1438
				// 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
  1439
				// 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
  1440
				// 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
  1441
				if ( coll instanceof Backbone.Collection && _.isFunction( coll.url ) ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1442
					var defaultUrl = coll.url();
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1443
					setUrl = coll.url( idsToFetch );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1444
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1445
					if ( setUrl === defaultUrl ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1446
						createModels();
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1447
						setUrl = coll.url( models );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1448
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1449
						if ( setUrl === defaultUrl ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1450
							setUrl = null;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1451
						}
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
				if ( setUrl ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1456
					// Do a single request to fetch all models
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1457
					var opts = _.defaults(
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1458
						{
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1459
							error: function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1460
								_.each( createdModels, function( model ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1461
									model.trigger( 'destroy', model, model.collection, options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1462
								});
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
								options.error && options.error.apply( models, arguments );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1465
							},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1466
							url: setUrl
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1467
						},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1468
						options
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1469
					);
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
					requests = [ coll.fetch( opts ) ];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1472
				}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1473
				else {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1474
					// Make a request per model to fetch
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1475
					if  ( !models.length ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1476
						createModels();
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1477
					}
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
					requests = _.map( models, function( model ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1480
						var opts = _.defaults(
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1481
							{
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1482
								error: function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1483
									if ( _.contains( createdModels, model ) ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1484
										model.trigger( 'destroy', model, model.collection, options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1485
									}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1486
									options.error && options.error.apply( models, arguments );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1487
								}
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
							options
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1490
						);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1491
						return model.fetch( opts );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1492
					}, this );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1493
				}
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
498
08d121184a38 upgrade libs
ymh <ymh.work@gmail.com>
parents: 442
diff changeset
  1496
			return this.deferArray(requests).then(
442
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1497
				function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1498
					return Backbone.Model.prototype.get.call( dit, attr );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1499
				}
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
		},
498
08d121184a38 upgrade libs
ymh <ymh.work@gmail.com>
parents: 442
diff changeset
  1502
		
08d121184a38 upgrade libs
ymh <ymh.work@gmail.com>
parents: 442
diff changeset
  1503
		deferArray: function(deferArray) {
08d121184a38 upgrade libs
ymh <ymh.work@gmail.com>
parents: 442
diff changeset
  1504
			return Backbone.$.when.apply(null, deferArray);
08d121184a38 upgrade libs
ymh <ymh.work@gmail.com>
parents: 442
diff changeset
  1505
		},
442
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
		set: function( key, value, options ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1508
			Backbone.Relational.eventQueue.block();
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1509
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1510
			// 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
  1511
			var attributes,
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1512
				result;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1513
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1514
			if ( _.isObject( key ) || key == null ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1515
				attributes = key;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1516
				options = value;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1517
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1518
			else {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1519
				attributes = {};
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1520
				attributes[ key ] = value;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1521
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1522
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1523
			try {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1524
				var id = this.id,
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1525
					newId = attributes && this.idAttribute in attributes && attributes[ this.idAttribute ];
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
				// 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
  1528
				Backbone.Relational.store.checkId( this, newId );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1529
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1530
				result = Backbone.Model.prototype.set.apply( this, arguments );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1531
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1532
				// 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
  1533
				if ( !this._isInitialized && !this.isLocked() ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1534
					this.constructor.initializeModelHierarchy();
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1535
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1536
					// 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
  1537
					if ( newId || newId === 0 ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1538
						Backbone.Relational.store.register( this );
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
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1541
					this.initializeRelations( options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1542
				}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1543
				// The store should know about an `id` update asap
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1544
				else if ( newId && newId !== id ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1545
					Backbone.Relational.store.update( this );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1546
				}
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
				if ( attributes ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1549
					this.updateRelations( attributes, options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1550
				}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1551
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1552
			finally {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1553
				// Try to run the global queue holding external events
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1554
				Backbone.Relational.eventQueue.unblock();
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
			return result;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1558
		},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1559
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1560
		clone: function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1561
			var attributes = _.clone( this.attributes );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1562
			if ( !_.isUndefined( attributes[ this.idAttribute ] ) ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1563
				attributes[ this.idAttribute ] = null;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1564
			}
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
			_.each( this.getRelations(), function( rel ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1567
				delete attributes[ rel.key ];
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
			return new this.constructor( attributes );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1571
		},
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
		/**
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1574
		 * Convert relations to JSON, omits them when required
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1575
		 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1576
		toJSON: function( options ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1577
			// 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
  1578
			if ( this.isLocked() ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1579
				return this.id;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1580
			}
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
			this.acquire();
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1583
			var json = Backbone.Model.prototype.toJSON.call( this, options );
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
			if ( this.constructor._superModel && !( this.constructor._subModelTypeAttribute in json ) ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1586
				json[ this.constructor._subModelTypeAttribute ] = this.constructor._subModelTypeValue;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1587
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1588
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1589
			_.each( this._relations, function( rel ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1590
				var related = json[ rel.key ],
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1591
					includeInJSON = rel.options.includeInJSON,
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1592
					value = null;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1593
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1594
				if ( includeInJSON === true ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1595
					if ( related && _.isFunction( related.toJSON ) ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1596
						value = related.toJSON( options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1597
					}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1598
				}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1599
				else if ( _.isString( includeInJSON ) ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1600
					if ( related instanceof Backbone.Collection ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1601
						value = related.pluck( 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
					else if ( related instanceof Backbone.Model ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1604
						value = related.get( includeInJSON );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1605
					}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1606
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1607
					// 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
  1608
					if ( includeInJSON === rel.relatedModel.prototype.idAttribute ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1609
						if ( rel instanceof Backbone.HasMany ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1610
							value = value.concat( rel.keyIds );
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
						else if ( rel instanceof Backbone.HasOne ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1613
							value = value || rel.keyId;
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
							if ( !value && !_.isObject( rel.keyContents ) ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1616
								value = rel.keyContents || null;
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
						}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1619
					}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1620
				}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1621
				else if ( _.isArray( includeInJSON ) ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1622
					if ( related instanceof Backbone.Collection ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1623
						value = [];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1624
						related.each( function( model ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1625
							var curJson = {};
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1626
							_.each( includeInJSON, function( key ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1627
								curJson[ key ] = model.get( key );
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
							value.push( curJson );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1630
						});
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1631
					}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1632
					else if ( related instanceof Backbone.Model ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1633
						value = {};
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1634
						_.each( includeInJSON, function( key ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1635
							value[ key ] = related.get( key );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1636
						});
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1637
					}
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
				else {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1640
					delete json[ rel.key ];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1641
				}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1642
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1643
				// 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
  1644
				// 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
  1645
				// 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
  1646
				if ( value === null && options && options.wait ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1647
					value = related;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1648
				}
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
				if ( includeInJSON ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1651
					json[ rel.keyDestination ] = value;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1652
				}
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
				if ( rel.keyDestination !== rel.key ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1655
					delete json[ rel.key ];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1656
				}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1657
			});
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
			this.release();
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1660
			return json;
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
	{
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1664
		/**
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
		 * @param superModel
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1667
		 * @returns {Backbone.RelationalModel.constructor}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1668
		 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1669
		setup: function( superModel ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1670
			// 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
  1671
			// 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
  1672
			this.prototype.relations = ( this.prototype.relations || [] ).slice( 0 );
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
			this._subModels = {};
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1675
			this._superModel = null;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1676
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1677
			// If this model has 'subModelTypes' itself, remember them in the store
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1678
			if ( this.prototype.hasOwnProperty( 'subModelTypes' ) ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1679
				Backbone.Relational.store.addSubModels( this.prototype.subModelTypes, this );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1680
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1681
			// The 'subModelTypes' property should not be inherited, so reset it.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1682
			else {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1683
				this.prototype.subModelTypes = null;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1684
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1685
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1686
			// Initialize all reverseRelations that belong to this new model.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1687
			_.each( this.prototype.relations || [], function( rel ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1688
				if ( !rel.model ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1689
					rel.model = this;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1690
				}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1691
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1692
				if ( rel.reverseRelation && rel.model === this ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1693
					var preInitialize = true;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1694
					if ( _.isString( rel.relatedModel ) ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1695
						/**
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1696
						 * The related model might not be defined for two reasons
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1697
						 *  1. it is related to itself
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1698
						 *  2. it never gets defined, e.g. a typo
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1699
						 *  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
  1700
						 * 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
  1701
						 * 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
  1702
						 * 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
  1703
						 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1704
						var relatedModel = Backbone.Relational.store.getObjectByName( rel.relatedModel );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1705
						preInitialize = relatedModel && ( relatedModel.prototype instanceof Backbone.RelationalModel );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1706
					}
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
					if ( preInitialize ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1709
						Backbone.Relational.store.initializeRelation( null, 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
					else if ( _.isString( rel.relatedModel ) ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1712
						Backbone.Relational.store.addOrphanRelation( rel );
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
				}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1715
			}, this );
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
			return this;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1718
		},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1719
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1720
		/**
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1721
		 * Create a 'Backbone.Model' instance based on 'attributes'.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1722
		 * @param {Object} attributes
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1723
		 * @param {Object} [options]
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1724
		 * @return {Backbone.Model}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1725
		 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1726
		build: function( attributes, options ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1727
			// '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
  1728
			this.initializeModelHierarchy();
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
			// Determine what type of (sub)model should be built if applicable.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1731
			var model = this._findSubModelType( this, attributes ) || this;
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
			return new model( attributes, options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1734
		},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1735
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1736
		/**
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1737
		 * Determines what type of (sub)model should be built if applicable.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1738
		 * Looks up the proper subModelType in 'this._subModels', recursing into
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1739
		 * types until a match is found.  Returns the applicable 'Backbone.Model'
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1740
		 * or null if no match is found.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1741
		 * @param {Backbone.Model} type
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1742
		 * @param {Object} attributes
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1743
		 * @return {Backbone.Model}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1744
		 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1745
		_findSubModelType: function( type, attributes ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1746
			if ( type._subModels && type.prototype.subModelTypeAttribute in attributes ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1747
				var subModelTypeAttribute = attributes[ type.prototype.subModelTypeAttribute ];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1748
				var subModelType = type._subModels[ subModelTypeAttribute ];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1749
				if ( subModelType ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1750
					return subModelType;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1751
				}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1752
				else {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1753
					// Recurse into subModelTypes to find a match
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1754
					for ( subModelTypeAttribute in type._subModels ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1755
						subModelType = this._findSubModelType( type._subModels[ subModelTypeAttribute ], attributes );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1756
						if ( subModelType ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1757
							return subModelType;
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
				}
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
			return null;
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
		/**
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1767
		 *
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1768
		 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1769
		initializeModelHierarchy: function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1770
			// Inherit any relations that have been defined in the parent model.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1771
			this.inheritRelations();
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1772
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1773
			// 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
  1774
			// haven't been resolved yet.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1775
			if ( this.prototype.subModelTypes ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1776
				var resolvedSubModels = _.keys( this._subModels );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1777
				var unresolvedSubModels = _.omit( this.prototype.subModelTypes, resolvedSubModels );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1778
				_.each( unresolvedSubModels, function( subModelTypeName ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1779
					var subModelType = Backbone.Relational.store.getObjectByName( subModelTypeName );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1780
					subModelType && subModelType.initializeModelHierarchy();
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
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1783
		},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1784
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1785
		inheritRelations: function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1786
			// Bail out if we've been here before.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1787
			if ( !_.isUndefined( this._superModel ) && !_.isNull( this._superModel ) ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1788
				return;
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
			// Try to initialize the _superModel.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1791
			Backbone.Relational.store.setupSuperModel( this );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1792
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1793
			// 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
  1794
			// (due to a redefinition of 'relations').
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1795
			if ( this._superModel ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1796
				// 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
  1797
				// 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
  1798
				// 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
  1799
				this._superModel.inheritRelations();
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1800
				if ( this._superModel.prototype.relations ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1801
					// 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
  1802
					var inheritedRelations = _.filter( this._superModel.prototype.relations || [], function( superRel ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1803
						return !_.any( this.prototype.relations || [], function( rel ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1804
							return superRel.relatedModel === rel.relatedModel && superRel.key === rel.key;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1805
						}, this );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1806
					}, this );
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
					this.prototype.relations = inheritedRelations.concat( this.prototype.relations );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1809
				}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1810
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1811
			// 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
  1812
			// isUndefined/isNull check next time.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1813
			else {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1814
				this._superModel = false;
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
		},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1817
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1818
		/**
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1819
		 * Find an instance of `this` type in 'Backbone.Relational.store'.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1820
		 * 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
  1821
		 * - 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
  1822
		 * - 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
  1823
		 * @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
  1824
		 * @param {Object} [options]
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1825
		 * @param {Boolean} [options.create=true]
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1826
		 * @param {Boolean} [options.merge=true]
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1827
		 * @param {Boolean} [options.parse=false]
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1828
		 * @return {Backbone.RelationalModel}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1829
		 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1830
		findOrCreate: function( attributes, options ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1831
			options || ( options = {} );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1832
			var parsedAttributes = ( _.isObject( attributes ) && options.parse && this.prototype.parse ) ?
498
08d121184a38 upgrade libs
ymh <ymh.work@gmail.com>
parents: 442
diff changeset
  1833
				this.prototype.parse( _.clone( attributes ), options ) : attributes;
442
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1834
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1835
			// 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
  1836
			// 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
  1837
			var model = this.findModel( parsedAttributes );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1838
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1839
			// 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
  1840
			// If not, create an instance (unless 'options.create' is false).
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1841
			if ( _.isObject( attributes ) ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1842
				if ( model && options.merge !== false ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1843
					// 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
  1844
					delete options.collection;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1845
					delete options.url;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1846
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1847
					model.set( parsedAttributes, 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
				else if ( !model && options.create !== false ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1850
					model = this.build( parsedAttributes, _.defaults( { parse: false }, options ) );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1851
				}
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
			return model;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1855
		},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1856
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1857
		/**
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1858
		 * Find an instance of `this` type in 'Backbone.Relational.store'.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1859
		 * - 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
  1860
		 * - 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
  1861
		 * @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
  1862
		 * @param {Object} [options]
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1863
		 * @param {Boolean} [options.merge=true]
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1864
		 * @param {Boolean} [options.parse=false]
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1865
		 * @return {Backbone.RelationalModel}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1866
		 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1867
		find: function( attributes, options ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1868
			options || ( options = {} );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1869
			options.create = false;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1870
			return this.findOrCreate( attributes, options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1871
		},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1872
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1873
		/**
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1874
		 * 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
  1875
		 * 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
  1876
		 * @param {Object} attributes
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1877
		 * @returns {Backbone.RelationalModel}
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
		findModel: function( attributes ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1880
			return Backbone.Relational.store.find( this, attributes );
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
	_.extend( Backbone.RelationalModel.prototype, Backbone.Semaphore );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1884
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1885
	/**
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1886
	 * 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
  1887
	 * if the collection.model has subModels.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1888
	 * 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
  1889
	 * (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
  1890
	 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1891
	Backbone.Collection.prototype.__prepareModel = Backbone.Collection.prototype._prepareModel;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1892
	Backbone.Collection.prototype._prepareModel = function( attrs, options ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1893
		var model;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1894
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1895
		if ( attrs instanceof Backbone.Model ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1896
			if ( !attrs.collection ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1897
				attrs.collection = this;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1898
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1899
			model = attrs;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1900
		}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1901
		else {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1902
			options = options ? _.clone( options ) : {};
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1903
			options.collection = this;
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
			if ( typeof this.model.findOrCreate !== 'undefined' ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1906
				model = this.model.findOrCreate( 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
			else {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1909
				model = new this.model( attrs, options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1910
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1911
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1912
			if ( model && model.validationError ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1913
				this.trigger( 'invalid', this, attrs, options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1914
				model = false;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1915
			}
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
		return model;
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
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1921
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
	 * 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
  1924
	 * and update the existing models. Also, trigger 'relational:add'.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1925
	 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1926
	var set = Backbone.Collection.prototype.__set = Backbone.Collection.prototype.set;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1927
	Backbone.Collection.prototype.set = function( models, options ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1928
		// Short-circuit if this Collection doesn't hold RelationalModels
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1929
		if ( !( this.model.prototype instanceof Backbone.RelationalModel ) ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1930
			return set.call( this, models, options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1931
		}
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
		if ( options && options.parse ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1934
			models = this.parse( models, options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1935
		}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1936
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1937
		var singular = !_.isArray( models ),
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1938
			newModels = [],
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1939
			toAdd = [],
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1940
			model = null;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1941
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1942
		models = singular ? ( models ? [ models ] : [] ) : _.clone( models );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1943
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1944
		//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
  1945
		for ( var i = 0; i < models.length; i++ ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1946
			model = models[i];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1947
			if ( !( model instanceof Backbone.Model ) ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1948
				model = Backbone.Collection.prototype._prepareModel.call( this, model, options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1949
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1950
			if ( model ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1951
				toAdd.push( model );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1952
				if ( !( this.get( model ) || this.get( model.cid ) ) ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1953
					newModels.push( model );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1954
				}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1955
				// 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
  1956
				// 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
  1957
				else if ( model.id !== null && model.id !== undefined ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1958
					this._byId[ model.id ] = model;
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
			}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1961
		}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1962
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1963
		// 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
  1964
		// 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
  1965
		toAdd = singular ? ( toAdd.length ? toAdd[ 0 ] : null ) : toAdd;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1966
		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
  1967
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1968
		for ( i = 0; i < newModels.length; i++ ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1969
			model = newModels[i];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1970
			// 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
  1971
			if ( this.get( model ) || this.get( model.cid ) ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1972
				this.trigger( 'relational:add', model, this, options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1973
			}
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
		return result;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1977
	};
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
	/**
498
08d121184a38 upgrade libs
ymh <ymh.work@gmail.com>
parents: 442
diff changeset
  1980
	 * Override 'Backbone.Collection._removeModels' to trigger 'relational:remove'.
442
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1981
	 */
498
08d121184a38 upgrade libs
ymh <ymh.work@gmail.com>
parents: 442
diff changeset
  1982
	var _removeModels = Backbone.Collection.prototype.___removeModels = Backbone.Collection.prototype._removeModels;
08d121184a38 upgrade libs
ymh <ymh.work@gmail.com>
parents: 442
diff changeset
  1983
	Backbone.Collection.prototype._removeModels = function( models, options ) {
442
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1984
		// Short-circuit if this Collection doesn't hold RelationalModels
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1985
		if ( !( this.model.prototype instanceof Backbone.RelationalModel ) ) {
498
08d121184a38 upgrade libs
ymh <ymh.work@gmail.com>
parents: 442
diff changeset
  1986
			return _removeModels.call( this, models, options );
442
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1987
		}
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1988
498
08d121184a38 upgrade libs
ymh <ymh.work@gmail.com>
parents: 442
diff changeset
  1989
		var toRemove = [];
442
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1990
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1991
		//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
  1992
		_.each( models, function( model ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1993
			model = this.get( model ) || ( model && this.get( model.cid ) );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1994
			model && toRemove.push( model );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1995
		}, this );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1996
498
08d121184a38 upgrade libs
ymh <ymh.work@gmail.com>
parents: 442
diff changeset
  1997
		var result = _removeModels.call( this, toRemove, options );
442
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1998
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1999
		_.each( toRemove, function( model ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2000
			this.trigger( 'relational:remove', model, this, options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2001
		}, this );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2002
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2003
		return result;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2004
	};
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
	 * Override 'Backbone.Collection.reset' to trigger 'relational:reset'.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2008
	 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2009
	var reset = Backbone.Collection.prototype.__reset = Backbone.Collection.prototype.reset;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2010
	Backbone.Collection.prototype.reset = function( models, options ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2011
		options = _.extend( { merge: true }, options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2012
		var result = reset.call( this, models, options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2013
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2014
		if ( this.model.prototype instanceof Backbone.RelationalModel ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2015
			this.trigger( 'relational:reset', this, options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2016
		}
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
		return result;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2019
	};
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
	 * Override 'Backbone.Collection.sort' to trigger 'relational:reset'.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2023
	 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2024
	var sort = Backbone.Collection.prototype.__sort = Backbone.Collection.prototype.sort;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2025
	Backbone.Collection.prototype.sort = function( options ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2026
		var result = sort.call( this, options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2027
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2028
		if ( this.model.prototype instanceof Backbone.RelationalModel ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2029
			this.trigger( 'relational:reset', this, options );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2030
		}
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
		return result;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2033
	};
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
	 * 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
  2037
	 * are ready.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2038
	 */
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2039
	var trigger = Backbone.Collection.prototype.__trigger = Backbone.Collection.prototype.trigger;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2040
	Backbone.Collection.prototype.trigger = function( eventName ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2041
		// Short-circuit if this Collection doesn't hold RelationalModels
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2042
		if ( !( this.model.prototype instanceof Backbone.RelationalModel ) ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2043
			return trigger.apply( this, arguments );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2044
		}
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
		if ( eventName === 'add' || eventName === 'remove' || eventName === 'reset' || eventName === 'sort' ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2047
			var dit = this,
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2048
				args = arguments;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2049
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2050
			if ( _.isObject( args[ 3 ] ) ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2051
				args = _.toArray( args );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2052
				// the fourth argument is the option object.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2053
				// 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
  2054
				args[ 3 ] = _.clone( args[ 3 ] );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2055
			}
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
			Backbone.Relational.eventQueue.add( function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2058
				trigger.apply( dit, args );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2059
			});
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
		else {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2062
			trigger.apply( this, arguments );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2063
		}
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
		return this;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2066
	};
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
	// Override .extend() to automatically call .setup()
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2069
	Backbone.RelationalModel.extend = function( protoProps, classProps ) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2070
		var child = Backbone.Model.extend.call( this, protoProps, classProps );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2071
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2072
		child.setup( this );
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2073
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2074
		return child;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2075
	};
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2076
}));