ember-source 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of ember-source might be problematic. Click here for more details.
- data/dist/ember-data-deps.js +1506 -1309
- data/dist/ember-data-deps.min.js +5 -5
- data/dist/ember-data-deps.prod.js +1499 -1302
- data/dist/ember-debug.js +2 -2
- data/dist/ember-old-router.js +2864 -4816
- data/dist/ember-old-router.min.js +8 -9
- data/dist/ember-old-router.prod.js +2849 -4801
- data/dist/ember-runtime.js +1505 -1308
- data/dist/ember-runtime.min.js +5 -5
- data/dist/ember-runtime.prod.js +1492 -1295
- data/dist/ember-spade.js +1 -1
- data/dist/ember-template-compiler.js +3 -3
- data/dist/ember-template-compiler.min.js +2 -2
- data/dist/ember-template-compiler.prod.js +1 -1
- data/dist/ember-tests.js +1 -1
- data/dist/ember.js +2746 -4636
- data/dist/ember.min.js +8 -9
- data/dist/ember.prod.js +2750 -4640
- metadata +2 -2
data/dist/ember-runtime.js
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
// Version: v1.0.0-rc.1-
|
2
|
-
// Last commit:
|
1
|
+
// Version: v1.0.0-rc.1-188-gb6bb967
|
2
|
+
// Last commit: b6bb967 (2013-03-16 18:09:42 -0700)
|
3
3
|
|
4
4
|
|
5
5
|
(function() {
|
@@ -150,8 +150,8 @@ Ember.deprecateFunc = function(message, func) {
|
|
150
150
|
|
151
151
|
})();
|
152
152
|
|
153
|
-
// Version: v1.0.0-rc.1-
|
154
|
-
// Last commit:
|
153
|
+
// Version: v1.0.0-rc.1-188-gb6bb967
|
154
|
+
// Last commit: b6bb967 (2013-03-16 18:09:42 -0700)
|
155
155
|
|
156
156
|
|
157
157
|
(function() {
|
@@ -418,6 +418,58 @@ Ember.merge = function(original, updates) {
|
|
418
418
|
}
|
419
419
|
};
|
420
420
|
|
421
|
+
/**
|
422
|
+
Returns true if the passed value is null or undefined. This avoids errors
|
423
|
+
from JSLint complaining about use of ==, which can be technically
|
424
|
+
confusing.
|
425
|
+
|
426
|
+
```javascript
|
427
|
+
Ember.isNone(); // true
|
428
|
+
Ember.isNone(null); // true
|
429
|
+
Ember.isNone(undefined); // true
|
430
|
+
Ember.isNone(''); // false
|
431
|
+
Ember.isNone([]); // false
|
432
|
+
Ember.isNone(function(){}); // false
|
433
|
+
```
|
434
|
+
|
435
|
+
@method isNone
|
436
|
+
@for Ember
|
437
|
+
@param {Object} obj Value to test
|
438
|
+
@return {Boolean}
|
439
|
+
*/
|
440
|
+
Ember.isNone = function(obj) {
|
441
|
+
return obj === null || obj === undefined;
|
442
|
+
};
|
443
|
+
Ember.none = Ember.deprecateFunc("Ember.none is deprecated. Please use Ember.isNone instead.", Ember.isNone);
|
444
|
+
|
445
|
+
/**
|
446
|
+
Verifies that a value is `null` or an empty string, empty array,
|
447
|
+
or empty function.
|
448
|
+
|
449
|
+
Constrains the rules on `Ember.isNone` by returning false for empty
|
450
|
+
string and empty arrays.
|
451
|
+
|
452
|
+
```javascript
|
453
|
+
Ember.isEmpty(); // true
|
454
|
+
Ember.isEmpty(null); // true
|
455
|
+
Ember.isEmpty(undefined); // true
|
456
|
+
Ember.isEmpty(''); // true
|
457
|
+
Ember.isEmpty([]); // true
|
458
|
+
Ember.isEmpty('Adam Hawkins'); // false
|
459
|
+
Ember.isEmpty([0,1,2]); // false
|
460
|
+
```
|
461
|
+
|
462
|
+
@method isEmpty
|
463
|
+
@for Ember
|
464
|
+
@param {Object} obj Value to test
|
465
|
+
@return {Boolean}
|
466
|
+
*/
|
467
|
+
Ember.isEmpty = function(obj) {
|
468
|
+
return obj === null || obj === undefined || (obj.length === 0 && typeof obj !== 'function') || (typeof obj === 'object' && Ember.get(obj, 'length') === 0);
|
469
|
+
};
|
470
|
+
Ember.empty = Ember.deprecateFunc("Ember.empty is deprecated. Please use Ember.isEmpty instead.", Ember.isEmpty) ;
|
471
|
+
|
472
|
+
|
421
473
|
})();
|
422
474
|
|
423
475
|
|
@@ -1761,7 +1813,7 @@ var MapWithDefault = Ember.MapWithDefault = function(options) {
|
|
1761
1813
|
@static
|
1762
1814
|
@param [options]
|
1763
1815
|
@param {anything} [options.defaultValue]
|
1764
|
-
@return {Ember.MapWithDefault|Ember.Map} If options are passed, returns
|
1816
|
+
@return {Ember.MapWithDefault|Ember.Map} If options are passed, returns
|
1765
1817
|
`Ember.MapWithDefault` otherwise returns `Ember.Map`
|
1766
1818
|
*/
|
1767
1819
|
MapWithDefault.create = function(options) {
|
@@ -1824,7 +1876,7 @@ var FIRST_KEY = /^([^\.\*]+)/;
|
|
1824
1876
|
// ..........................................................
|
1825
1877
|
// GET AND SET
|
1826
1878
|
//
|
1827
|
-
// If we are on a platform that supports accessors we can
|
1879
|
+
// If we are on a platform that supports accessors we can use those.
|
1828
1880
|
// Otherwise simulate accessors by looking up the property directly on the
|
1829
1881
|
// object.
|
1830
1882
|
|
@@ -1835,7 +1887,7 @@ var FIRST_KEY = /^([^\.\*]+)/;
|
|
1835
1887
|
|
1836
1888
|
If you plan to run on IE8 and older browsers then you should use this
|
1837
1889
|
method anytime you want to retrieve a property on an object that you don't
|
1838
|
-
know for sure is private. (Properties beginning with an underscore '_'
|
1890
|
+
know for sure is private. (Properties beginning with an underscore '_'
|
1839
1891
|
are considered private.)
|
1840
1892
|
|
1841
1893
|
On all newer browsers, you only need to use this method to retrieve
|
@@ -1897,7 +1949,7 @@ get = function get(obj, keyName) {
|
|
1897
1949
|
|
1898
1950
|
If you plan to run on IE8 and older browsers then you should use this
|
1899
1951
|
method anytime you want to set a property on an object that you don't
|
1900
|
-
know for sure is private. (Properties beginning with an underscore '_'
|
1952
|
+
know for sure is private. (Properties beginning with an underscore '_'
|
1901
1953
|
are considered private.)
|
1902
1954
|
|
1903
1955
|
On all newer browsers, you only need to use this method to set
|
@@ -2128,11 +2180,8 @@ Ember.isGlobalPath = function(path) {
|
|
2128
2180
|
@module ember-metal
|
2129
2181
|
*/
|
2130
2182
|
|
2131
|
-
var
|
2132
|
-
META_KEY = Ember.META_KEY,
|
2133
|
-
EMPTY_META = Ember.EMPTY_META,
|
2183
|
+
var META_KEY = Ember.META_KEY,
|
2134
2184
|
metaFor = Ember.meta,
|
2135
|
-
o_create = Ember.create,
|
2136
2185
|
objectDefineProperty = Ember.platform.defineProperty;
|
2137
2186
|
|
2138
2187
|
var MANDATORY_SETTER = Ember.ENV.MANDATORY_SETTER;
|
@@ -2552,7 +2601,6 @@ var guidFor = Ember.guidFor, // utils.js
|
|
2552
2601
|
META_KEY = Ember.META_KEY, // utils.js
|
2553
2602
|
// circular reference observer depends on Ember.watch
|
2554
2603
|
// we should move change events to this file or its own property_events.js
|
2555
|
-
notifyObservers = Ember.notifyObservers, // observer.js
|
2556
2604
|
forEach = Ember.ArrayPolyfills.forEach, // array.js
|
2557
2605
|
FIRST_KEY = /^([^\.\*]+)/,
|
2558
2606
|
IS_PATH = /[\.\*]/;
|
@@ -3092,7 +3140,7 @@ Ember.finishChains = function(obj) {
|
|
3092
3140
|
@param {String} keyName The property key (or path) that will change.
|
3093
3141
|
@return {void}
|
3094
3142
|
*/
|
3095
|
-
function propertyWillChange(obj, keyName
|
3143
|
+
function propertyWillChange(obj, keyName) {
|
3096
3144
|
var m = metaFor(obj, false),
|
3097
3145
|
watching = m.watching[keyName] > 0 || keyName === 'length',
|
3098
3146
|
proto = m.proto,
|
@@ -3200,7 +3248,6 @@ Ember.warn("The CP_DEFAULT_CACHEABLE flag has been removed and computed properti
|
|
3200
3248
|
var get = Ember.get,
|
3201
3249
|
set = Ember.set,
|
3202
3250
|
metaFor = Ember.meta,
|
3203
|
-
guidFor = Ember.guidFor,
|
3204
3251
|
a_slice = [].slice,
|
3205
3252
|
o_create = Ember.create,
|
3206
3253
|
META_KEY = Ember.META_KEY,
|
@@ -3236,20 +3283,8 @@ function keysForDep(obj, depsMeta, depKey) {
|
|
3236
3283
|
return keys;
|
3237
3284
|
}
|
3238
3285
|
|
3239
|
-
/* return obj[META_KEY].deps */
|
3240
3286
|
function metaForDeps(obj, meta) {
|
3241
|
-
|
3242
|
-
// If the current object has no dependencies...
|
3243
|
-
if (!deps) {
|
3244
|
-
// initialize the dependencies with a pointer back to
|
3245
|
-
// the current object
|
3246
|
-
deps = meta.deps = {};
|
3247
|
-
} else if (!meta.hasOwnProperty('deps')) {
|
3248
|
-
// otherwise if the dependencies are inherited from the
|
3249
|
-
// object's superclass, clone the deps
|
3250
|
-
deps = meta.deps = o_create(deps);
|
3251
|
-
}
|
3252
|
-
return deps;
|
3287
|
+
return keysForDep(obj, meta, 'deps');
|
3253
3288
|
}
|
3254
3289
|
|
3255
3290
|
function addDependentKeys(desc, obj, keyName, meta) {
|
@@ -3302,8 +3337,10 @@ function removeDependentKeys(desc, obj, keyName, meta) {
|
|
3302
3337
|
*/
|
3303
3338
|
function ComputedProperty(func, opts) {
|
3304
3339
|
this.func = func;
|
3340
|
+
|
3305
3341
|
this._cacheable = (opts && opts.cacheable !== undefined) ? opts.cacheable : true;
|
3306
3342
|
this._dependentKeys = opts && opts.dependentKeys;
|
3343
|
+
this._readOnly = opts && (opts.readOnly !== undefined || !!opts.readOnly);
|
3307
3344
|
}
|
3308
3345
|
|
3309
3346
|
Ember.ComputedProperty = ComputedProperty;
|
@@ -3358,6 +3395,28 @@ ComputedPropertyPrototype.volatile = function() {
|
|
3358
3395
|
return this.cacheable(false);
|
3359
3396
|
};
|
3360
3397
|
|
3398
|
+
/**
|
3399
|
+
Call on a computed property to set it into read-only mode. When in this
|
3400
|
+
mode the computed property will throw an error when set.
|
3401
|
+
|
3402
|
+
```javascript
|
3403
|
+
MyApp.person = Ember.Object.create({
|
3404
|
+
guid: function() {
|
3405
|
+
return 'guid-guid-guid';
|
3406
|
+
}.property().readOnly()
|
3407
|
+
});
|
3408
|
+
|
3409
|
+
MyApp.person.set('guid', 'new-guid'); // will throw an exception
|
3410
|
+
```
|
3411
|
+
|
3412
|
+
@method readOnly
|
3413
|
+
@chainable
|
3414
|
+
*/
|
3415
|
+
ComputedPropertyPrototype.readOnly = function(readOnly) {
|
3416
|
+
this._readOnly = readOnly === undefined || !!readOnly;
|
3417
|
+
return this;
|
3418
|
+
};
|
3419
|
+
|
3361
3420
|
/**
|
3362
3421
|
Sets the dependent keys on this computed property. Pass any number of
|
3363
3422
|
arguments containing key paths that this computed property depends on.
|
@@ -3482,9 +3541,14 @@ ComputedPropertyPrototype.set = function(obj, keyName, value) {
|
|
3482
3541
|
cache = meta.cache,
|
3483
3542
|
cachedValue, ret;
|
3484
3543
|
|
3544
|
+
if (this._readOnly) {
|
3545
|
+
throw new Error('Cannot Set: ' + keyName + ' on: ' + obj.toString() );
|
3546
|
+
}
|
3547
|
+
|
3485
3548
|
this._suspended = obj;
|
3486
3549
|
|
3487
3550
|
try {
|
3551
|
+
|
3488
3552
|
if (cacheable && cache.hasOwnProperty(keyName)) {
|
3489
3553
|
cachedValue = cache[keyName];
|
3490
3554
|
hadCachedValue = true;
|
@@ -3575,6 +3639,10 @@ Ember.computed = function(func) {
|
|
3575
3639
|
func = a_slice.call(arguments, -1)[0];
|
3576
3640
|
}
|
3577
3641
|
|
3642
|
+
if ( typeof func !== "function" ) {
|
3643
|
+
throw new Error("Computed Property declared without a property function");
|
3644
|
+
}
|
3645
|
+
|
3578
3646
|
var cp = new ComputedProperty(func);
|
3579
3647
|
|
3580
3648
|
if (args) {
|
@@ -3615,6 +3683,18 @@ Ember.computed.not = function(dependentKey) {
|
|
3615
3683
|
});
|
3616
3684
|
};
|
3617
3685
|
|
3686
|
+
/**
|
3687
|
+
@method computed.none
|
3688
|
+
@for Ember
|
3689
|
+
@param {String} dependentKey
|
3690
|
+
*/
|
3691
|
+
Ember.computed.none = function(dependentKey) {
|
3692
|
+
return Ember.computed(dependentKey, function(key) {
|
3693
|
+
var val = get(this, dependentKey);
|
3694
|
+
return Ember.isNone(val);
|
3695
|
+
});
|
3696
|
+
};
|
3697
|
+
|
3618
3698
|
/**
|
3619
3699
|
@method computed.empty
|
3620
3700
|
@for Ember
|
@@ -3623,7 +3703,7 @@ Ember.computed.not = function(dependentKey) {
|
|
3623
3703
|
Ember.computed.empty = function(dependentKey) {
|
3624
3704
|
return Ember.computed(dependentKey, function(key) {
|
3625
3705
|
var val = get(this, dependentKey);
|
3626
|
-
return
|
3706
|
+
return Ember.isEmpty(val);
|
3627
3707
|
});
|
3628
3708
|
};
|
3629
3709
|
|
@@ -3641,15 +3721,16 @@ Ember.computed.bool = function(dependentKey) {
|
|
3641
3721
|
/**
|
3642
3722
|
@method computed.alias
|
3643
3723
|
@for Ember
|
3724
|
+
|
3644
3725
|
@param {String} dependentKey
|
3645
3726
|
*/
|
3646
3727
|
Ember.computed.alias = function(dependentKey) {
|
3647
3728
|
return Ember.computed(dependentKey, function(key, value){
|
3648
|
-
if (arguments.length
|
3649
|
-
return get(this, dependentKey);
|
3650
|
-
} else {
|
3729
|
+
if (arguments.length > 1) {
|
3651
3730
|
set(this, dependentKey, value);
|
3652
3731
|
return value;
|
3732
|
+
} else {
|
3733
|
+
return get(this, dependentKey);
|
3653
3734
|
}
|
3654
3735
|
});
|
3655
3736
|
};
|
@@ -3665,7 +3746,6 @@ Ember.computed.alias = function(dependentKey) {
|
|
3665
3746
|
|
3666
3747
|
var o_create = Ember.create,
|
3667
3748
|
metaFor = Ember.meta,
|
3668
|
-
metaPath = Ember.metaPath,
|
3669
3749
|
META_KEY = Ember.META_KEY;
|
3670
3750
|
|
3671
3751
|
/*
|
@@ -4238,7 +4318,7 @@ Ember.RunLoop = RunLoop;
|
|
4238
4318
|
|
4239
4319
|
```javascript
|
4240
4320
|
Ember.run(function(){
|
4241
|
-
// code to be execute within a RunLoop
|
4321
|
+
// code to be execute within a RunLoop
|
4242
4322
|
});
|
4243
4323
|
```
|
4244
4324
|
|
@@ -4254,8 +4334,7 @@ Ember.RunLoop = RunLoop;
|
|
4254
4334
|
@return {Object} return value from invoking the passed function.
|
4255
4335
|
*/
|
4256
4336
|
Ember.run = function(target, method) {
|
4257
|
-
var
|
4258
|
-
args = arguments;
|
4337
|
+
var args = arguments;
|
4259
4338
|
run.begin();
|
4260
4339
|
|
4261
4340
|
function tryable() {
|
@@ -4273,11 +4352,11 @@ var run = Ember.run;
|
|
4273
4352
|
/**
|
4274
4353
|
Begins a new RunLoop. Any deferred actions invoked after the begin will
|
4275
4354
|
be buffered until you invoke a matching call to `Ember.run.end()`. This is
|
4276
|
-
|
4355
|
+
a lower-level way to use a RunLoop instead of using `Ember.run()`.
|
4277
4356
|
|
4278
4357
|
```javascript
|
4279
4358
|
Ember.run.begin();
|
4280
|
-
// code to be execute within a RunLoop
|
4359
|
+
// code to be execute within a RunLoop
|
4281
4360
|
Ember.run.end();
|
4282
4361
|
```
|
4283
4362
|
|
@@ -4295,7 +4374,7 @@ Ember.run.begin = function() {
|
|
4295
4374
|
|
4296
4375
|
```javascript
|
4297
4376
|
Ember.run.begin();
|
4298
|
-
// code to be execute within a RunLoop
|
4377
|
+
// code to be execute within a RunLoop
|
4299
4378
|
Ember.run.end();
|
4300
4379
|
```
|
4301
4380
|
|
@@ -4319,9 +4398,9 @@ Ember.run.end = function() {
|
|
4319
4398
|
|
4320
4399
|
@property queues
|
4321
4400
|
@type Array
|
4322
|
-
@default ['sync', 'actions', 'destroy'
|
4401
|
+
@default ['sync', 'actions', 'destroy']
|
4323
4402
|
*/
|
4324
|
-
Ember.run.queues = ['sync', 'actions', 'destroy'
|
4403
|
+
Ember.run.queues = ['sync', 'actions', 'destroy'];
|
4325
4404
|
|
4326
4405
|
/**
|
4327
4406
|
Adds the passed target/method and any optional arguments to the named
|
@@ -4334,19 +4413,19 @@ Ember.run.queues = ['sync', 'actions', 'destroy', 'timers'];
|
|
4334
4413
|
the `run.queues` property.
|
4335
4414
|
|
4336
4415
|
```javascript
|
4337
|
-
Ember.run.schedule('timers', this, function(){
|
4338
|
-
// this will be executed at the end of the RunLoop, when timers are run
|
4339
|
-
console.log("scheduled on timers queue");
|
4340
|
-
});
|
4341
|
-
|
4342
4416
|
Ember.run.schedule('sync', this, function(){
|
4343
|
-
// this will be executed
|
4417
|
+
// this will be executed in the first RunLoop queue, when bindings are synced
|
4344
4418
|
console.log("scheduled on sync queue");
|
4345
4419
|
});
|
4346
4420
|
|
4421
|
+
Ember.run.schedule('actions', this, function(){
|
4422
|
+
// this will be executed in the 'actions' queue, after bindings have synced.
|
4423
|
+
console.log("scheduled on actions queue");
|
4424
|
+
});
|
4425
|
+
|
4347
4426
|
// Note the functions will be run in order based on the run queues order. Output would be:
|
4348
4427
|
// scheduled on sync queue
|
4349
|
-
// scheduled on
|
4428
|
+
// scheduled on actions queue
|
4350
4429
|
```
|
4351
4430
|
|
4352
4431
|
@method schedule
|
@@ -4372,7 +4451,7 @@ function autorun() {
|
|
4372
4451
|
|
4373
4452
|
// Used by global test teardown
|
4374
4453
|
Ember.run.hasScheduledTimers = function() {
|
4375
|
-
return !!(scheduledAutorun || scheduledLater
|
4454
|
+
return !!(scheduledAutorun || scheduledLater);
|
4376
4455
|
};
|
4377
4456
|
|
4378
4457
|
// Used by global test teardown
|
@@ -4385,10 +4464,6 @@ Ember.run.cancelTimers = function () {
|
|
4385
4464
|
clearTimeout(scheduledLater);
|
4386
4465
|
scheduledLater = null;
|
4387
4466
|
}
|
4388
|
-
if (scheduledNext) {
|
4389
|
-
clearTimeout(scheduledNext);
|
4390
|
-
scheduledNext = null;
|
4391
|
-
}
|
4392
4467
|
timers = {};
|
4393
4468
|
};
|
4394
4469
|
|
@@ -4423,7 +4498,8 @@ Ember.run.autorun = function() {
|
|
4423
4498
|
bindings in the application to sync.
|
4424
4499
|
|
4425
4500
|
You should call this method anytime you need any changed state to propagate
|
4426
|
-
throughout the app immediately without repainting the UI
|
4501
|
+
throughout the app immediately without repainting the UI (which happens
|
4502
|
+
in the later 'render' queue added by the `ember-views` package).
|
4427
4503
|
|
4428
4504
|
```javascript
|
4429
4505
|
Ember.run.sync();
|
@@ -4443,25 +4519,30 @@ Ember.run.sync = function() {
|
|
4443
4519
|
|
4444
4520
|
var timers = {}; // active timers...
|
4445
4521
|
|
4446
|
-
var scheduledLater;
|
4522
|
+
var scheduledLater, scheduledLaterExpires;
|
4447
4523
|
function invokeLaterTimers() {
|
4448
4524
|
scheduledLater = null;
|
4449
|
-
|
4450
|
-
|
4451
|
-
|
4452
|
-
|
4453
|
-
|
4454
|
-
if (
|
4455
|
-
|
4456
|
-
|
4457
|
-
|
4458
|
-
|
4525
|
+
run(function() {
|
4526
|
+
var now = (+ new Date()), earliest = -1;
|
4527
|
+
for (var key in timers) {
|
4528
|
+
if (!timers.hasOwnProperty(key)) { continue; }
|
4529
|
+
var timer = timers[key];
|
4530
|
+
if (timer && timer.expires) {
|
4531
|
+
if (now >= timer.expires) {
|
4532
|
+
delete timers[key];
|
4533
|
+
invoke(timer.target, timer.method, timer.args, 2);
|
4534
|
+
} else {
|
4535
|
+
if (earliest < 0 || (timer.expires < earliest)) { earliest = timer.expires; }
|
4536
|
+
}
|
4459
4537
|
}
|
4460
4538
|
}
|
4461
|
-
}
|
4462
4539
|
|
4463
|
-
|
4464
|
-
|
4540
|
+
// schedule next timeout to fire when the earliest timer expires
|
4541
|
+
if (earliest > 0) {
|
4542
|
+
scheduledLater = setTimeout(invokeLaterTimers, earliest - now);
|
4543
|
+
scheduledLaterExpires = earliest;
|
4544
|
+
}
|
4545
|
+
});
|
4465
4546
|
}
|
4466
4547
|
|
4467
4548
|
/**
|
@@ -4509,7 +4590,19 @@ Ember.run.later = function(target, method) {
|
|
4509
4590
|
timer = { target: target, method: method, expires: expires, args: args };
|
4510
4591
|
guid = Ember.guidFor(timer);
|
4511
4592
|
timers[guid] = timer;
|
4512
|
-
|
4593
|
+
|
4594
|
+
if(scheduledLater && expires < scheduledLaterExpires) {
|
4595
|
+
// Cancel later timer (then reschedule earlier timer below)
|
4596
|
+
clearTimeout(scheduledLater);
|
4597
|
+
scheduledLater = null;
|
4598
|
+
}
|
4599
|
+
|
4600
|
+
if (!scheduledLater) {
|
4601
|
+
// Schedule later timers to be run.
|
4602
|
+
scheduledLater = setTimeout(invokeLaterTimers, wait);
|
4603
|
+
scheduledLaterExpires = expires;
|
4604
|
+
}
|
4605
|
+
|
4513
4606
|
return guid;
|
4514
4607
|
};
|
4515
4608
|
|
@@ -4565,6 +4658,21 @@ function scheduleOnce(queue, target, method, args) {
|
|
4565
4658
|
});
|
4566
4659
|
```
|
4567
4660
|
|
4661
|
+
Also note that passing an anonymous function to `Ember.run.once` will
|
4662
|
+
not prevent additional calls with an identical anonymous function from
|
4663
|
+
scheduling the items multiple times, e.g.:
|
4664
|
+
|
4665
|
+
```javascript
|
4666
|
+
function scheduleIt() {
|
4667
|
+
Ember.run.once(myContext, function() { console.log("Closure"); });
|
4668
|
+
}
|
4669
|
+
scheduleIt();
|
4670
|
+
scheduleIt();
|
4671
|
+
// "Closure" will print twice, even though we're using `Ember.run.once`,
|
4672
|
+
// because the function we pass to it is anonymous and won't match the
|
4673
|
+
// previously scheduled operation.
|
4674
|
+
```
|
4675
|
+
|
4568
4676
|
@method once
|
4569
4677
|
@param {Object} [target] target of method to invoke
|
4570
4678
|
@param {Function|String} method The method to invoke.
|
@@ -4581,22 +4689,9 @@ Ember.run.scheduleOnce = function(queue, target, method, args) {
|
|
4581
4689
|
return scheduleOnce(queue, target, method, slice.call(arguments, 3));
|
4582
4690
|
};
|
4583
4691
|
|
4584
|
-
var scheduledNext;
|
4585
|
-
function invokeNextTimers() {
|
4586
|
-
scheduledNext = null;
|
4587
|
-
for(var key in timers) {
|
4588
|
-
if (!timers.hasOwnProperty(key)) { continue; }
|
4589
|
-
var timer = timers[key];
|
4590
|
-
if (timer.next) {
|
4591
|
-
delete timers[key];
|
4592
|
-
invoke(timer.target, timer.method, timer.args, 2);
|
4593
|
-
}
|
4594
|
-
}
|
4595
|
-
}
|
4596
|
-
|
4597
4692
|
/**
|
4598
4693
|
Schedules an item to run after control has been returned to the system.
|
4599
|
-
This is
|
4694
|
+
This is equivalent to calling `Ember.run.later` with a wait time of 1ms.
|
4600
4695
|
|
4601
4696
|
```javascript
|
4602
4697
|
Ember.run.next(myContext, function(){
|
@@ -4612,20 +4707,10 @@ function invokeNextTimers() {
|
|
4612
4707
|
@param {Object} [args*] Optional arguments to pass to the timeout.
|
4613
4708
|
@return {Object} timer
|
4614
4709
|
*/
|
4615
|
-
Ember.run.next = function(
|
4616
|
-
var
|
4617
|
-
|
4618
|
-
|
4619
|
-
method: method,
|
4620
|
-
args: slice.call(arguments),
|
4621
|
-
next: true
|
4622
|
-
};
|
4623
|
-
|
4624
|
-
guid = Ember.guidFor(timer);
|
4625
|
-
timers[guid] = timer;
|
4626
|
-
|
4627
|
-
if (!scheduledNext) { scheduledNext = setTimeout(invokeNextTimers, 1); }
|
4628
|
-
return guid;
|
4710
|
+
Ember.run.next = function() {
|
4711
|
+
var args = slice.call(arguments);
|
4712
|
+
args.push(1); // 1 millisecond wait
|
4713
|
+
return run.later.apply(this, args);
|
4629
4714
|
};
|
4630
4715
|
|
4631
4716
|
/**
|
@@ -5130,7 +5215,6 @@ var Mixin, REQUIRED, Alias,
|
|
5130
5215
|
a_indexOf = Ember.ArrayPolyfills.indexOf,
|
5131
5216
|
a_forEach = Ember.ArrayPolyfills.forEach,
|
5132
5217
|
a_slice = [].slice,
|
5133
|
-
EMPTY_META = {}, // dummy for non-writable meta
|
5134
5218
|
o_create = Ember.create,
|
5135
5219
|
defineProperty = Ember.defineProperty,
|
5136
5220
|
guidFor = Ember.guidFor;
|
@@ -5499,6 +5583,38 @@ Mixin.finishPartial = finishPartial;
|
|
5499
5583
|
Ember.anyUnprocessedMixins = false;
|
5500
5584
|
|
5501
5585
|
/**
|
5586
|
+
Creates an instance of a class. Accepts either no arguments, or an object
|
5587
|
+
containing values to initialize the newly instantiated object with.
|
5588
|
+
|
5589
|
+
```javascript
|
5590
|
+
App.Person = Ember.Object.extend({
|
5591
|
+
helloWorld: function() {
|
5592
|
+
alert("Hi, my name is " + this.get('name'));
|
5593
|
+
}
|
5594
|
+
});
|
5595
|
+
|
5596
|
+
var tom = App.Person.create({
|
5597
|
+
name: 'Tom Dale'
|
5598
|
+
});
|
5599
|
+
|
5600
|
+
tom.helloWorld(); // alerts "Hi, my name is Tom Dale".
|
5601
|
+
```
|
5602
|
+
|
5603
|
+
`create` will call the `init` function if defined during
|
5604
|
+
`Ember.AnyObject.extend`
|
5605
|
+
|
5606
|
+
If no arguments are passed to `create`, it will not set values to the new
|
5607
|
+
instance during initialization:
|
5608
|
+
|
5609
|
+
```javascript
|
5610
|
+
var noName = App.Person.create();
|
5611
|
+
noName.helloWorld(); // alerts undefined
|
5612
|
+
```
|
5613
|
+
|
5614
|
+
NOTE: For performance reasons, you cannot declare methods or computed
|
5615
|
+
properties during `create`. You should instead declare methods and computed
|
5616
|
+
properties when using `extend`.
|
5617
|
+
|
5502
5618
|
@method create
|
5503
5619
|
@static
|
5504
5620
|
@param arguments*
|
@@ -6014,35 +6130,35 @@ define("rsvp",
|
|
6014
6130
|
}
|
6015
6131
|
|
6016
6132
|
function all(promises) {
|
6017
|
-
|
6018
|
-
|
6019
|
-
|
6133
|
+
var i, results = [];
|
6134
|
+
var allPromise = new Promise();
|
6135
|
+
var remaining = promises.length;
|
6020
6136
|
|
6021
6137
|
if (remaining === 0) {
|
6022
6138
|
allPromise.resolve([]);
|
6023
6139
|
}
|
6024
6140
|
|
6025
|
-
|
6026
|
-
|
6027
|
-
|
6028
|
-
|
6029
|
-
|
6141
|
+
var resolver = function(index) {
|
6142
|
+
return function(value) {
|
6143
|
+
resolve(index, value);
|
6144
|
+
};
|
6145
|
+
};
|
6030
6146
|
|
6031
|
-
|
6032
|
-
|
6033
|
-
|
6034
|
-
|
6035
|
-
|
6036
|
-
|
6147
|
+
var resolve = function(index, value) {
|
6148
|
+
results[index] = value;
|
6149
|
+
if (--remaining === 0) {
|
6150
|
+
allPromise.resolve(results);
|
6151
|
+
}
|
6152
|
+
};
|
6037
6153
|
|
6038
|
-
|
6039
|
-
|
6040
|
-
|
6154
|
+
var reject = function(error) {
|
6155
|
+
allPromise.reject(error);
|
6156
|
+
};
|
6041
6157
|
|
6042
|
-
|
6043
|
-
|
6044
|
-
|
6045
|
-
|
6158
|
+
for (i = 0; i < remaining; i++) {
|
6159
|
+
promises[i].then(resolver(i), reject);
|
6160
|
+
}
|
6161
|
+
return allPromise;
|
6046
6162
|
}
|
6047
6163
|
|
6048
6164
|
EventTarget.mixin(Promise.prototype);
|
@@ -6418,57 +6534,6 @@ Ember.typeOf = function(item) {
|
|
6418
6534
|
return ret;
|
6419
6535
|
};
|
6420
6536
|
|
6421
|
-
/**
|
6422
|
-
Returns true if the passed value is null or undefined. This avoids errors
|
6423
|
-
from JSLint complaining about use of ==, which can be technically
|
6424
|
-
confusing.
|
6425
|
-
|
6426
|
-
```javascript
|
6427
|
-
Ember.isNone(); // true
|
6428
|
-
Ember.isNone(null); // true
|
6429
|
-
Ember.isNone(undefined); // true
|
6430
|
-
Ember.isNone(''); // false
|
6431
|
-
Ember.isNone([]); // false
|
6432
|
-
Ember.isNone(function(){}); // false
|
6433
|
-
```
|
6434
|
-
|
6435
|
-
@method isNone
|
6436
|
-
@for Ember
|
6437
|
-
@param {Object} obj Value to test
|
6438
|
-
@return {Boolean}
|
6439
|
-
*/
|
6440
|
-
Ember.isNone = function(obj) {
|
6441
|
-
return obj === null || obj === undefined;
|
6442
|
-
};
|
6443
|
-
Ember.none = Ember.deprecateFunc("Ember.none is deprecated. Please use Ember.isNone instead.", Ember.isNone);
|
6444
|
-
|
6445
|
-
/**
|
6446
|
-
Verifies that a value is `null` or an empty string, empty array,
|
6447
|
-
or empty function.
|
6448
|
-
|
6449
|
-
Constrains the rules on `Ember.isNone` by returning false for empty
|
6450
|
-
string and empty arrays.
|
6451
|
-
|
6452
|
-
```javascript
|
6453
|
-
Ember.isEmpty(); // true
|
6454
|
-
Ember.isEmpty(null); // true
|
6455
|
-
Ember.isEmpty(undefined); // true
|
6456
|
-
Ember.isEmpty(''); // true
|
6457
|
-
Ember.isEmpty([]); // true
|
6458
|
-
Ember.isEmpty('Adam Hawkins'); // false
|
6459
|
-
Ember.isEmpty([0,1,2]); // false
|
6460
|
-
```
|
6461
|
-
|
6462
|
-
@method isEmpty
|
6463
|
-
@for Ember
|
6464
|
-
@param {Object} obj Value to test
|
6465
|
-
@return {Boolean}
|
6466
|
-
*/
|
6467
|
-
Ember.isEmpty = function(obj) {
|
6468
|
-
return obj === null || obj === undefined || (obj.length === 0 && typeof obj !== 'function') || (typeof obj === 'object' && Ember.get(obj, 'length') === 0);
|
6469
|
-
};
|
6470
|
-
Ember.empty = Ember.deprecateFunc("Ember.empty is deprecated. Please use Ember.isEmpty instead.", Ember.isEmpty) ;
|
6471
|
-
|
6472
6537
|
/**
|
6473
6538
|
This will compare two javascript values of possibly different types.
|
6474
6539
|
It will tell you which one is greater than the other by returning:
|
@@ -6924,10 +6989,11 @@ Ember.String = {
|
|
6924
6989
|
*/
|
6925
6990
|
dasherize: function(str) {
|
6926
6991
|
var cache = STRING_DASHERIZE_CACHE,
|
6927
|
-
|
6992
|
+
hit = cache.hasOwnProperty(str),
|
6993
|
+
ret;
|
6928
6994
|
|
6929
|
-
if (
|
6930
|
-
return
|
6995
|
+
if (hit) {
|
6996
|
+
return cache[str];
|
6931
6997
|
} else {
|
6932
6998
|
ret = Ember.String.decamelize(str).replace(STRING_DASHERIZE_REGEXP,'-');
|
6933
6999
|
cache[str] = ret;
|
@@ -6937,7 +7003,7 @@ Ember.String = {
|
|
6937
7003
|
},
|
6938
7004
|
|
6939
7005
|
/**
|
6940
|
-
Returns the
|
7006
|
+
Returns the lowerCamelCase form of a string.
|
6941
7007
|
|
6942
7008
|
```javascript
|
6943
7009
|
'innerHTML'.camelize(); // 'innerHTML'
|
@@ -7008,10 +7074,10 @@ Ember.String = {
|
|
7008
7074
|
/**
|
7009
7075
|
Returns the Capitalized form of a string
|
7010
7076
|
|
7011
|
-
'innerHTML'.capitalize()
|
7012
|
-
'action_name'.capitalize()
|
7013
|
-
'css-class-name'.capitalize()
|
7014
|
-
'my favorite items'.capitalize()
|
7077
|
+
'innerHTML'.capitalize() // 'InnerHTML'
|
7078
|
+
'action_name'.capitalize() // 'Action_name'
|
7079
|
+
'css-class-name'.capitalize() // 'Css-class-name'
|
7080
|
+
'my favorite items'.capitalize() // 'My favorite items'
|
7015
7081
|
|
7016
7082
|
@method capitalize
|
7017
7083
|
@param {String} str
|
@@ -7355,8 +7421,7 @@ function iter(key, value) {
|
|
7355
7421
|
@extends Ember.Mixin
|
7356
7422
|
@since Ember 0.9
|
7357
7423
|
*/
|
7358
|
-
Ember.Enumerable = Ember.Mixin.create(
|
7359
|
-
/** @scope Ember.Enumerable.prototype */ {
|
7424
|
+
Ember.Enumerable = Ember.Mixin.create({
|
7360
7425
|
|
7361
7426
|
// compatibility
|
7362
7427
|
isEnumerable: true,
|
@@ -7389,7 +7454,7 @@ Ember.Enumerable = Ember.Mixin.create(
|
|
7389
7454
|
|
7390
7455
|
@method nextObject
|
7391
7456
|
@param {Number} index the current index of the iteration
|
7392
|
-
@param {Object} previousObject the value returned by the last call to
|
7457
|
+
@param {Object} previousObject the value returned by the last call to
|
7393
7458
|
`nextObject`.
|
7394
7459
|
@param {Object} context a context object you can use to maintain state.
|
7395
7460
|
@return {Object} the next object in the iteration or undefined
|
@@ -7408,10 +7473,10 @@ Ember.Enumerable = Ember.Mixin.create(
|
|
7408
7473
|
|
7409
7474
|
```javascript
|
7410
7475
|
var arr = ["a", "b", "c"];
|
7411
|
-
arr.firstObject
|
7476
|
+
arr.get('firstObject'); // "a"
|
7412
7477
|
|
7413
7478
|
var arr = [];
|
7414
|
-
arr.firstObject
|
7479
|
+
arr.get('firstObject'); // undefined
|
7415
7480
|
```
|
7416
7481
|
|
7417
7482
|
@property firstObject
|
@@ -7434,10 +7499,10 @@ Ember.Enumerable = Ember.Mixin.create(
|
|
7434
7499
|
|
7435
7500
|
```javascript
|
7436
7501
|
var arr = ["a", "b", "c"];
|
7437
|
-
arr.lastObject
|
7502
|
+
arr.get('lastObject'); // "c"
|
7438
7503
|
|
7439
7504
|
var arr = [];
|
7440
|
-
arr.lastObject
|
7505
|
+
arr.get('lastObject'); // undefined
|
7441
7506
|
```
|
7442
7507
|
|
7443
7508
|
@property lastObject
|
@@ -7570,7 +7635,7 @@ Ember.Enumerable = Ember.Mixin.create(
|
|
7570
7635
|
@return {Array} The mapped array.
|
7571
7636
|
*/
|
7572
7637
|
map: function(callback, target) {
|
7573
|
-
var ret = [];
|
7638
|
+
var ret = Ember.A([]);
|
7574
7639
|
this.forEach(function(x, idx, i) {
|
7575
7640
|
ret[idx] = callback.call(target, x, idx,i);
|
7576
7641
|
});
|
@@ -7620,7 +7685,7 @@ Ember.Enumerable = Ember.Mixin.create(
|
|
7620
7685
|
@return {Array} A filtered array.
|
7621
7686
|
*/
|
7622
7687
|
filter: function(callback, target) {
|
7623
|
-
var ret = [];
|
7688
|
+
var ret = Ember.A([]);
|
7624
7689
|
this.forEach(function(x, idx, i) {
|
7625
7690
|
if (callback.call(target, x, idx, i)) ret.push(x);
|
7626
7691
|
});
|
@@ -7909,7 +7974,7 @@ Ember.Enumerable = Ember.Mixin.create(
|
|
7909
7974
|
@return {Array} return values from calling invoke.
|
7910
7975
|
*/
|
7911
7976
|
invoke: function(methodName) {
|
7912
|
-
var args, ret = [];
|
7977
|
+
var args, ret = Ember.A([]);
|
7913
7978
|
if (arguments.length>1) args = a_slice.call(arguments, 1);
|
7914
7979
|
|
7915
7980
|
this.forEach(function(x, idx) {
|
@@ -7930,7 +7995,7 @@ Ember.Enumerable = Ember.Mixin.create(
|
|
7930
7995
|
@return {Array} the enumerable as an array.
|
7931
7996
|
*/
|
7932
7997
|
toArray: function() {
|
7933
|
-
var ret = [];
|
7998
|
+
var ret = Ember.A([]);
|
7934
7999
|
this.forEach(function(o, idx) { ret[idx] = o; });
|
7935
8000
|
return ret ;
|
7936
8001
|
},
|
@@ -7964,7 +8029,7 @@ Ember.Enumerable = Ember.Mixin.create(
|
|
7964
8029
|
*/
|
7965
8030
|
without: function(value) {
|
7966
8031
|
if (!this.contains(value)) return this; // nothing to do
|
7967
|
-
var ret = []
|
8032
|
+
var ret = Ember.A([]);
|
7968
8033
|
this.forEach(function(k) {
|
7969
8034
|
if (k !== value) ret[ret.length] = k;
|
7970
8035
|
}) ;
|
@@ -7984,7 +8049,7 @@ Ember.Enumerable = Ember.Mixin.create(
|
|
7984
8049
|
@return {Ember.Enumerable}
|
7985
8050
|
*/
|
7986
8051
|
uniq: function() {
|
7987
|
-
var ret = [];
|
8052
|
+
var ret = Ember.A([]);
|
7988
8053
|
this.forEach(function(k){
|
7989
8054
|
if (a_indexOf(ret, k)<0) ret.push(k);
|
7990
8055
|
});
|
@@ -8016,7 +8081,7 @@ Ember.Enumerable = Ember.Mixin.create(
|
|
8016
8081
|
|
8017
8082
|
@method addEnumerableObserver
|
8018
8083
|
@param {Object} target
|
8019
|
-
@param {Hash} opts
|
8084
|
+
@param {Hash} [opts]
|
8020
8085
|
*/
|
8021
8086
|
addEnumerableObserver: function(target, opts) {
|
8022
8087
|
var willChange = (opts && opts.willChange) || 'enumerableWillChange',
|
@@ -8114,7 +8179,7 @@ Ember.Enumerable = Ember.Mixin.create(
|
|
8114
8179
|
@chainable
|
8115
8180
|
*/
|
8116
8181
|
enumerableContentDidChange: function(removing, adding) {
|
8117
|
-
var
|
8182
|
+
var removeCnt, addCnt, hasDelta;
|
8118
8183
|
|
8119
8184
|
if ('number' === typeof removing) removeCnt = removing;
|
8120
8185
|
else if (removing) removeCnt = get(removing, 'length');
|
@@ -8152,7 +8217,7 @@ Ember.Enumerable = Ember.Mixin.create(
|
|
8152
8217
|
// HELPERS
|
8153
8218
|
//
|
8154
8219
|
|
8155
|
-
var get = Ember.get, set = Ember.set,
|
8220
|
+
var get = Ember.get, set = Ember.set, map = Ember.EnumerableUtils.map, cacheFor = Ember.cacheFor;
|
8156
8221
|
|
8157
8222
|
function none(obj) { return obj===null || obj===undefined; }
|
8158
8223
|
|
@@ -8294,15 +8359,19 @@ Ember.Array = Ember.Mixin.create(Ember.Enumerable, /** @scope Ember.Array.protot
|
|
8294
8359
|
```
|
8295
8360
|
|
8296
8361
|
@method slice
|
8297
|
-
@param
|
8298
|
-
@param
|
8362
|
+
@param {Integer} beginIndex (Optional) index to begin slicing from.
|
8363
|
+
@param {Integer} endIndex (Optional) index to end the slice at.
|
8299
8364
|
@return {Array} New array with specified slice
|
8300
8365
|
*/
|
8301
8366
|
slice: function(beginIndex, endIndex) {
|
8302
|
-
var ret = [];
|
8367
|
+
var ret = Ember.A([]);
|
8303
8368
|
var length = get(this, 'length') ;
|
8304
8369
|
if (none(beginIndex)) beginIndex = 0 ;
|
8305
8370
|
if (none(endIndex) || (endIndex > length)) endIndex = length ;
|
8371
|
+
|
8372
|
+
if (beginIndex < 0) beginIndex = length + beginIndex;
|
8373
|
+
if (endIndex < 0) endIndex = length + endIndex;
|
8374
|
+
|
8306
8375
|
while(beginIndex < endIndex) {
|
8307
8376
|
ret[ret.length] = this.objectAt(beginIndex++) ;
|
8308
8377
|
}
|
@@ -8456,9 +8525,9 @@ Ember.Array = Ember.Mixin.create(Ember.Enumerable, /** @scope Ember.Array.protot
|
|
8456
8525
|
|
8457
8526
|
@method arrayContentWillChange
|
8458
8527
|
@param {Number} startIdx The starting index in the array that will change.
|
8459
|
-
@param {Number} removeAmt The number of items that will be removed. If you
|
8528
|
+
@param {Number} removeAmt The number of items that will be removed. If you
|
8460
8529
|
pass `null` assumes 0
|
8461
|
-
@param {Number} addAmt The number of items that will be added If you
|
8530
|
+
@param {Number} addAmt The number of items that will be added If you
|
8462
8531
|
pass `null` assumes 0.
|
8463
8532
|
@return {Ember.Array} receiver
|
8464
8533
|
*/
|
@@ -8819,8 +8888,7 @@ var forEach = Ember.EnumerableUtils.forEach;
|
|
8819
8888
|
@extends Ember.Mixin
|
8820
8889
|
@uses Ember.Enumerable
|
8821
8890
|
*/
|
8822
|
-
Ember.MutableEnumerable = Ember.Mixin.create(Ember.Enumerable,
|
8823
|
-
/** @scope Ember.MutableEnumerable.prototype */ {
|
8891
|
+
Ember.MutableEnumerable = Ember.Mixin.create(Ember.Enumerable, {
|
8824
8892
|
|
8825
8893
|
/**
|
8826
8894
|
__Required.__ You must implement this method to apply this mixin.
|
@@ -8905,7 +8973,7 @@ var EMPTY = [];
|
|
8905
8973
|
// HELPERS
|
8906
8974
|
//
|
8907
8975
|
|
8908
|
-
var get = Ember.get, set = Ember.set
|
8976
|
+
var get = Ember.get, set = Ember.set;
|
8909
8977
|
|
8910
8978
|
/**
|
8911
8979
|
This mixin defines the API for modifying array-like objects. These methods
|
@@ -8932,11 +9000,11 @@ Ember.MutableArray = Ember.Mixin.create(Ember.Array, Ember.MutableEnumerable,
|
|
8932
9000
|
passed array. You should also call `this.enumerableContentDidChange()`
|
8933
9001
|
|
8934
9002
|
@method replace
|
8935
|
-
@param {Number} idx Starting index in the array to replace. If
|
9003
|
+
@param {Number} idx Starting index in the array to replace. If
|
8936
9004
|
idx >= length, then append to the end of the array.
|
8937
|
-
@param {Number} amt Number of elements that should be removed from
|
9005
|
+
@param {Number} amt Number of elements that should be removed from
|
8938
9006
|
the array, starting at *idx*.
|
8939
|
-
@param {Array} objects An array of zero or more objects that should be
|
9007
|
+
@param {Array} objects An array of zero or more objects that should be
|
8940
9008
|
inserted into the array at *idx*
|
8941
9009
|
*/
|
8942
9010
|
replace: Ember.required(),
|
@@ -9201,7 +9269,7 @@ Ember.MutableArray = Ember.Mixin.create(Ember.Array, Ember.MutableEnumerable,
|
|
9201
9269
|
@submodule ember-runtime
|
9202
9270
|
*/
|
9203
9271
|
|
9204
|
-
var get = Ember.get, set = Ember.set
|
9272
|
+
var get = Ember.get, set = Ember.set;
|
9205
9273
|
|
9206
9274
|
/**
|
9207
9275
|
## Overview
|
@@ -9799,6 +9867,16 @@ Ember.TargetActionSupport = Ember.Mixin.create({
|
|
9799
9867
|
// outputs: 'Our person has greeted'
|
9800
9868
|
```
|
9801
9869
|
|
9870
|
+
You can also chain multiple event subscriptions:
|
9871
|
+
|
9872
|
+
```javascript
|
9873
|
+
person.on('greet', function() {
|
9874
|
+
console.log('Our person has greeted');
|
9875
|
+
}).one('greet', function() {
|
9876
|
+
console.log('Offer one-time special');
|
9877
|
+
}).off('event', this, forgetThis);
|
9878
|
+
```
|
9879
|
+
|
9802
9880
|
@class Evented
|
9803
9881
|
@namespace Ember
|
9804
9882
|
@extends Ember.Mixin
|
@@ -9826,6 +9904,7 @@ Ember.Evented = Ember.Mixin.create({
|
|
9826
9904
|
*/
|
9827
9905
|
on: function(name, target, method) {
|
9828
9906
|
Ember.addListener(this, name, target, method);
|
9907
|
+
return this;
|
9829
9908
|
},
|
9830
9909
|
|
9831
9910
|
/**
|
@@ -9849,6 +9928,7 @@ Ember.Evented = Ember.Mixin.create({
|
|
9849
9928
|
}
|
9850
9929
|
|
9851
9930
|
Ember.addListener(this, name, target, method, true);
|
9931
|
+
return this;
|
9852
9932
|
},
|
9853
9933
|
|
9854
9934
|
/**
|
@@ -9892,6 +9972,7 @@ Ember.Evented = Ember.Mixin.create({
|
|
9892
9972
|
*/
|
9893
9973
|
off: function(name, target, method) {
|
9894
9974
|
Ember.removeListener(this, name, target, method);
|
9975
|
+
return this;
|
9895
9976
|
},
|
9896
9977
|
|
9897
9978
|
/**
|
@@ -9922,8 +10003,7 @@ RSVP.async = function(callback, binding) {
|
|
9922
10003
|
@submodule ember-runtime
|
9923
10004
|
*/
|
9924
10005
|
|
9925
|
-
var get = Ember.get
|
9926
|
-
slice = Array.prototype.slice;
|
10006
|
+
var get = Ember.get;
|
9927
10007
|
|
9928
10008
|
/**
|
9929
10009
|
@class Deferred
|
@@ -9999,7 +10079,6 @@ Ember.Container.set = Ember.set;
|
|
9999
10079
|
var set = Ember.set, get = Ember.get,
|
10000
10080
|
o_create = Ember.create,
|
10001
10081
|
o_defineProperty = Ember.platform.defineProperty,
|
10002
|
-
a_slice = Array.prototype.slice,
|
10003
10082
|
GUID_KEY = Ember.GUID_KEY,
|
10004
10083
|
guidFor = Ember.guidFor,
|
10005
10084
|
generateGuid = Ember.generateGuid,
|
@@ -10147,6 +10226,37 @@ CoreObject.PrototypeMixin = Mixin.create({
|
|
10147
10226
|
|
10148
10227
|
isInstance: true,
|
10149
10228
|
|
10229
|
+
/**
|
10230
|
+
An overridable method called when objects are instantiated. By default,
|
10231
|
+
does nothing unless it is overridden during class definition.
|
10232
|
+
|
10233
|
+
Example:
|
10234
|
+
|
10235
|
+
```javascript
|
10236
|
+
App.Person = Ember.Object.extend({
|
10237
|
+
init: function() {
|
10238
|
+
this._super();
|
10239
|
+
alert('Name is ' + this.get('name'));
|
10240
|
+
}
|
10241
|
+
});
|
10242
|
+
|
10243
|
+
var steve = App.Person.create({
|
10244
|
+
name: "Steve"
|
10245
|
+
});
|
10246
|
+
|
10247
|
+
// alerts 'Name is Steve'.
|
10248
|
+
```
|
10249
|
+
|
10250
|
+
NOTE: If you do override `init` for a framework class like `Ember.View` or
|
10251
|
+
`Ember.ArrayController`, be sure to call `this._super()` in your
|
10252
|
+
`init` declaration! If you don't, Ember may not have an opportunity to
|
10253
|
+
do important setup work, and you'll see strange behavior in your
|
10254
|
+
application.
|
10255
|
+
|
10256
|
+
```
|
10257
|
+
|
10258
|
+
@method init
|
10259
|
+
*/
|
10150
10260
|
init: function() {},
|
10151
10261
|
|
10152
10262
|
/**
|
@@ -10191,14 +10301,14 @@ CoreObject.PrototypeMixin = Mixin.create({
|
|
10191
10301
|
view.get('classNames'); // ['ember-view', 'bar', 'foo', 'baz']
|
10192
10302
|
```
|
10193
10303
|
Adding a single property that is not an array will just add it in the array:
|
10194
|
-
|
10304
|
+
|
10195
10305
|
```javascript
|
10196
10306
|
var view = App.FooBarView.create({
|
10197
10307
|
classNames: 'baz'
|
10198
10308
|
})
|
10199
10309
|
view.get('classNames'); // ['ember-view', 'bar', 'foo', 'baz']
|
10200
10310
|
```
|
10201
|
-
|
10311
|
+
|
10202
10312
|
Using the `concatenatedProperties` property, we can tell to Ember that mix
|
10203
10313
|
the content of the properties.
|
10204
10314
|
|
@@ -10297,7 +10407,7 @@ CoreObject.PrototypeMixin = Mixin.create({
|
|
10297
10407
|
}
|
10298
10408
|
});
|
10299
10409
|
teacher = App.Teacher.create()
|
10300
|
-
teacher.toString();
|
10410
|
+
teacher.toString(); //=> "<App.Teacher:ember1026:Tom Dale>"
|
10301
10411
|
|
10302
10412
|
@method toString
|
10303
10413
|
@return {String} string representation
|
@@ -10476,687 +10586,723 @@ Ember.CoreObject = CoreObject;
|
|
10476
10586
|
@submodule ember-runtime
|
10477
10587
|
*/
|
10478
10588
|
|
10479
|
-
var get = Ember.get, set = Ember.set, guidFor = Ember.guidFor, none = Ember.isNone;
|
10480
|
-
|
10481
10589
|
/**
|
10482
|
-
|
10590
|
+
`Ember.Object` is the main base class for all Ember objects. It is a subclass
|
10591
|
+
of `Ember.CoreObject` with the `Ember.Observable` mixin applied. For details,
|
10592
|
+
see the documentation for each of these.
|
10483
10593
|
|
10484
|
-
|
10485
|
-
|
10486
|
-
|
10487
|
-
|
10594
|
+
@class Object
|
10595
|
+
@namespace Ember
|
10596
|
+
@extends Ember.CoreObject
|
10597
|
+
@uses Ember.Observable
|
10598
|
+
*/
|
10599
|
+
Ember.Object = Ember.CoreObject.extend(Ember.Observable);
|
10600
|
+
Ember.Object.toString = function() { return "Ember.Object"; };
|
10488
10601
|
|
10489
|
-
|
10490
|
-
on any enumerable object including both Sets and Arrays.
|
10602
|
+
})();
|
10491
10603
|
|
10492
|
-
## Creating a Set
|
10493
10604
|
|
10494
|
-
You can create a set like you would most objects using
|
10495
|
-
`new Ember.Set()`. Most new sets you create will be empty, but you can
|
10496
|
-
also initialize the set with some content by passing an array or other
|
10497
|
-
enumerable of objects to the constructor.
|
10498
10605
|
|
10499
|
-
|
10500
|
-
|
10606
|
+
(function() {
|
10607
|
+
/**
|
10608
|
+
@module ember
|
10609
|
+
@submodule ember-runtime
|
10610
|
+
*/
|
10501
10611
|
|
10502
|
-
|
10503
|
-
// creates a new empty set
|
10504
|
-
var foundNames = new Ember.Set();
|
10612
|
+
var get = Ember.get, indexOf = Ember.ArrayPolyfills.indexOf;
|
10505
10613
|
|
10506
|
-
|
10507
|
-
|
10614
|
+
/**
|
10615
|
+
A Namespace is an object usually used to contain other objects or methods
|
10616
|
+
such as an application or framework. Create a namespace anytime you want
|
10617
|
+
to define one of these new containers.
|
10508
10618
|
|
10509
|
-
|
10510
|
-
var namesCopy = new Ember.Set(names);
|
10619
|
+
# Example Usage
|
10511
10620
|
|
10512
|
-
|
10513
|
-
|
10621
|
+
```javascript
|
10622
|
+
MyFramework = Ember.Namespace.create({
|
10623
|
+
VERSION: '1.0.0'
|
10624
|
+
});
|
10514
10625
|
```
|
10515
10626
|
|
10516
|
-
|
10627
|
+
@class Namespace
|
10628
|
+
@namespace Ember
|
10629
|
+
@extends Ember.Object
|
10630
|
+
*/
|
10631
|
+
var Namespace = Ember.Namespace = Ember.Object.extend({
|
10632
|
+
isNamespace: true,
|
10517
10633
|
|
10518
|
-
|
10519
|
-
|
10520
|
-
|
10634
|
+
init: function() {
|
10635
|
+
Ember.Namespace.NAMESPACES.push(this);
|
10636
|
+
Ember.Namespace.PROCESSED = false;
|
10637
|
+
},
|
10521
10638
|
|
10522
|
-
|
10523
|
-
|
10524
|
-
|
10525
|
-
remove the object the first time and have no effect on future calls until
|
10526
|
-
you add the object to the set again.
|
10639
|
+
toString: function() {
|
10640
|
+
var name = get(this, 'name');
|
10641
|
+
if (name) { return name; }
|
10527
10642
|
|
10528
|
-
|
10529
|
-
|
10643
|
+
findNamespaces();
|
10644
|
+
return this[Ember.GUID_KEY+'_name'];
|
10645
|
+
},
|
10530
10646
|
|
10531
|
-
|
10532
|
-
|
10533
|
-
|
10534
|
-
queue when you don't care which order the jobs are executed in.
|
10647
|
+
nameClasses: function() {
|
10648
|
+
processNamespace([this.toString()], this, {});
|
10649
|
+
},
|
10535
10650
|
|
10536
|
-
|
10651
|
+
destroy: function() {
|
10652
|
+
var namespaces = Ember.Namespace.NAMESPACES;
|
10653
|
+
Ember.lookup[this.toString()] = undefined;
|
10654
|
+
namespaces.splice(indexOf.call(namespaces, this), 1);
|
10655
|
+
this._super();
|
10656
|
+
}
|
10657
|
+
});
|
10537
10658
|
|
10538
|
-
|
10539
|
-
|
10659
|
+
Namespace.reopenClass({
|
10660
|
+
NAMESPACES: [Ember],
|
10661
|
+
NAMESPACES_BY_ID: {},
|
10662
|
+
PROCESSED: false,
|
10663
|
+
processAll: processAllNamespaces,
|
10664
|
+
byName: function(name) {
|
10665
|
+
if (!Ember.BOOTED) {
|
10666
|
+
processAllNamespaces();
|
10667
|
+
}
|
10540
10668
|
|
10541
|
-
|
10669
|
+
return NAMESPACES_BY_ID[name];
|
10670
|
+
}
|
10671
|
+
});
|
10542
10672
|
|
10543
|
-
|
10544
|
-
alerted whenever the content changes. You can also add an enumerable
|
10545
|
-
observer to the set to be notified of specific objects that are added and
|
10546
|
-
removed from the set. See `Ember.Enumerable` for more information on
|
10547
|
-
enumerables.
|
10673
|
+
var NAMESPACES_BY_ID = Namespace.NAMESPACES_BY_ID;
|
10548
10674
|
|
10549
|
-
|
10550
|
-
|
10551
|
-
changes. It would be better if you could just adjust the filtered set based
|
10552
|
-
on what was changed on the original set. The same issue applies to merging
|
10553
|
-
sets, as well.
|
10675
|
+
var hasOwnProp = ({}).hasOwnProperty,
|
10676
|
+
guidFor = Ember.guidFor;
|
10554
10677
|
|
10555
|
-
|
10678
|
+
function processNamespace(paths, root, seen) {
|
10679
|
+
var idx = paths.length;
|
10556
10680
|
|
10557
|
-
|
10558
|
-
on the methods you will use with `Ember.Set`, please consult these mixins.
|
10559
|
-
The most useful ones will be `Ember.Enumerable` and
|
10560
|
-
`Ember.MutableEnumerable` which implement most of the common iterator
|
10561
|
-
methods you are used to on Array.
|
10681
|
+
NAMESPACES_BY_ID[paths.join('.')] = root;
|
10562
10682
|
|
10563
|
-
|
10564
|
-
|
10565
|
-
|
10566
|
-
|
10567
|
-
code that can know with certainty when the underlying set data will or
|
10568
|
-
will not be modified.
|
10683
|
+
// Loop over all of the keys in the namespace, looking for classes
|
10684
|
+
for(var key in root) {
|
10685
|
+
if (!hasOwnProp.call(root, key)) { continue; }
|
10686
|
+
var obj = root[key];
|
10569
10687
|
|
10570
|
-
|
10571
|
-
|
10572
|
-
|
10573
|
-
|
10574
|
-
|
10575
|
-
|
10576
|
-
@since Ember 0.9
|
10577
|
-
*/
|
10578
|
-
Ember.Set = Ember.CoreObject.extend(Ember.MutableEnumerable, Ember.Copyable, Ember.Freezable,
|
10579
|
-
/** @scope Ember.Set.prototype */ {
|
10688
|
+
// If we are processing the `Ember` namespace, for example, the
|
10689
|
+
// `paths` will start with `["Ember"]`. Every iteration through
|
10690
|
+
// the loop will update the **second** element of this list with
|
10691
|
+
// the key, so processing `Ember.View` will make the Array
|
10692
|
+
// `['Ember', 'View']`.
|
10693
|
+
paths[idx] = key;
|
10580
10694
|
|
10581
|
-
|
10582
|
-
|
10583
|
-
|
10695
|
+
// If we have found an unprocessed class
|
10696
|
+
if (obj && obj.toString === classToString) {
|
10697
|
+
// Replace the class' `toString` with the dot-separated path
|
10698
|
+
// and set its `NAME_KEY`
|
10699
|
+
obj.toString = makeToString(paths.join('.'));
|
10700
|
+
obj[NAME_KEY] = paths.join('.');
|
10584
10701
|
|
10585
|
-
|
10586
|
-
|
10702
|
+
// Support nested namespaces
|
10703
|
+
} else if (obj && obj.isNamespace) {
|
10704
|
+
// Skip aliased namespaces
|
10705
|
+
if (seen[guidFor(obj)]) { continue; }
|
10706
|
+
seen[guidFor(obj)] = true;
|
10587
10707
|
|
10588
|
-
|
10589
|
-
|
10590
|
-
|
10591
|
-
|
10592
|
-
length: 0,
|
10708
|
+
// Process the child namespace
|
10709
|
+
processNamespace(paths, obj, seen);
|
10710
|
+
}
|
10711
|
+
}
|
10593
10712
|
|
10594
|
-
|
10595
|
-
|
10596
|
-
without having to recreate it.
|
10713
|
+
paths.length = idx; // cut out last item
|
10714
|
+
}
|
10597
10715
|
|
10598
|
-
|
10599
|
-
|
10600
|
-
colors.length; // 3
|
10601
|
-
colors.clear();
|
10602
|
-
colors.length; // 0
|
10603
|
-
```
|
10716
|
+
function findNamespaces() {
|
10717
|
+
var Namespace = Ember.Namespace, lookup = Ember.lookup, obj, isNamespace;
|
10604
10718
|
|
10605
|
-
|
10606
|
-
@return {Ember.Set} An empty Set
|
10607
|
-
*/
|
10608
|
-
clear: function() {
|
10609
|
-
if (this.isFrozen) { throw new Error(Ember.FROZEN_ERROR); }
|
10719
|
+
if (Namespace.PROCESSED) { return; }
|
10610
10720
|
|
10611
|
-
|
10612
|
-
|
10721
|
+
for (var prop in lookup) {
|
10722
|
+
// These don't raise exceptions but can cause warnings
|
10723
|
+
if (prop === "parent" || prop === "top" || prop === "frameElement") { continue; }
|
10613
10724
|
|
10614
|
-
|
10725
|
+
// get(window.globalStorage, 'isNamespace') would try to read the storage for domain isNamespace and cause exception in Firefox.
|
10726
|
+
// globalStorage is a storage obsoleted by the WhatWG storage specification. See https://developer.mozilla.org/en/DOM/Storage#globalStorage
|
10727
|
+
if (prop === "globalStorage" && lookup.StorageList && lookup.globalStorage instanceof lookup.StorageList) { continue; }
|
10728
|
+
// Unfortunately, some versions of IE don't support window.hasOwnProperty
|
10729
|
+
if (lookup.hasOwnProperty && !lookup.hasOwnProperty(prop)) { continue; }
|
10615
10730
|
|
10616
|
-
|
10617
|
-
|
10618
|
-
|
10731
|
+
// At times we are not allowed to access certain properties for security reasons.
|
10732
|
+
// There are also times where even if we can access them, we are not allowed to access their properties.
|
10733
|
+
try {
|
10734
|
+
obj = Ember.lookup[prop];
|
10735
|
+
isNamespace = obj && obj.isNamespace;
|
10736
|
+
} catch (e) {
|
10737
|
+
continue;
|
10738
|
+
}
|
10619
10739
|
|
10620
|
-
|
10621
|
-
|
10622
|
-
|
10623
|
-
delete this[i];
|
10740
|
+
if (isNamespace) {
|
10741
|
+
Ember.deprecate("Namespaces should not begin with lowercase.", /^[A-Z]/.test(prop));
|
10742
|
+
obj[NAME_KEY] = prop;
|
10624
10743
|
}
|
10744
|
+
}
|
10745
|
+
}
|
10625
10746
|
|
10626
|
-
|
10747
|
+
var NAME_KEY = Ember.NAME_KEY = Ember.GUID_KEY + '_name';
|
10627
10748
|
|
10628
|
-
|
10629
|
-
|
10630
|
-
|
10749
|
+
function superClassString(mixin) {
|
10750
|
+
var superclass = mixin.superclass;
|
10751
|
+
if (superclass) {
|
10752
|
+
if (superclass[NAME_KEY]) { return superclass[NAME_KEY]; }
|
10753
|
+
else { return superClassString(superclass); }
|
10754
|
+
} else {
|
10755
|
+
return;
|
10756
|
+
}
|
10757
|
+
}
|
10631
10758
|
|
10632
|
-
|
10633
|
-
|
10759
|
+
function classToString() {
|
10760
|
+
if (!Ember.BOOTED && !this[NAME_KEY]) {
|
10761
|
+
processAllNamespaces();
|
10762
|
+
}
|
10634
10763
|
|
10635
|
-
|
10636
|
-
Returns true if the passed object is also an enumerable that contains the
|
10637
|
-
same objects as the receiver.
|
10764
|
+
var ret;
|
10638
10765
|
|
10639
|
-
|
10640
|
-
|
10641
|
-
|
10766
|
+
if (this[NAME_KEY]) {
|
10767
|
+
ret = this[NAME_KEY];
|
10768
|
+
} else {
|
10769
|
+
var str = superClassString(this);
|
10770
|
+
if (str) {
|
10771
|
+
ret = "(subclass of " + str + ")";
|
10772
|
+
} else {
|
10773
|
+
ret = "(unknown mixin)";
|
10774
|
+
}
|
10775
|
+
this.toString = makeToString(ret);
|
10776
|
+
}
|
10642
10777
|
|
10643
|
-
|
10644
|
-
|
10645
|
-
```
|
10778
|
+
return ret;
|
10779
|
+
}
|
10646
10780
|
|
10647
|
-
|
10648
|
-
|
10649
|
-
|
10650
|
-
*/
|
10651
|
-
isEqual: function(obj) {
|
10652
|
-
// fail fast
|
10653
|
-
if (!Ember.Enumerable.detect(obj)) return false;
|
10781
|
+
function processAllNamespaces() {
|
10782
|
+
var unprocessedNamespaces = !Namespace.PROCESSED,
|
10783
|
+
unprocessedMixins = Ember.anyUnprocessedMixins;
|
10654
10784
|
|
10655
|
-
|
10656
|
-
|
10785
|
+
if (unprocessedNamespaces) {
|
10786
|
+
findNamespaces();
|
10787
|
+
Namespace.PROCESSED = true;
|
10788
|
+
}
|
10657
10789
|
|
10658
|
-
|
10659
|
-
|
10790
|
+
if (unprocessedNamespaces || unprocessedMixins) {
|
10791
|
+
var namespaces = Namespace.NAMESPACES, namespace;
|
10792
|
+
for (var i=0, l=namespaces.length; i<l; i++) {
|
10793
|
+
namespace = namespaces[i];
|
10794
|
+
processNamespace([namespace.toString()], namespace, {});
|
10660
10795
|
}
|
10661
10796
|
|
10662
|
-
|
10663
|
-
}
|
10797
|
+
Ember.anyUnprocessedMixins = false;
|
10798
|
+
}
|
10799
|
+
}
|
10664
10800
|
|
10665
|
-
|
10666
|
-
|
10667
|
-
|
10668
|
-
the passed value is null this method will have no effect.
|
10801
|
+
function makeToString(ret) {
|
10802
|
+
return function() { return ret; };
|
10803
|
+
}
|
10669
10804
|
|
10670
|
-
|
10805
|
+
Ember.Mixin.prototype.toString = classToString;
|
10671
10806
|
|
10672
|
-
|
10673
|
-
var colors = new Ember.Set();
|
10674
|
-
colors.add("blue"); // ["blue"]
|
10675
|
-
colors.add("blue"); // ["blue"]
|
10676
|
-
colors.add("red"); // ["blue", "red"]
|
10677
|
-
colors.add(null); // ["blue", "red"]
|
10678
|
-
colors.add(undefined); // ["blue", "red"]
|
10679
|
-
```
|
10807
|
+
})();
|
10680
10808
|
|
10681
|
-
@method add
|
10682
|
-
@param {Object} obj The object to add.
|
10683
|
-
@return {Ember.Set} The set itself.
|
10684
|
-
*/
|
10685
|
-
add: Ember.aliasMethod('addObject'),
|
10686
10809
|
|
10687
|
-
/**
|
10688
|
-
Removes the object from the set if it is found. If you pass a `null` value
|
10689
|
-
or an object that is already not in the set, this method will have no
|
10690
|
-
effect. This is an alias for `Ember.MutableEnumerable.removeObject()`.
|
10691
10810
|
|
10692
|
-
|
10693
|
-
|
10694
|
-
colors.remove("red"); // ["blue", "green"]
|
10695
|
-
colors.remove("purple"); // ["blue", "green"]
|
10696
|
-
colors.remove(null); // ["blue", "green"]
|
10697
|
-
```
|
10811
|
+
(function() {
|
10812
|
+
Ember.Application = Ember.Namespace.extend();
|
10698
10813
|
|
10699
|
-
|
10700
|
-
@param {Object} obj The object to remove
|
10701
|
-
@return {Ember.Set} The set itself.
|
10702
|
-
*/
|
10703
|
-
remove: Ember.aliasMethod('removeObject'),
|
10814
|
+
})();
|
10704
10815
|
|
10705
|
-
/**
|
10706
|
-
Removes the last element from the set and returns it, or `null` if it's empty.
|
10707
10816
|
|
10708
|
-
```javascript
|
10709
|
-
var colors = new Ember.Set(["green", "blue"]);
|
10710
|
-
colors.pop(); // "blue"
|
10711
|
-
colors.pop(); // "green"
|
10712
|
-
colors.pop(); // null
|
10713
|
-
```
|
10714
10817
|
|
10715
|
-
|
10716
|
-
|
10717
|
-
|
10718
|
-
|
10719
|
-
|
10720
|
-
var obj = this.length > 0 ? this[this.length-1] : null;
|
10721
|
-
this.remove(obj);
|
10722
|
-
return obj;
|
10723
|
-
},
|
10818
|
+
(function() {
|
10819
|
+
/**
|
10820
|
+
@module ember
|
10821
|
+
@submodule ember-runtime
|
10822
|
+
*/
|
10724
10823
|
|
10725
|
-
|
10726
|
-
|
10727
|
-
the set itself.
|
10824
|
+
var OUT_OF_RANGE_EXCEPTION = "Index out of range";
|
10825
|
+
var EMPTY = [];
|
10728
10826
|
|
10729
|
-
|
10827
|
+
var get = Ember.get, set = Ember.set;
|
10730
10828
|
|
10731
|
-
|
10732
|
-
|
10733
|
-
|
10734
|
-
|
10735
|
-
|
10736
|
-
```
|
10829
|
+
/**
|
10830
|
+
An ArrayProxy wraps any other object that implements `Ember.Array` and/or
|
10831
|
+
`Ember.MutableArray,` forwarding all requests. This makes it very useful for
|
10832
|
+
a number of binding use cases or other cases where being able to swap
|
10833
|
+
out the underlying array is useful.
|
10737
10834
|
|
10738
|
-
|
10739
|
-
@return {Ember.Set} The set itself.
|
10740
|
-
*/
|
10741
|
-
push: Ember.aliasMethod('addObject'),
|
10835
|
+
A simple example of usage:
|
10742
10836
|
|
10743
|
-
|
10744
|
-
|
10837
|
+
```javascript
|
10838
|
+
var pets = ['dog', 'cat', 'fish'];
|
10839
|
+
var ap = Ember.ArrayProxy.create({ content: Ember.A(pets) });
|
10745
10840
|
|
10746
|
-
|
10841
|
+
ap.get('firstObject'); // 'dog'
|
10842
|
+
ap.set('content', ['amoeba', 'paramecium']);
|
10843
|
+
ap.get('firstObject'); // 'amoeba'
|
10844
|
+
```
|
10747
10845
|
|
10748
|
-
|
10749
|
-
|
10750
|
-
|
10751
|
-
colors.shift(); // "green"
|
10752
|
-
colors.shift(); // null
|
10753
|
-
```
|
10846
|
+
This class can also be useful as a layer to transform the contents of
|
10847
|
+
an array, as they are accessed. This can be done by overriding
|
10848
|
+
`objectAtContent`:
|
10754
10849
|
|
10755
|
-
|
10756
|
-
|
10757
|
-
|
10758
|
-
|
10850
|
+
```javascript
|
10851
|
+
var pets = ['dog', 'cat', 'fish'];
|
10852
|
+
var ap = Ember.ArrayProxy.create({
|
10853
|
+
content: Ember.A(pets),
|
10854
|
+
objectAtContent: function(idx) {
|
10855
|
+
return this.get('content').objectAt(idx).toUpperCase();
|
10856
|
+
}
|
10857
|
+
});
|
10759
10858
|
|
10760
|
-
|
10761
|
-
|
10762
|
-
the set itself.
|
10859
|
+
ap.get('firstObject'); // . 'DOG'
|
10860
|
+
```
|
10763
10861
|
|
10764
|
-
|
10862
|
+
@class ArrayProxy
|
10863
|
+
@namespace Ember
|
10864
|
+
@extends Ember.Object
|
10865
|
+
@uses Ember.MutableArray
|
10866
|
+
*/
|
10867
|
+
Ember.ArrayProxy = Ember.Object.extend(Ember.MutableArray,
|
10868
|
+
/** @scope Ember.ArrayProxy.prototype */ {
|
10765
10869
|
|
10766
|
-
|
10767
|
-
|
10768
|
-
|
10769
|
-
colors.unshift("green"); // ["red", "green"]
|
10770
|
-
colors.unshift("blue"); // ["red", "green", "blue"]
|
10771
|
-
```
|
10870
|
+
/**
|
10871
|
+
The content array. Must be an object that implements `Ember.Array` and/or
|
10872
|
+
`Ember.MutableArray.`
|
10772
10873
|
|
10773
|
-
@
|
10774
|
-
@
|
10874
|
+
@property content
|
10875
|
+
@type Ember.Array
|
10775
10876
|
*/
|
10776
|
-
|
10877
|
+
content: null,
|
10777
10878
|
|
10778
10879
|
/**
|
10779
|
-
|
10780
|
-
|
10781
|
-
|
10782
|
-
|
10783
|
-
```javascript
|
10784
|
-
var colors = new Ember.Set();
|
10785
|
-
colors.addEach(["red", "green", "blue"]); // ["red", "green", "blue"]
|
10786
|
-
```
|
10880
|
+
The array that the proxy pretends to be. In the default `ArrayProxy`
|
10881
|
+
implementation, this and `content` are the same. Subclasses of `ArrayProxy`
|
10882
|
+
can override this property to provide things like sorting and filtering.
|
10787
10883
|
|
10788
|
-
|
10789
|
-
@param {Ember.Enumerable} objects the objects to add.
|
10790
|
-
@return {Ember.Set} The set itself.
|
10884
|
+
@property arrangedContent
|
10791
10885
|
*/
|
10792
|
-
|
10886
|
+
arrangedContent: Ember.computed.alias('content'),
|
10793
10887
|
|
10794
10888
|
/**
|
10795
|
-
|
10796
|
-
|
10797
|
-
|
10889
|
+
Should actually retrieve the object at the specified index from the
|
10890
|
+
content. You can override this method in subclasses to transform the
|
10891
|
+
content item to something new.
|
10798
10892
|
|
10799
|
-
|
10800
|
-
var colors = new Ember.Set(["red", "green", "blue"]);
|
10801
|
-
colors.removeEach(["red", "blue"]); // ["green"]
|
10802
|
-
```
|
10893
|
+
This method will only be called if content is non-`null`.
|
10803
10894
|
|
10804
|
-
@method
|
10805
|
-
@param {
|
10806
|
-
@return {
|
10895
|
+
@method objectAtContent
|
10896
|
+
@param {Number} idx The index to retrieve.
|
10897
|
+
@return {Object} the value or undefined if none found
|
10807
10898
|
*/
|
10808
|
-
|
10899
|
+
objectAtContent: function(idx) {
|
10900
|
+
return get(this, 'arrangedContent').objectAt(idx);
|
10901
|
+
},
|
10809
10902
|
|
10810
|
-
|
10811
|
-
|
10812
|
-
|
10903
|
+
/**
|
10904
|
+
Should actually replace the specified objects on the content array.
|
10905
|
+
You can override this method in subclasses to transform the content item
|
10906
|
+
into something new.
|
10813
10907
|
|
10814
|
-
|
10815
|
-
this._super();
|
10816
|
-
if (items) this.addObjects(items);
|
10817
|
-
},
|
10908
|
+
This method will only be called if content is non-`null`.
|
10818
10909
|
|
10819
|
-
|
10820
|
-
|
10821
|
-
|
10910
|
+
@method replaceContent
|
10911
|
+
@param {Number} idx The starting index
|
10912
|
+
@param {Number} amt The number of items to remove from the content.
|
10913
|
+
@param {Array} objects Optional array of objects to insert or null if no
|
10914
|
+
objects.
|
10915
|
+
@return {void}
|
10916
|
+
*/
|
10917
|
+
replaceContent: function(idx, amt, objects) {
|
10918
|
+
get(this, 'content').replace(idx, amt, objects);
|
10822
10919
|
},
|
10823
10920
|
|
10824
|
-
|
10825
|
-
|
10826
|
-
return this.length > 0 ? this[0] : undefined;
|
10827
|
-
}),
|
10828
|
-
|
10829
|
-
// more optimized version
|
10830
|
-
lastObject: Ember.computed(function() {
|
10831
|
-
return this.length > 0 ? this[this.length-1] : undefined;
|
10832
|
-
}),
|
10921
|
+
/**
|
10922
|
+
@private
|
10833
10923
|
|
10834
|
-
|
10835
|
-
|
10836
|
-
if (get(this, 'isFrozen')) throw new Error(Ember.FROZEN_ERROR);
|
10837
|
-
if (none(obj)) return this; // nothing to do
|
10924
|
+
Invoked when the content property is about to change. Notifies observers that the
|
10925
|
+
entire array content will change.
|
10838
10926
|
|
10839
|
-
|
10840
|
-
|
10841
|
-
|
10842
|
-
|
10927
|
+
@method _contentWillChange
|
10928
|
+
*/
|
10929
|
+
_contentWillChange: Ember.beforeObserver(function() {
|
10930
|
+
this._teardownContent();
|
10931
|
+
}, 'content'),
|
10843
10932
|
|
10844
|
-
|
10933
|
+
_teardownContent: function() {
|
10934
|
+
var content = get(this, 'content');
|
10845
10935
|
|
10846
|
-
|
10936
|
+
if (content) {
|
10937
|
+
content.removeArrayObserver(this, {
|
10938
|
+
willChange: 'contentArrayWillChange',
|
10939
|
+
didChange: 'contentArrayDidChange'
|
10940
|
+
});
|
10941
|
+
}
|
10942
|
+
},
|
10847
10943
|
|
10848
|
-
|
10849
|
-
|
10944
|
+
contentArrayWillChange: Ember.K,
|
10945
|
+
contentArrayDidChange: Ember.K,
|
10850
10946
|
|
10851
|
-
|
10852
|
-
|
10853
|
-
this[len] = obj;
|
10854
|
-
set(this, 'length', len+1);
|
10947
|
+
/**
|
10948
|
+
@private
|
10855
10949
|
|
10856
|
-
|
10857
|
-
|
10950
|
+
Invoked when the content property changes. Notifies observers that the
|
10951
|
+
entire array content has changed.
|
10858
10952
|
|
10859
|
-
|
10953
|
+
@method _contentDidChange
|
10954
|
+
*/
|
10955
|
+
_contentDidChange: Ember.observer(function() {
|
10956
|
+
var content = get(this, 'content');
|
10957
|
+
|
10958
|
+
Ember.assert("Can't set ArrayProxy's content to itself", content !== this);
|
10959
|
+
|
10960
|
+
this._setupContent();
|
10961
|
+
}, 'content'),
|
10962
|
+
|
10963
|
+
_setupContent: function() {
|
10964
|
+
var content = get(this, 'content');
|
10965
|
+
|
10966
|
+
if (content) {
|
10967
|
+
content.addArrayObserver(this, {
|
10968
|
+
willChange: 'contentArrayWillChange',
|
10969
|
+
didChange: 'contentArrayDidChange'
|
10970
|
+
});
|
10971
|
+
}
|
10860
10972
|
},
|
10861
10973
|
|
10862
|
-
|
10863
|
-
|
10864
|
-
|
10865
|
-
if (none(obj)) return this; // nothing to do
|
10974
|
+
_arrangedContentWillChange: Ember.beforeObserver(function() {
|
10975
|
+
var arrangedContent = get(this, 'arrangedContent'),
|
10976
|
+
len = arrangedContent ? get(arrangedContent, 'length') : 0;
|
10866
10977
|
|
10867
|
-
|
10868
|
-
|
10869
|
-
len = get(this, 'length'),
|
10870
|
-
isFirst = idx === 0,
|
10871
|
-
isLast = idx === len-1,
|
10872
|
-
last, removed;
|
10978
|
+
this.arrangedContentArrayWillChange(this, 0, len, undefined);
|
10979
|
+
this.arrangedContentWillChange(this);
|
10873
10980
|
|
10981
|
+
this._teardownArrangedContent(arrangedContent);
|
10982
|
+
}, 'arrangedContent'),
|
10874
10983
|
|
10875
|
-
|
10876
|
-
|
10984
|
+
_arrangedContentDidChange: Ember.observer(function() {
|
10985
|
+
var arrangedContent = get(this, 'arrangedContent'),
|
10986
|
+
len = arrangedContent ? get(arrangedContent, 'length') : 0;
|
10877
10987
|
|
10878
|
-
|
10879
|
-
if (isFirst) { Ember.propertyWillChange(this, 'firstObject'); }
|
10880
|
-
if (isLast) { Ember.propertyWillChange(this, 'lastObject'); }
|
10988
|
+
Ember.assert("Can't set ArrayProxy's content to itself", arrangedContent !== this);
|
10881
10989
|
|
10882
|
-
|
10883
|
-
if (idx < len-1) {
|
10884
|
-
last = this[len-1];
|
10885
|
-
this[idx] = last;
|
10886
|
-
this[guidFor(last)] = idx;
|
10887
|
-
}
|
10990
|
+
this._setupArrangedContent();
|
10888
10991
|
|
10889
|
-
|
10890
|
-
|
10891
|
-
|
10992
|
+
this.arrangedContentDidChange(this);
|
10993
|
+
this.arrangedContentArrayDidChange(this, 0, undefined, len);
|
10994
|
+
}, 'arrangedContent'),
|
10892
10995
|
|
10893
|
-
|
10894
|
-
|
10895
|
-
this.enumerableContentDidChange(removed, null);
|
10896
|
-
}
|
10996
|
+
_setupArrangedContent: function() {
|
10997
|
+
var arrangedContent = get(this, 'arrangedContent');
|
10897
10998
|
|
10898
|
-
|
10999
|
+
if (arrangedContent) {
|
11000
|
+
arrangedContent.addArrayObserver(this, {
|
11001
|
+
willChange: 'arrangedContentArrayWillChange',
|
11002
|
+
didChange: 'arrangedContentArrayDidChange'
|
11003
|
+
});
|
11004
|
+
}
|
10899
11005
|
},
|
10900
11006
|
|
10901
|
-
|
10902
|
-
|
10903
|
-
return this[guidFor(obj)]>=0;
|
10904
|
-
},
|
11007
|
+
_teardownArrangedContent: function() {
|
11008
|
+
var arrangedContent = get(this, 'arrangedContent');
|
10905
11009
|
|
10906
|
-
|
10907
|
-
|
10908
|
-
|
10909
|
-
|
10910
|
-
|
10911
|
-
ret[guidFor(this[loc])] = loc;
|
11010
|
+
if (arrangedContent) {
|
11011
|
+
arrangedContent.removeArrayObserver(this, {
|
11012
|
+
willChange: 'arrangedContentArrayWillChange',
|
11013
|
+
didChange: 'arrangedContentArrayDidChange'
|
11014
|
+
});
|
10912
11015
|
}
|
10913
|
-
return ret;
|
10914
11016
|
},
|
10915
11017
|
|
10916
|
-
|
10917
|
-
|
10918
|
-
for(idx = 0; idx < len; idx++) {
|
10919
|
-
array[idx] = this[idx];
|
10920
|
-
}
|
10921
|
-
return "Ember.Set<%@>".fmt(array.join(','));
|
10922
|
-
}
|
11018
|
+
arrangedContentWillChange: Ember.K,
|
11019
|
+
arrangedContentDidChange: Ember.K,
|
10923
11020
|
|
10924
|
-
|
11021
|
+
objectAt: function(idx) {
|
11022
|
+
return get(this, 'content') && this.objectAtContent(idx);
|
11023
|
+
},
|
10925
11024
|
|
10926
|
-
|
11025
|
+
length: Ember.computed(function() {
|
11026
|
+
var arrangedContent = get(this, 'arrangedContent');
|
11027
|
+
return arrangedContent ? get(arrangedContent, 'length') : 0;
|
11028
|
+
// No dependencies since Enumerable notifies length of change
|
11029
|
+
}),
|
10927
11030
|
|
11031
|
+
_replace: function(idx, amt, objects) {
|
11032
|
+
var content = get(this, 'content');
|
11033
|
+
Ember.assert('The content property of '+ this.constructor + ' should be set before modifying it', content);
|
11034
|
+
if (content) this.replaceContent(idx, amt, objects);
|
11035
|
+
return this;
|
11036
|
+
},
|
10928
11037
|
|
11038
|
+
replace: function() {
|
11039
|
+
if (get(this, 'arrangedContent') === get(this, 'content')) {
|
11040
|
+
this._replace.apply(this, arguments);
|
11041
|
+
} else {
|
11042
|
+
throw new Ember.Error("Using replace on an arranged ArrayProxy is not allowed.");
|
11043
|
+
}
|
11044
|
+
},
|
10929
11045
|
|
10930
|
-
|
10931
|
-
|
10932
|
-
|
10933
|
-
|
10934
|
-
|
11046
|
+
_insertAt: function(idx, object) {
|
11047
|
+
if (idx > get(this, 'content.length')) throw new Error(OUT_OF_RANGE_EXCEPTION);
|
11048
|
+
this._replace(idx, 0, [object]);
|
11049
|
+
return this;
|
11050
|
+
},
|
10935
11051
|
|
10936
|
-
|
10937
|
-
|
10938
|
-
|
10939
|
-
|
11052
|
+
insertAt: function(idx, object) {
|
11053
|
+
if (get(this, 'arrangedContent') === get(this, 'content')) {
|
11054
|
+
return this._insertAt(idx, object);
|
11055
|
+
} else {
|
11056
|
+
throw new Ember.Error("Using insertAt on an arranged ArrayProxy is not allowed.");
|
11057
|
+
}
|
11058
|
+
},
|
10940
11059
|
|
10941
|
-
|
10942
|
-
|
10943
|
-
|
10944
|
-
|
10945
|
-
|
10946
|
-
Ember.Object = Ember.CoreObject.extend(Ember.Observable);
|
10947
|
-
Ember.Object.toString = function() { return "Ember.Object"; };
|
11060
|
+
removeAt: function(start, len) {
|
11061
|
+
if ('number' === typeof start) {
|
11062
|
+
var content = get(this, 'content'),
|
11063
|
+
arrangedContent = get(this, 'arrangedContent'),
|
11064
|
+
indices = [], i;
|
10948
11065
|
|
10949
|
-
|
11066
|
+
if ((start < 0) || (start >= get(this, 'length'))) {
|
11067
|
+
throw new Error(OUT_OF_RANGE_EXCEPTION);
|
11068
|
+
}
|
10950
11069
|
|
11070
|
+
if (len === undefined) len = 1;
|
10951
11071
|
|
11072
|
+
// Get a list of indices in original content to remove
|
11073
|
+
for (i=start; i<start+len; i++) {
|
11074
|
+
// Use arrangedContent here so we avoid confusion with objects transformed by objectAtContent
|
11075
|
+
indices.push(content.indexOf(arrangedContent.objectAt(i)));
|
11076
|
+
}
|
10952
11077
|
|
10953
|
-
|
10954
|
-
|
10955
|
-
@module ember
|
10956
|
-
@submodule ember-runtime
|
10957
|
-
*/
|
11078
|
+
// Replace in reverse order since indices will change
|
11079
|
+
indices.sort(function(a,b) { return b - a; });
|
10958
11080
|
|
10959
|
-
|
11081
|
+
Ember.beginPropertyChanges();
|
11082
|
+
for (i=0; i<indices.length; i++) {
|
11083
|
+
this._replace(indices[i], 1, EMPTY);
|
11084
|
+
}
|
11085
|
+
Ember.endPropertyChanges();
|
11086
|
+
}
|
10960
11087
|
|
10961
|
-
|
10962
|
-
|
10963
|
-
such as an application or framework. Create a namespace anytime you want
|
10964
|
-
to define one of these new containers.
|
11088
|
+
return this ;
|
11089
|
+
},
|
10965
11090
|
|
10966
|
-
|
11091
|
+
pushObject: function(obj) {
|
11092
|
+
this._insertAt(get(this, 'content.length'), obj) ;
|
11093
|
+
return obj ;
|
11094
|
+
},
|
10967
11095
|
|
10968
|
-
|
10969
|
-
|
10970
|
-
|
10971
|
-
}
|
10972
|
-
```
|
11096
|
+
pushObjects: function(objects) {
|
11097
|
+
this._replace(get(this, 'length'), 0, objects);
|
11098
|
+
return this;
|
11099
|
+
},
|
10973
11100
|
|
10974
|
-
|
10975
|
-
|
10976
|
-
@extends Ember.Object
|
10977
|
-
*/
|
10978
|
-
var Namespace = Ember.Namespace = Ember.Object.extend({
|
10979
|
-
isNamespace: true,
|
11101
|
+
setObjects: function(objects) {
|
11102
|
+
if (objects.length === 0) return this.clear();
|
10980
11103
|
|
10981
|
-
|
10982
|
-
|
10983
|
-
|
11104
|
+
var len = get(this, 'length');
|
11105
|
+
this._replace(0, len, objects);
|
11106
|
+
return this;
|
10984
11107
|
},
|
10985
11108
|
|
10986
|
-
|
10987
|
-
|
10988
|
-
|
11109
|
+
unshiftObject: function(obj) {
|
11110
|
+
this._insertAt(0, obj) ;
|
11111
|
+
return obj ;
|
11112
|
+
},
|
10989
11113
|
|
10990
|
-
|
10991
|
-
|
11114
|
+
unshiftObjects: function(objects) {
|
11115
|
+
this._replace(0, 0, objects);
|
11116
|
+
return this;
|
10992
11117
|
},
|
10993
11118
|
|
10994
|
-
|
10995
|
-
|
11119
|
+
slice: function() {
|
11120
|
+
var arr = this.toArray();
|
11121
|
+
return arr.slice.apply(arr, arguments);
|
10996
11122
|
},
|
10997
11123
|
|
10998
|
-
|
10999
|
-
|
11000
|
-
|
11001
|
-
namespaces.splice(indexOf.call(namespaces, this), 1);
|
11002
|
-
this._super();
|
11003
|
-
}
|
11004
|
-
});
|
11124
|
+
arrangedContentArrayWillChange: function(item, idx, removedCnt, addedCnt) {
|
11125
|
+
this.arrayContentWillChange(idx, removedCnt, addedCnt);
|
11126
|
+
},
|
11005
11127
|
|
11006
|
-
|
11007
|
-
|
11008
|
-
|
11009
|
-
PROCESSED: false,
|
11010
|
-
processAll: processAllNamespaces,
|
11011
|
-
byName: function(name) {
|
11012
|
-
if (!Ember.BOOTED) {
|
11013
|
-
processAllNamespaces();
|
11014
|
-
}
|
11128
|
+
arrangedContentArrayDidChange: function(item, idx, removedCnt, addedCnt) {
|
11129
|
+
this.arrayContentDidChange(idx, removedCnt, addedCnt);
|
11130
|
+
},
|
11015
11131
|
|
11016
|
-
|
11132
|
+
init: function() {
|
11133
|
+
this._super();
|
11134
|
+
this._setupContent();
|
11135
|
+
this._setupArrangedContent();
|
11136
|
+
},
|
11137
|
+
|
11138
|
+
willDestroy: function() {
|
11139
|
+
this._teardownArrangedContent();
|
11140
|
+
this._teardownContent();
|
11017
11141
|
}
|
11018
11142
|
});
|
11019
11143
|
|
11020
|
-
var NAMESPACES_BY_ID = Namespace.NAMESPACES_BY_ID;
|
11021
11144
|
|
11022
|
-
|
11023
|
-
guidFor = Ember.guidFor;
|
11145
|
+
})();
|
11024
11146
|
|
11025
|
-
function processNamespace(paths, root, seen) {
|
11026
|
-
var idx = paths.length;
|
11027
11147
|
|
11028
|
-
NAMESPACES_BY_ID[paths.join('.')] = root;
|
11029
11148
|
|
11030
|
-
|
11031
|
-
|
11032
|
-
|
11033
|
-
|
11034
|
-
|
11035
|
-
// If we are processing the `Ember` namespace, for example, the
|
11036
|
-
// `paths` will start with `["Ember"]`. Every iteration through
|
11037
|
-
// the loop will update the **second** element of this list with
|
11038
|
-
// the key, so processing `Ember.View` will make the Array
|
11039
|
-
// `['Ember', 'View']`.
|
11040
|
-
paths[idx] = key;
|
11041
|
-
|
11042
|
-
// If we have found an unprocessed class
|
11043
|
-
if (obj && obj.toString === classToString) {
|
11044
|
-
// Replace the class' `toString` with the dot-separated path
|
11045
|
-
// and set its `NAME_KEY`
|
11046
|
-
obj.toString = makeToString(paths.join('.'));
|
11047
|
-
obj[NAME_KEY] = paths.join('.');
|
11149
|
+
(function() {
|
11150
|
+
/**
|
11151
|
+
@module ember
|
11152
|
+
@submodule ember-runtime
|
11153
|
+
*/
|
11048
11154
|
|
11049
|
-
|
11050
|
-
|
11051
|
-
|
11052
|
-
|
11053
|
-
|
11155
|
+
var get = Ember.get,
|
11156
|
+
set = Ember.set,
|
11157
|
+
fmt = Ember.String.fmt,
|
11158
|
+
addBeforeObserver = Ember.addBeforeObserver,
|
11159
|
+
addObserver = Ember.addObserver,
|
11160
|
+
removeBeforeObserver = Ember.removeBeforeObserver,
|
11161
|
+
removeObserver = Ember.removeObserver,
|
11162
|
+
propertyWillChange = Ember.propertyWillChange,
|
11163
|
+
propertyDidChange = Ember.propertyDidChange;
|
11054
11164
|
|
11055
|
-
|
11056
|
-
|
11057
|
-
|
11058
|
-
|
11165
|
+
function contentPropertyWillChange(content, contentKey) {
|
11166
|
+
var key = contentKey.slice(8); // remove "content."
|
11167
|
+
if (key in this) { return; } // if shadowed in proxy
|
11168
|
+
propertyWillChange(this, key);
|
11169
|
+
}
|
11059
11170
|
|
11060
|
-
|
11171
|
+
function contentPropertyDidChange(content, contentKey) {
|
11172
|
+
var key = contentKey.slice(8); // remove "content."
|
11173
|
+
if (key in this) { return; } // if shadowed in proxy
|
11174
|
+
propertyDidChange(this, key);
|
11061
11175
|
}
|
11062
11176
|
|
11063
|
-
|
11064
|
-
|
11177
|
+
/**
|
11178
|
+
`Ember.ObjectProxy` forwards all properties not defined by the proxy itself
|
11179
|
+
to a proxied `content` object.
|
11065
11180
|
|
11066
|
-
|
11181
|
+
```javascript
|
11182
|
+
object = Ember.Object.create({
|
11183
|
+
name: 'Foo'
|
11184
|
+
});
|
11067
11185
|
|
11068
|
-
|
11069
|
-
|
11070
|
-
|
11186
|
+
proxy = Ember.ObjectProxy.create({
|
11187
|
+
content: object
|
11188
|
+
});
|
11071
11189
|
|
11072
|
-
|
11073
|
-
|
11074
|
-
|
11075
|
-
|
11076
|
-
if (lookup.hasOwnProperty && !lookup.hasOwnProperty(prop)) { continue; }
|
11190
|
+
// Access and change existing properties
|
11191
|
+
proxy.get('name') // 'Foo'
|
11192
|
+
proxy.set('name', 'Bar');
|
11193
|
+
object.get('name') // 'Bar'
|
11077
11194
|
|
11078
|
-
|
11079
|
-
|
11080
|
-
|
11081
|
-
|
11082
|
-
isNamespace = obj && obj.isNamespace;
|
11083
|
-
} catch (e) {
|
11084
|
-
continue;
|
11085
|
-
}
|
11195
|
+
// Create new 'description' property on `object`
|
11196
|
+
proxy.set('description', 'Foo is a whizboo baz');
|
11197
|
+
object.get('description') // 'Foo is a whizboo baz'
|
11198
|
+
```
|
11086
11199
|
|
11087
|
-
|
11088
|
-
|
11089
|
-
obj[NAME_KEY] = prop;
|
11090
|
-
}
|
11091
|
-
}
|
11092
|
-
}
|
11200
|
+
While `content` is unset, setting a property to be delegated will throw an
|
11201
|
+
Error.
|
11093
11202
|
|
11094
|
-
|
11203
|
+
```javascript
|
11204
|
+
proxy = Ember.ObjectProxy.create({
|
11205
|
+
content: null,
|
11206
|
+
flag: null
|
11207
|
+
});
|
11208
|
+
proxy.set('flag', true);
|
11209
|
+
proxy.get('flag'); // true
|
11210
|
+
proxy.get('foo'); // undefined
|
11211
|
+
proxy.set('foo', 'data'); // throws Error
|
11212
|
+
```
|
11095
11213
|
|
11096
|
-
|
11097
|
-
var superclass = mixin.superclass;
|
11098
|
-
if (superclass) {
|
11099
|
-
if (superclass[NAME_KEY]) { return superclass[NAME_KEY]; }
|
11100
|
-
else { return superClassString(superclass); }
|
11101
|
-
} else {
|
11102
|
-
return;
|
11103
|
-
}
|
11104
|
-
}
|
11214
|
+
Delegated properties can be bound to and will change when content is updated.
|
11105
11215
|
|
11106
|
-
|
11107
|
-
if (!Ember.BOOTED && !this[NAME_KEY]) {
|
11108
|
-
processAllNamespaces();
|
11109
|
-
}
|
11216
|
+
Computed properties on the proxy itself can depend on delegated properties.
|
11110
11217
|
|
11111
|
-
|
11218
|
+
```javascript
|
11219
|
+
ProxyWithComputedProperty = Ember.ObjectProxy.extend({
|
11220
|
+
fullName: function () {
|
11221
|
+
var firstName = this.get('firstName'),
|
11222
|
+
lastName = this.get('lastName');
|
11223
|
+
if (firstName && lastName) {
|
11224
|
+
return firstName + ' ' + lastName;
|
11225
|
+
}
|
11226
|
+
return firstName || lastName;
|
11227
|
+
}.property('firstName', 'lastName')
|
11228
|
+
});
|
11112
11229
|
|
11113
|
-
|
11114
|
-
ret = this[NAME_KEY];
|
11115
|
-
} else {
|
11116
|
-
var str = superClassString(this);
|
11117
|
-
if (str) {
|
11118
|
-
ret = "(subclass of " + str + ")";
|
11119
|
-
} else {
|
11120
|
-
ret = "(unknown mixin)";
|
11121
|
-
}
|
11122
|
-
this.toString = makeToString(ret);
|
11123
|
-
}
|
11230
|
+
proxy = ProxyWithComputedProperty.create();
|
11124
11231
|
|
11125
|
-
|
11126
|
-
|
11232
|
+
proxy.get('fullName'); // undefined
|
11233
|
+
proxy.set('content', {
|
11234
|
+
firstName: 'Tom', lastName: 'Dale'
|
11235
|
+
}); // triggers property change for fullName on proxy
|
11127
11236
|
|
11128
|
-
|
11129
|
-
|
11130
|
-
unprocessedMixins = Ember.anyUnprocessedMixins;
|
11237
|
+
proxy.get('fullName'); // 'Tom Dale'
|
11238
|
+
```
|
11131
11239
|
|
11132
|
-
|
11133
|
-
|
11134
|
-
|
11135
|
-
|
11240
|
+
@class ObjectProxy
|
11241
|
+
@namespace Ember
|
11242
|
+
@extends Ember.Object
|
11243
|
+
*/
|
11244
|
+
Ember.ObjectProxy = Ember.Object.extend(
|
11245
|
+
/** @scope Ember.ObjectProxy.prototype */ {
|
11246
|
+
/**
|
11247
|
+
The object whose properties will be forwarded.
|
11136
11248
|
|
11137
|
-
|
11138
|
-
|
11139
|
-
|
11140
|
-
|
11141
|
-
|
11142
|
-
|
11249
|
+
@property content
|
11250
|
+
@type Ember.Object
|
11251
|
+
@default null
|
11252
|
+
*/
|
11253
|
+
content: null,
|
11254
|
+
_contentDidChange: Ember.observer(function() {
|
11255
|
+
Ember.assert("Can't set ObjectProxy's content to itself", this.get('content') !== this);
|
11256
|
+
}, 'content'),
|
11143
11257
|
|
11144
|
-
|
11145
|
-
}
|
11146
|
-
}
|
11258
|
+
isTruthy: Ember.computed.bool('content'),
|
11147
11259
|
|
11148
|
-
|
11149
|
-
return function() { return ret; };
|
11150
|
-
}
|
11260
|
+
_debugContainerKey: null,
|
11151
11261
|
|
11152
|
-
|
11262
|
+
willWatchProperty: function (key) {
|
11263
|
+
var contentKey = 'content.' + key;
|
11264
|
+
addBeforeObserver(this, contentKey, null, contentPropertyWillChange);
|
11265
|
+
addObserver(this, contentKey, null, contentPropertyDidChange);
|
11266
|
+
},
|
11153
11267
|
|
11154
|
-
|
11268
|
+
didUnwatchProperty: function (key) {
|
11269
|
+
var contentKey = 'content.' + key;
|
11270
|
+
removeBeforeObserver(this, contentKey, null, contentPropertyWillChange);
|
11271
|
+
removeObserver(this, contentKey, null, contentPropertyDidChange);
|
11272
|
+
},
|
11155
11273
|
|
11274
|
+
unknownProperty: function (key) {
|
11275
|
+
var content = get(this, 'content');
|
11276
|
+
if (content) {
|
11277
|
+
return get(content, key);
|
11278
|
+
}
|
11279
|
+
},
|
11156
11280
|
|
11281
|
+
setUnknownProperty: function (key, value) {
|
11282
|
+
var content = get(this, 'content');
|
11283
|
+
Ember.assert(fmt("Cannot delegate set('%@', %@) to the 'content' property of object proxy %@: its 'content' is undefined.", [key, value, this]), content);
|
11284
|
+
return set(content, key, value);
|
11285
|
+
}
|
11286
|
+
});
|
11157
11287
|
|
11158
|
-
(
|
11159
|
-
|
11288
|
+
Ember.ObjectProxy.reopenClass({
|
11289
|
+
create: function () {
|
11290
|
+
var mixin, prototype, i, l, properties, keyName;
|
11291
|
+
if (arguments.length) {
|
11292
|
+
prototype = this.proto();
|
11293
|
+
for (i = 0, l = arguments.length; i < l; i++) {
|
11294
|
+
properties = arguments[i];
|
11295
|
+
for (keyName in properties) {
|
11296
|
+
if (!properties.hasOwnProperty(keyName) || keyName in prototype) { continue; }
|
11297
|
+
if (!mixin) mixin = {};
|
11298
|
+
mixin[keyName] = null;
|
11299
|
+
}
|
11300
|
+
}
|
11301
|
+
if (mixin) this._initMixins([mixin]);
|
11302
|
+
}
|
11303
|
+
return this._super.apply(this, arguments);
|
11304
|
+
}
|
11305
|
+
});
|
11160
11306
|
|
11161
11307
|
})();
|
11162
11308
|
|
@@ -11169,237 +11315,203 @@ Ember.Application = Ember.Namespace.extend();
|
|
11169
11315
|
*/
|
11170
11316
|
|
11171
11317
|
|
11172
|
-
var get = Ember.get,
|
11173
|
-
|
11174
|
-
/**
|
11175
|
-
An ArrayProxy wraps any other object that implements `Ember.Array` and/or
|
11176
|
-
`Ember.MutableArray,` forwarding all requests. This makes it very useful for
|
11177
|
-
a number of binding use cases or other cases where being able to swap
|
11178
|
-
out the underlying array is useful.
|
11318
|
+
var set = Ember.set, get = Ember.get, guidFor = Ember.guidFor;
|
11319
|
+
var forEach = Ember.EnumerableUtils.forEach;
|
11179
11320
|
|
11180
|
-
|
11321
|
+
var EachArray = Ember.Object.extend(Ember.Array, {
|
11181
11322
|
|
11182
|
-
|
11183
|
-
|
11184
|
-
|
11323
|
+
init: function(content, keyName, owner) {
|
11324
|
+
this._super();
|
11325
|
+
this._keyName = keyName;
|
11326
|
+
this._owner = owner;
|
11327
|
+
this._content = content;
|
11328
|
+
},
|
11185
11329
|
|
11186
|
-
|
11187
|
-
|
11188
|
-
|
11189
|
-
|
11190
|
-
|
11191
|
-
This class can also be useful as a layer to transform the contents of
|
11192
|
-
an array, as they are accessed. This can be done by overriding
|
11193
|
-
`objectAtContent`:
|
11330
|
+
objectAt: function(idx) {
|
11331
|
+
var item = this._content.objectAt(idx);
|
11332
|
+
return item && get(item, this._keyName);
|
11333
|
+
},
|
11194
11334
|
|
11195
|
-
|
11196
|
-
|
11197
|
-
|
11198
|
-
|
11199
|
-
objectAtContent: function(idx) {
|
11200
|
-
return this.get('content').objectAt(idx).toUpperCase();
|
11201
|
-
}
|
11202
|
-
});
|
11335
|
+
length: Ember.computed(function() {
|
11336
|
+
var content = this._content;
|
11337
|
+
return content ? get(content, 'length') : 0;
|
11338
|
+
})
|
11203
11339
|
|
11204
|
-
|
11205
|
-
```
|
11340
|
+
});
|
11206
11341
|
|
11207
|
-
|
11208
|
-
@namespace Ember
|
11209
|
-
@extends Ember.Object
|
11210
|
-
@uses Ember.MutableArray
|
11211
|
-
*/
|
11212
|
-
Ember.ArrayProxy = Ember.Object.extend(Ember.MutableArray,
|
11213
|
-
/** @scope Ember.ArrayProxy.prototype */ {
|
11342
|
+
var IS_OBSERVER = /^.+:(before|change)$/;
|
11214
11343
|
|
11215
|
-
|
11216
|
-
|
11217
|
-
|
11344
|
+
function addObserverForContentKey(content, keyName, proxy, idx, loc) {
|
11345
|
+
var objects = proxy._objects, guid;
|
11346
|
+
if (!objects) objects = proxy._objects = {};
|
11218
11347
|
|
11219
|
-
|
11220
|
-
|
11221
|
-
|
11222
|
-
|
11348
|
+
while(--loc>=idx) {
|
11349
|
+
var item = content.objectAt(loc);
|
11350
|
+
if (item) {
|
11351
|
+
Ember.addBeforeObserver(item, keyName, proxy, 'contentKeyWillChange');
|
11352
|
+
Ember.addObserver(item, keyName, proxy, 'contentKeyDidChange');
|
11223
11353
|
|
11224
|
-
|
11225
|
-
|
11226
|
-
|
11227
|
-
|
11354
|
+
// keep track of the index each item was found at so we can map
|
11355
|
+
// it back when the obj changes.
|
11356
|
+
guid = guidFor(item);
|
11357
|
+
if (!objects[guid]) objects[guid] = [];
|
11358
|
+
objects[guid].push(loc);
|
11359
|
+
}
|
11360
|
+
}
|
11361
|
+
}
|
11228
11362
|
|
11229
|
-
|
11230
|
-
|
11231
|
-
|
11363
|
+
function removeObserverForContentKey(content, keyName, proxy, idx, loc) {
|
11364
|
+
var objects = proxy._objects;
|
11365
|
+
if (!objects) objects = proxy._objects = {};
|
11366
|
+
var indicies, guid;
|
11232
11367
|
|
11233
|
-
|
11234
|
-
|
11235
|
-
|
11236
|
-
|
11368
|
+
while(--loc>=idx) {
|
11369
|
+
var item = content.objectAt(loc);
|
11370
|
+
if (item) {
|
11371
|
+
Ember.removeBeforeObserver(item, keyName, proxy, 'contentKeyWillChange');
|
11372
|
+
Ember.removeObserver(item, keyName, proxy, 'contentKeyDidChange');
|
11237
11373
|
|
11238
|
-
|
11374
|
+
guid = guidFor(item);
|
11375
|
+
indicies = objects[guid];
|
11376
|
+
indicies[indicies.indexOf(loc)] = null;
|
11377
|
+
}
|
11378
|
+
}
|
11379
|
+
}
|
11239
11380
|
|
11240
|
-
|
11241
|
-
|
11242
|
-
|
11243
|
-
|
11244
|
-
objectAtContent: function(idx) {
|
11245
|
-
return get(this, 'arrangedContent').objectAt(idx);
|
11246
|
-
},
|
11381
|
+
/**
|
11382
|
+
This is the object instance returned when you get the `@each` property on an
|
11383
|
+
array. It uses the unknownProperty handler to automatically create
|
11384
|
+
EachArray instances for property names.
|
11247
11385
|
|
11248
|
-
|
11249
|
-
|
11250
|
-
|
11251
|
-
|
11386
|
+
@private
|
11387
|
+
@class EachProxy
|
11388
|
+
@namespace Ember
|
11389
|
+
@extends Ember.Object
|
11390
|
+
*/
|
11391
|
+
Ember.EachProxy = Ember.Object.extend({
|
11252
11392
|
|
11253
|
-
|
11393
|
+
init: function(content) {
|
11394
|
+
this._super();
|
11395
|
+
this._content = content;
|
11396
|
+
content.addArrayObserver(this);
|
11254
11397
|
|
11255
|
-
|
11256
|
-
|
11257
|
-
|
11258
|
-
|
11259
|
-
|
11260
|
-
@return {void}
|
11261
|
-
*/
|
11262
|
-
replaceContent: function(idx, amt, objects) {
|
11263
|
-
get(this, 'content').replace(idx, amt, objects);
|
11398
|
+
// in case someone is already observing some keys make sure they are
|
11399
|
+
// added
|
11400
|
+
forEach(Ember.watchedEvents(this), function(eventName) {
|
11401
|
+
this.didAddListener(eventName);
|
11402
|
+
}, this);
|
11264
11403
|
},
|
11265
11404
|
|
11266
11405
|
/**
|
11267
|
-
|
11268
|
-
|
11269
|
-
Invoked when the content property is about to change. Notifies observers that the
|
11270
|
-
entire array content will change.
|
11406
|
+
You can directly access mapped properties by simply requesting them.
|
11407
|
+
The `unknownProperty` handler will generate an EachArray of each item.
|
11271
11408
|
|
11272
|
-
@method
|
11409
|
+
@method unknownProperty
|
11410
|
+
@param keyName {String}
|
11411
|
+
@param value {anything}
|
11273
11412
|
*/
|
11274
|
-
|
11275
|
-
|
11276
|
-
|
11277
|
-
|
11278
|
-
|
11279
|
-
|
11280
|
-
|
11281
|
-
if (content) {
|
11282
|
-
content.removeArrayObserver(this, {
|
11283
|
-
willChange: 'contentArrayWillChange',
|
11284
|
-
didChange: 'contentArrayDidChange'
|
11285
|
-
});
|
11286
|
-
}
|
11413
|
+
unknownProperty: function(keyName, value) {
|
11414
|
+
var ret;
|
11415
|
+
ret = new EachArray(this._content, keyName, this);
|
11416
|
+
Ember.defineProperty(this, keyName, null, ret);
|
11417
|
+
this.beginObservingContentKey(keyName);
|
11418
|
+
return ret;
|
11287
11419
|
},
|
11288
11420
|
|
11289
|
-
|
11290
|
-
|
11291
|
-
|
11292
|
-
/**
|
11293
|
-
@private
|
11294
|
-
|
11295
|
-
Invoked when the content property changes. Notifies observers that the
|
11296
|
-
entire array content has changed.
|
11421
|
+
// ..........................................................
|
11422
|
+
// ARRAY CHANGES
|
11423
|
+
// Invokes whenever the content array itself changes.
|
11297
11424
|
|
11298
|
-
|
11299
|
-
|
11300
|
-
_contentDidChange: Ember.observer(function() {
|
11301
|
-
var content = get(this, 'content');
|
11425
|
+
arrayWillChange: function(content, idx, removedCnt, addedCnt) {
|
11426
|
+
var keys = this._keys, key, lim;
|
11302
11427
|
|
11303
|
-
|
11428
|
+
lim = removedCnt>0 ? idx+removedCnt : -1;
|
11429
|
+
Ember.beginPropertyChanges(this);
|
11304
11430
|
|
11305
|
-
|
11306
|
-
|
11431
|
+
for(key in keys) {
|
11432
|
+
if (!keys.hasOwnProperty(key)) { continue; }
|
11307
11433
|
|
11308
|
-
|
11309
|
-
var content = get(this, 'content');
|
11434
|
+
if (lim>0) removeObserverForContentKey(content, key, this, idx, lim);
|
11310
11435
|
|
11311
|
-
|
11312
|
-
content.addArrayObserver(this, {
|
11313
|
-
willChange: 'contentArrayWillChange',
|
11314
|
-
didChange: 'contentArrayDidChange'
|
11315
|
-
});
|
11436
|
+
Ember.propertyWillChange(this, key);
|
11316
11437
|
}
|
11317
|
-
},
|
11318
11438
|
|
11319
|
-
|
11320
|
-
|
11321
|
-
|
11439
|
+
Ember.propertyWillChange(this._content, '@each');
|
11440
|
+
Ember.endPropertyChanges(this);
|
11441
|
+
},
|
11322
11442
|
|
11323
|
-
|
11324
|
-
this.
|
11443
|
+
arrayDidChange: function(content, idx, removedCnt, addedCnt) {
|
11444
|
+
var keys = this._keys, key, lim;
|
11325
11445
|
|
11326
|
-
|
11327
|
-
|
11446
|
+
lim = addedCnt>0 ? idx+addedCnt : -1;
|
11447
|
+
Ember.beginPropertyChanges(this);
|
11328
11448
|
|
11329
|
-
|
11330
|
-
|
11331
|
-
len = arrangedContent ? get(arrangedContent, 'length') : 0;
|
11449
|
+
for(key in keys) {
|
11450
|
+
if (!keys.hasOwnProperty(key)) { continue; }
|
11332
11451
|
|
11333
|
-
|
11452
|
+
if (lim>0) addObserverForContentKey(content, key, this, idx, lim);
|
11334
11453
|
|
11335
|
-
|
11454
|
+
Ember.propertyDidChange(this, key);
|
11455
|
+
}
|
11336
11456
|
|
11337
|
-
|
11338
|
-
|
11339
|
-
},
|
11457
|
+
Ember.propertyDidChange(this._content, '@each');
|
11458
|
+
Ember.endPropertyChanges(this);
|
11459
|
+
},
|
11340
11460
|
|
11341
|
-
|
11342
|
-
|
11461
|
+
// ..........................................................
|
11462
|
+
// LISTEN FOR NEW OBSERVERS AND OTHER EVENT LISTENERS
|
11463
|
+
// Start monitoring keys based on who is listening...
|
11343
11464
|
|
11344
|
-
|
11345
|
-
|
11346
|
-
|
11347
|
-
didChange: 'arrangedContentArrayDidChange'
|
11348
|
-
});
|
11465
|
+
didAddListener: function(eventName) {
|
11466
|
+
if (IS_OBSERVER.test(eventName)) {
|
11467
|
+
this.beginObservingContentKey(eventName.slice(0, -7));
|
11349
11468
|
}
|
11350
11469
|
},
|
11351
11470
|
|
11352
|
-
|
11353
|
-
|
11354
|
-
|
11355
|
-
if (arrangedContent) {
|
11356
|
-
arrangedContent.removeArrayObserver(this, {
|
11357
|
-
willChange: 'arrangedContentArrayWillChange',
|
11358
|
-
didChange: 'arrangedContentArrayDidChange'
|
11359
|
-
});
|
11471
|
+
didRemoveListener: function(eventName) {
|
11472
|
+
if (IS_OBSERVER.test(eventName)) {
|
11473
|
+
this.stopObservingContentKey(eventName.slice(0, -7));
|
11360
11474
|
}
|
11361
11475
|
},
|
11362
11476
|
|
11363
|
-
|
11364
|
-
|
11477
|
+
// ..........................................................
|
11478
|
+
// CONTENT KEY OBSERVING
|
11479
|
+
// Actual watch keys on the source content.
|
11365
11480
|
|
11366
|
-
|
11367
|
-
|
11481
|
+
beginObservingContentKey: function(keyName) {
|
11482
|
+
var keys = this._keys;
|
11483
|
+
if (!keys) keys = this._keys = {};
|
11484
|
+
if (!keys[keyName]) {
|
11485
|
+
keys[keyName] = 1;
|
11486
|
+
var content = this._content,
|
11487
|
+
len = get(content, 'length');
|
11488
|
+
addObserverForContentKey(content, keyName, this, 0, len);
|
11489
|
+
} else {
|
11490
|
+
keys[keyName]++;
|
11491
|
+
}
|
11368
11492
|
},
|
11369
11493
|
|
11370
|
-
|
11371
|
-
var
|
11372
|
-
|
11373
|
-
|
11374
|
-
|
11375
|
-
|
11376
|
-
|
11377
|
-
Ember.assert('The content property of '+ this.constructor + ' should be set before modifying it', this.get('content'));
|
11378
|
-
if (get(this, 'content')) this.replaceContent(idx, amt, objects);
|
11379
|
-
return this;
|
11380
|
-
},
|
11381
|
-
|
11382
|
-
arrangedContentArrayWillChange: function(item, idx, removedCnt, addedCnt) {
|
11383
|
-
this.arrayContentWillChange(idx, removedCnt, addedCnt);
|
11384
|
-
},
|
11385
|
-
|
11386
|
-
arrangedContentArrayDidChange: function(item, idx, removedCnt, addedCnt) {
|
11387
|
-
this.arrayContentDidChange(idx, removedCnt, addedCnt);
|
11494
|
+
stopObservingContentKey: function(keyName) {
|
11495
|
+
var keys = this._keys;
|
11496
|
+
if (keys && (keys[keyName]>0) && (--keys[keyName]<=0)) {
|
11497
|
+
var content = this._content,
|
11498
|
+
len = get(content, 'length');
|
11499
|
+
removeObserverForContentKey(content, keyName, this, 0, len);
|
11500
|
+
}
|
11388
11501
|
},
|
11389
11502
|
|
11390
|
-
|
11391
|
-
|
11392
|
-
this._setupContent();
|
11393
|
-
this._setupArrangedContent();
|
11503
|
+
contentKeyWillChange: function(obj, keyName) {
|
11504
|
+
Ember.propertyWillChange(this, keyName);
|
11394
11505
|
},
|
11395
11506
|
|
11396
|
-
|
11397
|
-
|
11398
|
-
this._teardownContent();
|
11507
|
+
contentKeyDidChange: function(obj, keyName) {
|
11508
|
+
Ember.propertyDidChange(this, keyName);
|
11399
11509
|
}
|
11510
|
+
|
11400
11511
|
});
|
11401
11512
|
|
11402
11513
|
|
11514
|
+
|
11403
11515
|
})();
|
11404
11516
|
|
11405
11517
|
|
@@ -11410,524 +11522,611 @@ Ember.ArrayProxy = Ember.Object.extend(Ember.MutableArray,
|
|
11410
11522
|
@submodule ember-runtime
|
11411
11523
|
*/
|
11412
11524
|
|
11413
|
-
var get = Ember.get,
|
11414
|
-
set = Ember.set,
|
11415
|
-
fmt = Ember.String.fmt,
|
11416
|
-
addBeforeObserver = Ember.addBeforeObserver,
|
11417
|
-
addObserver = Ember.addObserver,
|
11418
|
-
removeBeforeObserver = Ember.removeBeforeObserver,
|
11419
|
-
removeObserver = Ember.removeObserver,
|
11420
|
-
propertyWillChange = Ember.propertyWillChange,
|
11421
|
-
propertyDidChange = Ember.propertyDidChange;
|
11422
|
-
|
11423
|
-
function contentPropertyWillChange(content, contentKey) {
|
11424
|
-
var key = contentKey.slice(8); // remove "content."
|
11425
|
-
if (key in this) { return; } // if shadowed in proxy
|
11426
|
-
propertyWillChange(this, key);
|
11427
|
-
}
|
11428
|
-
|
11429
|
-
function contentPropertyDidChange(content, contentKey) {
|
11430
|
-
var key = contentKey.slice(8); // remove "content."
|
11431
|
-
if (key in this) { return; } // if shadowed in proxy
|
11432
|
-
propertyDidChange(this, key);
|
11433
|
-
}
|
11434
|
-
|
11435
|
-
/**
|
11436
|
-
`Ember.ObjectProxy` forwards all properties not defined by the proxy itself
|
11437
|
-
to a proxied `content` object.
|
11438
|
-
|
11439
|
-
```javascript
|
11440
|
-
object = Ember.Object.create({
|
11441
|
-
name: 'Foo'
|
11442
|
-
});
|
11443
|
-
|
11444
|
-
proxy = Ember.ObjectProxy.create({
|
11445
|
-
content: object
|
11446
|
-
});
|
11447
11525
|
|
11448
|
-
|
11449
|
-
proxy.get('name') // 'Foo'
|
11450
|
-
proxy.set('name', 'Bar');
|
11451
|
-
object.get('name') // 'Bar'
|
11526
|
+
var get = Ember.get, set = Ember.set;
|
11452
11527
|
|
11453
|
-
|
11454
|
-
|
11455
|
-
|
11456
|
-
|
11528
|
+
// Add Ember.Array to Array.prototype. Remove methods with native
|
11529
|
+
// implementations and supply some more optimized versions of generic methods
|
11530
|
+
// because they are so common.
|
11531
|
+
var NativeArray = Ember.Mixin.create(Ember.MutableArray, Ember.Observable, Ember.Copyable, {
|
11457
11532
|
|
11458
|
-
|
11459
|
-
|
11533
|
+
// because length is a built-in property we need to know to just get the
|
11534
|
+
// original property.
|
11535
|
+
get: function(key) {
|
11536
|
+
if (key==='length') return this.length;
|
11537
|
+
else if ('number' === typeof key) return this[key];
|
11538
|
+
else return this._super(key);
|
11539
|
+
},
|
11460
11540
|
|
11461
|
-
|
11462
|
-
|
11463
|
-
|
11464
|
-
flag: null
|
11465
|
-
});
|
11466
|
-
proxy.set('flag', true);
|
11467
|
-
proxy.get('flag'); // true
|
11468
|
-
proxy.get('foo'); // undefined
|
11469
|
-
proxy.set('foo', 'data'); // throws Error
|
11470
|
-
```
|
11541
|
+
objectAt: function(idx) {
|
11542
|
+
return this[idx];
|
11543
|
+
},
|
11471
11544
|
|
11472
|
-
|
11545
|
+
// primitive for array support.
|
11546
|
+
replace: function(idx, amt, objects) {
|
11473
11547
|
|
11474
|
-
|
11548
|
+
if (this.isFrozen) throw Ember.FROZEN_ERROR ;
|
11475
11549
|
|
11476
|
-
|
11477
|
-
|
11478
|
-
|
11479
|
-
|
11480
|
-
|
11481
|
-
if (firstName && lastName) {
|
11482
|
-
return firstName + ' ' + lastName;
|
11483
|
-
}
|
11484
|
-
return firstName || lastName;
|
11485
|
-
}.property('firstName', 'lastName')
|
11486
|
-
});
|
11550
|
+
// if we replaced exactly the same number of items, then pass only the
|
11551
|
+
// replaced range. Otherwise, pass the full remaining array length
|
11552
|
+
// since everything has shifted
|
11553
|
+
var len = objects ? get(objects, 'length') : 0;
|
11554
|
+
this.arrayContentWillChange(idx, amt, len);
|
11487
11555
|
|
11488
|
-
|
11556
|
+
if (!objects || objects.length === 0) {
|
11557
|
+
this.splice(idx, amt) ;
|
11558
|
+
} else {
|
11559
|
+
var args = [idx, amt].concat(objects) ;
|
11560
|
+
this.splice.apply(this,args) ;
|
11561
|
+
}
|
11489
11562
|
|
11490
|
-
|
11491
|
-
|
11492
|
-
|
11493
|
-
}); // triggers property change for fullName on proxy
|
11563
|
+
this.arrayContentDidChange(idx, amt, len);
|
11564
|
+
return this ;
|
11565
|
+
},
|
11494
11566
|
|
11495
|
-
|
11496
|
-
|
11567
|
+
// If you ask for an unknown property, then try to collect the value
|
11568
|
+
// from member items.
|
11569
|
+
unknownProperty: function(key, value) {
|
11570
|
+
var ret;// = this.reducedProperty(key, value) ;
|
11571
|
+
if ((value !== undefined) && ret === undefined) {
|
11572
|
+
ret = this[key] = value;
|
11573
|
+
}
|
11574
|
+
return ret ;
|
11575
|
+
},
|
11497
11576
|
|
11498
|
-
|
11499
|
-
|
11500
|
-
|
11501
|
-
|
11502
|
-
Ember.ObjectProxy = Ember.Object.extend(
|
11503
|
-
/** @scope Ember.ObjectProxy.prototype */ {
|
11504
|
-
/**
|
11505
|
-
The object whose properties will be forwarded.
|
11577
|
+
// If browser did not implement indexOf natively, then override with
|
11578
|
+
// specialized version
|
11579
|
+
indexOf: function(object, startAt) {
|
11580
|
+
var idx, len = this.length;
|
11506
11581
|
|
11507
|
-
|
11508
|
-
|
11509
|
-
|
11510
|
-
*/
|
11511
|
-
content: null,
|
11512
|
-
_contentDidChange: Ember.observer(function() {
|
11513
|
-
Ember.assert("Can't set ObjectProxy's content to itself", this.get('content') !== this);
|
11514
|
-
}, 'content'),
|
11582
|
+
if (startAt === undefined) startAt = 0;
|
11583
|
+
else startAt = (startAt < 0) ? Math.ceil(startAt) : Math.floor(startAt);
|
11584
|
+
if (startAt < 0) startAt += len;
|
11515
11585
|
|
11516
|
-
|
11586
|
+
for(idx=startAt;idx<len;idx++) {
|
11587
|
+
if (this[idx] === object) return idx ;
|
11588
|
+
}
|
11589
|
+
return -1;
|
11590
|
+
},
|
11517
11591
|
|
11518
|
-
|
11592
|
+
lastIndexOf: function(object, startAt) {
|
11593
|
+
var idx, len = this.length;
|
11519
11594
|
|
11520
|
-
|
11521
|
-
|
11522
|
-
|
11523
|
-
addObserver(this, contentKey, null, contentPropertyDidChange);
|
11524
|
-
},
|
11595
|
+
if (startAt === undefined) startAt = len-1;
|
11596
|
+
else startAt = (startAt < 0) ? Math.ceil(startAt) : Math.floor(startAt);
|
11597
|
+
if (startAt < 0) startAt += len;
|
11525
11598
|
|
11526
|
-
|
11527
|
-
|
11528
|
-
|
11529
|
-
|
11599
|
+
for(idx=startAt;idx>=0;idx--) {
|
11600
|
+
if (this[idx] === object) return idx ;
|
11601
|
+
}
|
11602
|
+
return -1;
|
11530
11603
|
},
|
11531
11604
|
|
11532
|
-
|
11533
|
-
|
11534
|
-
|
11535
|
-
return get(content, key);
|
11605
|
+
copy: function(deep) {
|
11606
|
+
if (deep) {
|
11607
|
+
return this.map(function(item){ return Ember.copy(item, true); });
|
11536
11608
|
}
|
11537
|
-
},
|
11538
11609
|
|
11539
|
-
|
11540
|
-
var content = get(this, 'content');
|
11541
|
-
Ember.assert(fmt("Cannot delegate set('%@', %@) to the 'content' property of object proxy %@: its 'content' is undefined.", [key, value, this]), content);
|
11542
|
-
return set(content, key, value);
|
11610
|
+
return this.slice();
|
11543
11611
|
}
|
11544
11612
|
});
|
11545
11613
|
|
11546
|
-
|
11547
|
-
|
11548
|
-
|
11549
|
-
|
11550
|
-
prototype = this.proto();
|
11551
|
-
for (i = 0, l = arguments.length; i < l; i++) {
|
11552
|
-
properties = arguments[i];
|
11553
|
-
for (keyName in properties) {
|
11554
|
-
if (!properties.hasOwnProperty(keyName) || keyName in prototype) { continue; }
|
11555
|
-
if (!mixin) mixin = {};
|
11556
|
-
mixin[keyName] = null;
|
11557
|
-
}
|
11558
|
-
}
|
11559
|
-
if (mixin) this._initMixins([mixin]);
|
11560
|
-
}
|
11561
|
-
return this._super.apply(this, arguments);
|
11562
|
-
}
|
11614
|
+
// Remove any methods implemented natively so we don't override them
|
11615
|
+
var ignore = ['length'];
|
11616
|
+
Ember.EnumerableUtils.forEach(NativeArray.keys(), function(methodName) {
|
11617
|
+
if (Array.prototype[methodName]) ignore.push(methodName);
|
11563
11618
|
});
|
11564
11619
|
|
11565
|
-
|
11566
|
-
|
11567
|
-
|
11620
|
+
if (ignore.length>0) {
|
11621
|
+
NativeArray = NativeArray.without.apply(NativeArray, ignore);
|
11622
|
+
}
|
11568
11623
|
|
11569
|
-
(function() {
|
11570
11624
|
/**
|
11571
|
-
|
11572
|
-
|
11625
|
+
The NativeArray mixin contains the properties needed to to make the native
|
11626
|
+
Array support Ember.MutableArray and all of its dependent APIs. Unless you
|
11627
|
+
have `Ember.EXTEND_PROTOTYPES` or `Ember.EXTEND_PROTOTYPES.Array` set to
|
11628
|
+
false, this will be applied automatically. Otherwise you can apply the mixin
|
11629
|
+
at anytime by calling `Ember.NativeArray.activate`.
|
11630
|
+
|
11631
|
+
@class NativeArray
|
11632
|
+
@namespace Ember
|
11633
|
+
@extends Ember.Mixin
|
11634
|
+
@uses Ember.MutableArray
|
11635
|
+
@uses Ember.MutableEnumerable
|
11636
|
+
@uses Ember.Copyable
|
11637
|
+
@uses Ember.Freezable
|
11573
11638
|
*/
|
11639
|
+
Ember.NativeArray = NativeArray;
|
11574
11640
|
|
11641
|
+
/**
|
11642
|
+
Creates an `Ember.NativeArray` from an Array like object.
|
11643
|
+
Does not modify the original object.
|
11575
11644
|
|
11576
|
-
|
11577
|
-
|
11645
|
+
@method A
|
11646
|
+
@for Ember
|
11647
|
+
@return {Ember.NativeArray}
|
11648
|
+
*/
|
11649
|
+
Ember.A = function(arr){
|
11650
|
+
if (arr === undefined) { arr = []; }
|
11651
|
+
return Ember.Array.detect(arr) ? arr : Ember.NativeArray.apply(arr);
|
11652
|
+
};
|
11578
11653
|
|
11579
|
-
|
11654
|
+
/**
|
11655
|
+
Activates the mixin on the Array.prototype if not already applied. Calling
|
11656
|
+
this method more than once is safe.
|
11580
11657
|
|
11581
|
-
|
11582
|
-
|
11583
|
-
|
11584
|
-
|
11585
|
-
|
11586
|
-
|
11658
|
+
@method activate
|
11659
|
+
@for Ember.NativeArray
|
11660
|
+
@static
|
11661
|
+
@return {void}
|
11662
|
+
*/
|
11663
|
+
Ember.NativeArray.activate = function() {
|
11664
|
+
NativeArray.apply(Array.prototype);
|
11587
11665
|
|
11588
|
-
|
11589
|
-
|
11590
|
-
return item && get(item, this._keyName);
|
11591
|
-
},
|
11666
|
+
Ember.A = function(arr) { return arr || []; };
|
11667
|
+
};
|
11592
11668
|
|
11593
|
-
|
11594
|
-
|
11595
|
-
|
11596
|
-
})
|
11669
|
+
if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.Array) {
|
11670
|
+
Ember.NativeArray.activate();
|
11671
|
+
}
|
11597
11672
|
|
11598
|
-
});
|
11599
11673
|
|
11600
|
-
|
11674
|
+
})();
|
11601
11675
|
|
11602
|
-
function addObserverForContentKey(content, keyName, proxy, idx, loc) {
|
11603
|
-
var objects = proxy._objects, guid;
|
11604
|
-
if (!objects) objects = proxy._objects = {};
|
11605
11676
|
|
11606
|
-
while(--loc>=idx) {
|
11607
|
-
var item = content.objectAt(loc);
|
11608
|
-
if (item) {
|
11609
|
-
Ember.addBeforeObserver(item, keyName, proxy, 'contentKeyWillChange');
|
11610
|
-
Ember.addObserver(item, keyName, proxy, 'contentKeyDidChange');
|
11611
11677
|
|
11612
|
-
|
11613
|
-
|
11614
|
-
|
11615
|
-
|
11616
|
-
|
11617
|
-
}
|
11618
|
-
}
|
11619
|
-
}
|
11678
|
+
(function() {
|
11679
|
+
/**
|
11680
|
+
@module ember
|
11681
|
+
@submodule ember-runtime
|
11682
|
+
*/
|
11620
11683
|
|
11621
|
-
|
11622
|
-
var objects = proxy._objects;
|
11623
|
-
if (!objects) objects = proxy._objects = {};
|
11624
|
-
var indicies, guid;
|
11684
|
+
var get = Ember.get, set = Ember.set, guidFor = Ember.guidFor, none = Ember.isNone, fmt = Ember.String.fmt;
|
11625
11685
|
|
11626
|
-
|
11627
|
-
|
11628
|
-
if (item) {
|
11629
|
-
Ember.removeBeforeObserver(item, keyName, proxy, 'contentKeyWillChange');
|
11630
|
-
Ember.removeObserver(item, keyName, proxy, 'contentKeyDidChange');
|
11686
|
+
/**
|
11687
|
+
An unordered collection of objects.
|
11631
11688
|
|
11632
|
-
|
11633
|
-
|
11634
|
-
|
11635
|
-
|
11636
|
-
}
|
11637
|
-
}
|
11689
|
+
A Set works a bit like an array except that its items are not ordered. You
|
11690
|
+
can create a set to efficiently test for membership for an object. You can
|
11691
|
+
also iterate through a set just like an array, even accessing objects by
|
11692
|
+
index, however there is no guarantee as to their order.
|
11638
11693
|
|
11639
|
-
|
11640
|
-
|
11641
|
-
array. It uses the unknownProperty handler to automatically create
|
11642
|
-
EachArray instances for property names.
|
11694
|
+
All Sets are observable via the Enumerable Observer API - which works
|
11695
|
+
on any enumerable object including both Sets and Arrays.
|
11643
11696
|
|
11644
|
-
|
11645
|
-
|
11697
|
+
## Creating a Set
|
11698
|
+
|
11699
|
+
You can create a set like you would most objects using
|
11700
|
+
`new Ember.Set()`. Most new sets you create will be empty, but you can
|
11701
|
+
also initialize the set with some content by passing an array or other
|
11702
|
+
enumerable of objects to the constructor.
|
11703
|
+
|
11704
|
+
Finally, you can pass in an existing set and the set will be copied. You
|
11705
|
+
can also create a copy of a set by calling `Ember.Set#copy()`.
|
11706
|
+
|
11707
|
+
```javascript
|
11708
|
+
// creates a new empty set
|
11709
|
+
var foundNames = new Ember.Set();
|
11710
|
+
|
11711
|
+
// creates a set with four names in it.
|
11712
|
+
var names = new Ember.Set(["Charles", "Tom", "Juan", "Alex"]); // :P
|
11713
|
+
|
11714
|
+
// creates a copy of the names set.
|
11715
|
+
var namesCopy = new Ember.Set(names);
|
11716
|
+
|
11717
|
+
// same as above.
|
11718
|
+
var anotherNamesCopy = names.copy();
|
11719
|
+
```
|
11720
|
+
|
11721
|
+
## Adding/Removing Objects
|
11722
|
+
|
11723
|
+
You generally add or remove objects from a set using `add()` or
|
11724
|
+
`remove()`. You can add any type of object including primitives such as
|
11725
|
+
numbers, strings, and booleans.
|
11726
|
+
|
11727
|
+
Unlike arrays, objects can only exist one time in a set. If you call `add()`
|
11728
|
+
on a set with the same object multiple times, the object will only be added
|
11729
|
+
once. Likewise, calling `remove()` with the same object multiple times will
|
11730
|
+
remove the object the first time and have no effect on future calls until
|
11731
|
+
you add the object to the set again.
|
11732
|
+
|
11733
|
+
NOTE: You cannot add/remove `null` or `undefined` to a set. Any attempt to do
|
11734
|
+
so will be ignored.
|
11735
|
+
|
11736
|
+
In addition to add/remove you can also call `push()`/`pop()`. Push behaves
|
11737
|
+
just like `add()` but `pop()`, unlike `remove()` will pick an arbitrary
|
11738
|
+
object, remove it and return it. This is a good way to use a set as a job
|
11739
|
+
queue when you don't care which order the jobs are executed in.
|
11740
|
+
|
11741
|
+
## Testing for an Object
|
11742
|
+
|
11743
|
+
To test for an object's presence in a set you simply call
|
11744
|
+
`Ember.Set#contains()`.
|
11745
|
+
|
11746
|
+
## Observing changes
|
11747
|
+
|
11748
|
+
When using `Ember.Set`, you can observe the `"[]"` property to be
|
11749
|
+
alerted whenever the content changes. You can also add an enumerable
|
11750
|
+
observer to the set to be notified of specific objects that are added and
|
11751
|
+
removed from the set. See `Ember.Enumerable` for more information on
|
11752
|
+
enumerables.
|
11753
|
+
|
11754
|
+
This is often unhelpful. If you are filtering sets of objects, for instance,
|
11755
|
+
it is very inefficient to re-filter all of the items each time the set
|
11756
|
+
changes. It would be better if you could just adjust the filtered set based
|
11757
|
+
on what was changed on the original set. The same issue applies to merging
|
11758
|
+
sets, as well.
|
11759
|
+
|
11760
|
+
## Other Methods
|
11761
|
+
|
11762
|
+
`Ember.Set` primary implements other mixin APIs. For a complete reference
|
11763
|
+
on the methods you will use with `Ember.Set`, please consult these mixins.
|
11764
|
+
The most useful ones will be `Ember.Enumerable` and
|
11765
|
+
`Ember.MutableEnumerable` which implement most of the common iterator
|
11766
|
+
methods you are used to on Array.
|
11767
|
+
|
11768
|
+
Note that you can also use the `Ember.Copyable` and `Ember.Freezable`
|
11769
|
+
APIs on `Ember.Set` as well. Once a set is frozen it can no longer be
|
11770
|
+
modified. The benefit of this is that when you call `frozenCopy()` on it,
|
11771
|
+
Ember will avoid making copies of the set. This allows you to write
|
11772
|
+
code that can know with certainty when the underlying set data will or
|
11773
|
+
will not be modified.
|
11774
|
+
|
11775
|
+
@class Set
|
11646
11776
|
@namespace Ember
|
11647
|
-
@extends Ember.
|
11777
|
+
@extends Ember.CoreObject
|
11778
|
+
@uses Ember.MutableEnumerable
|
11779
|
+
@uses Ember.Copyable
|
11780
|
+
@uses Ember.Freezable
|
11781
|
+
@since Ember 0.9
|
11648
11782
|
*/
|
11649
|
-
Ember.
|
11650
|
-
|
11651
|
-
init: function(content) {
|
11652
|
-
this._super();
|
11653
|
-
this._content = content;
|
11654
|
-
content.addArrayObserver(this);
|
11783
|
+
Ember.Set = Ember.CoreObject.extend(Ember.MutableEnumerable, Ember.Copyable, Ember.Freezable,
|
11784
|
+
/** @scope Ember.Set.prototype */ {
|
11655
11785
|
|
11656
|
-
|
11657
|
-
|
11658
|
-
|
11659
|
-
this.didAddListener(eventName);
|
11660
|
-
}, this);
|
11661
|
-
},
|
11786
|
+
// ..........................................................
|
11787
|
+
// IMPLEMENT ENUMERABLE APIS
|
11788
|
+
//
|
11662
11789
|
|
11663
11790
|
/**
|
11664
|
-
|
11665
|
-
The `unknownProperty` handler will generate an EachArray of each item.
|
11791
|
+
This property will change as the number of objects in the set changes.
|
11666
11792
|
|
11667
|
-
@
|
11668
|
-
@
|
11669
|
-
@
|
11793
|
+
@property length
|
11794
|
+
@type number
|
11795
|
+
@default 0
|
11670
11796
|
*/
|
11671
|
-
|
11672
|
-
var ret;
|
11673
|
-
ret = new EachArray(this._content, keyName, this);
|
11674
|
-
Ember.defineProperty(this, keyName, null, ret);
|
11675
|
-
this.beginObservingContentKey(keyName);
|
11676
|
-
return ret;
|
11677
|
-
},
|
11797
|
+
length: 0,
|
11678
11798
|
|
11679
|
-
|
11680
|
-
|
11681
|
-
|
11799
|
+
/**
|
11800
|
+
Clears the set. This is useful if you want to reuse an existing set
|
11801
|
+
without having to recreate it.
|
11682
11802
|
|
11683
|
-
|
11684
|
-
var
|
11803
|
+
```javascript
|
11804
|
+
var colors = new Ember.Set(["red", "green", "blue"]);
|
11805
|
+
colors.length; // 3
|
11806
|
+
colors.clear();
|
11807
|
+
colors.length; // 0
|
11808
|
+
```
|
11685
11809
|
|
11686
|
-
|
11687
|
-
Ember.
|
11810
|
+
@method clear
|
11811
|
+
@return {Ember.Set} An empty Set
|
11812
|
+
*/
|
11813
|
+
clear: function() {
|
11814
|
+
if (this.isFrozen) { throw new Error(Ember.FROZEN_ERROR); }
|
11688
11815
|
|
11689
|
-
|
11690
|
-
|
11816
|
+
var len = get(this, 'length');
|
11817
|
+
if (len === 0) { return this; }
|
11691
11818
|
|
11692
|
-
|
11819
|
+
var guid;
|
11693
11820
|
|
11694
|
-
|
11821
|
+
this.enumerableContentWillChange(len, 0);
|
11822
|
+
Ember.propertyWillChange(this, 'firstObject');
|
11823
|
+
Ember.propertyWillChange(this, 'lastObject');
|
11824
|
+
|
11825
|
+
for (var i=0; i < len; i++){
|
11826
|
+
guid = guidFor(this[i]);
|
11827
|
+
delete this[guid];
|
11828
|
+
delete this[i];
|
11695
11829
|
}
|
11696
11830
|
|
11697
|
-
|
11698
|
-
|
11831
|
+
set(this, 'length', 0);
|
11832
|
+
|
11833
|
+
Ember.propertyDidChange(this, 'firstObject');
|
11834
|
+
Ember.propertyDidChange(this, 'lastObject');
|
11835
|
+
this.enumerableContentDidChange(len, 0);
|
11836
|
+
|
11837
|
+
return this;
|
11699
11838
|
},
|
11700
11839
|
|
11701
|
-
|
11702
|
-
|
11840
|
+
/**
|
11841
|
+
Returns true if the passed object is also an enumerable that contains the
|
11842
|
+
same objects as the receiver.
|
11703
11843
|
|
11704
|
-
|
11705
|
-
|
11844
|
+
```javascript
|
11845
|
+
var colors = ["red", "green", "blue"],
|
11846
|
+
same_colors = new Ember.Set(colors);
|
11706
11847
|
|
11707
|
-
|
11708
|
-
|
11848
|
+
same_colors.isEqual(colors); // true
|
11849
|
+
same_colors.isEqual(["purple", "brown"]); // false
|
11850
|
+
```
|
11709
11851
|
|
11710
|
-
|
11852
|
+
@method isEqual
|
11853
|
+
@param {Ember.Set} obj the other object.
|
11854
|
+
@return {Boolean}
|
11855
|
+
*/
|
11856
|
+
isEqual: function(obj) {
|
11857
|
+
// fail fast
|
11858
|
+
if (!Ember.Enumerable.detect(obj)) return false;
|
11711
11859
|
|
11712
|
-
|
11860
|
+
var loc = get(this, 'length');
|
11861
|
+
if (get(obj, 'length') !== loc) return false;
|
11862
|
+
|
11863
|
+
while(--loc >= 0) {
|
11864
|
+
if (!obj.contains(this[loc])) return false;
|
11713
11865
|
}
|
11714
11866
|
|
11715
|
-
|
11716
|
-
Ember.endPropertyChanges(this);
|
11867
|
+
return true;
|
11717
11868
|
},
|
11718
11869
|
|
11719
|
-
|
11720
|
-
|
11721
|
-
|
11870
|
+
/**
|
11871
|
+
Adds an object to the set. Only non-`null` objects can be added to a set
|
11872
|
+
and those can only be added once. If the object is already in the set or
|
11873
|
+
the passed value is null this method will have no effect.
|
11722
11874
|
|
11723
|
-
|
11724
|
-
if (IS_OBSERVER.test(eventName)) {
|
11725
|
-
this.beginObservingContentKey(eventName.slice(0, -7));
|
11726
|
-
}
|
11727
|
-
},
|
11875
|
+
This is an alias for `Ember.MutableEnumerable.addObject()`.
|
11728
11876
|
|
11729
|
-
|
11730
|
-
|
11731
|
-
|
11732
|
-
|
11733
|
-
|
11877
|
+
```javascript
|
11878
|
+
var colors = new Ember.Set();
|
11879
|
+
colors.add("blue"); // ["blue"]
|
11880
|
+
colors.add("blue"); // ["blue"]
|
11881
|
+
colors.add("red"); // ["blue", "red"]
|
11882
|
+
colors.add(null); // ["blue", "red"]
|
11883
|
+
colors.add(undefined); // ["blue", "red"]
|
11884
|
+
```
|
11734
11885
|
|
11735
|
-
|
11736
|
-
|
11737
|
-
|
11886
|
+
@method add
|
11887
|
+
@param {Object} obj The object to add.
|
11888
|
+
@return {Ember.Set} The set itself.
|
11889
|
+
*/
|
11890
|
+
add: Ember.aliasMethod('addObject'),
|
11738
11891
|
|
11739
|
-
|
11740
|
-
|
11741
|
-
|
11742
|
-
|
11743
|
-
keys[keyName] = 1;
|
11744
|
-
var content = this._content,
|
11745
|
-
len = get(content, 'length');
|
11746
|
-
addObserverForContentKey(content, keyName, this, 0, len);
|
11747
|
-
} else {
|
11748
|
-
keys[keyName]++;
|
11749
|
-
}
|
11750
|
-
},
|
11892
|
+
/**
|
11893
|
+
Removes the object from the set if it is found. If you pass a `null` value
|
11894
|
+
or an object that is already not in the set, this method will have no
|
11895
|
+
effect. This is an alias for `Ember.MutableEnumerable.removeObject()`.
|
11751
11896
|
|
11752
|
-
|
11753
|
-
var
|
11754
|
-
|
11755
|
-
|
11756
|
-
|
11757
|
-
|
11758
|
-
|
11897
|
+
```javascript
|
11898
|
+
var colors = new Ember.Set(["red", "green", "blue"]);
|
11899
|
+
colors.remove("red"); // ["blue", "green"]
|
11900
|
+
colors.remove("purple"); // ["blue", "green"]
|
11901
|
+
colors.remove(null); // ["blue", "green"]
|
11902
|
+
```
|
11903
|
+
|
11904
|
+
@method remove
|
11905
|
+
@param {Object} obj The object to remove
|
11906
|
+
@return {Ember.Set} The set itself.
|
11907
|
+
*/
|
11908
|
+
remove: Ember.aliasMethod('removeObject'),
|
11909
|
+
|
11910
|
+
/**
|
11911
|
+
Removes the last element from the set and returns it, or `null` if it's empty.
|
11912
|
+
|
11913
|
+
```javascript
|
11914
|
+
var colors = new Ember.Set(["green", "blue"]);
|
11915
|
+
colors.pop(); // "blue"
|
11916
|
+
colors.pop(); // "green"
|
11917
|
+
colors.pop(); // null
|
11918
|
+
```
|
11919
|
+
|
11920
|
+
@method pop
|
11921
|
+
@return {Object} The removed object from the set or null.
|
11922
|
+
*/
|
11923
|
+
pop: function() {
|
11924
|
+
if (get(this, 'isFrozen')) throw new Error(Ember.FROZEN_ERROR);
|
11925
|
+
var obj = this.length > 0 ? this[this.length-1] : null;
|
11926
|
+
this.remove(obj);
|
11927
|
+
return obj;
|
11759
11928
|
},
|
11760
11929
|
|
11761
|
-
|
11762
|
-
|
11763
|
-
|
11930
|
+
/**
|
11931
|
+
Inserts the given object on to the end of the set. It returns
|
11932
|
+
the set itself.
|
11933
|
+
|
11934
|
+
This is an alias for `Ember.MutableEnumerable.addObject()`.
|
11935
|
+
|
11936
|
+
```javascript
|
11937
|
+
var colors = new Ember.Set();
|
11938
|
+
colors.push("red"); // ["red"]
|
11939
|
+
colors.push("green"); // ["red", "green"]
|
11940
|
+
colors.push("blue"); // ["red", "green", "blue"]
|
11941
|
+
```
|
11942
|
+
|
11943
|
+
@method push
|
11944
|
+
@return {Ember.Set} The set itself.
|
11945
|
+
*/
|
11946
|
+
push: Ember.aliasMethod('addObject'),
|
11947
|
+
|
11948
|
+
/**
|
11949
|
+
Removes the last element from the set and returns it, or `null` if it's empty.
|
11950
|
+
|
11951
|
+
This is an alias for `Ember.Set.pop()`.
|
11952
|
+
|
11953
|
+
```javascript
|
11954
|
+
var colors = new Ember.Set(["green", "blue"]);
|
11955
|
+
colors.shift(); // "blue"
|
11956
|
+
colors.shift(); // "green"
|
11957
|
+
colors.shift(); // null
|
11958
|
+
```
|
11959
|
+
|
11960
|
+
@method shift
|
11961
|
+
@return {Object} The removed object from the set or null.
|
11962
|
+
*/
|
11963
|
+
shift: Ember.aliasMethod('pop'),
|
11964
|
+
|
11965
|
+
/**
|
11966
|
+
Inserts the given object on to the end of the set. It returns
|
11967
|
+
the set itself.
|
11764
11968
|
|
11765
|
-
|
11766
|
-
Ember.propertyDidChange(this, keyName);
|
11767
|
-
}
|
11969
|
+
This is an alias of `Ember.Set.push()`
|
11768
11970
|
|
11769
|
-
|
11971
|
+
```javascript
|
11972
|
+
var colors = new Ember.Set();
|
11973
|
+
colors.unshift("red"); // ["red"]
|
11974
|
+
colors.unshift("green"); // ["red", "green"]
|
11975
|
+
colors.unshift("blue"); // ["red", "green", "blue"]
|
11976
|
+
```
|
11770
11977
|
|
11978
|
+
@method unshift
|
11979
|
+
@return {Ember.Set} The set itself.
|
11980
|
+
*/
|
11981
|
+
unshift: Ember.aliasMethod('push'),
|
11771
11982
|
|
11983
|
+
/**
|
11984
|
+
Adds each object in the passed enumerable to the set.
|
11772
11985
|
|
11773
|
-
|
11986
|
+
This is an alias of `Ember.MutableEnumerable.addObjects()`
|
11774
11987
|
|
11988
|
+
```javascript
|
11989
|
+
var colors = new Ember.Set();
|
11990
|
+
colors.addEach(["red", "green", "blue"]); // ["red", "green", "blue"]
|
11991
|
+
```
|
11775
11992
|
|
11993
|
+
@method addEach
|
11994
|
+
@param {Ember.Enumerable} objects the objects to add.
|
11995
|
+
@return {Ember.Set} The set itself.
|
11996
|
+
*/
|
11997
|
+
addEach: Ember.aliasMethod('addObjects'),
|
11776
11998
|
|
11777
|
-
|
11778
|
-
|
11779
|
-
@module ember
|
11780
|
-
@submodule ember-runtime
|
11781
|
-
*/
|
11999
|
+
/**
|
12000
|
+
Removes each object in the passed enumerable to the set.
|
11782
12001
|
|
12002
|
+
This is an alias of `Ember.MutableEnumerable.removeObjects()`
|
11783
12003
|
|
11784
|
-
|
12004
|
+
```javascript
|
12005
|
+
var colors = new Ember.Set(["red", "green", "blue"]);
|
12006
|
+
colors.removeEach(["red", "blue"]); // ["green"]
|
12007
|
+
```
|
11785
12008
|
|
11786
|
-
|
11787
|
-
|
11788
|
-
|
11789
|
-
|
12009
|
+
@method removeEach
|
12010
|
+
@param {Ember.Enumerable} objects the objects to remove.
|
12011
|
+
@return {Ember.Set} The set itself.
|
12012
|
+
*/
|
12013
|
+
removeEach: Ember.aliasMethod('removeObjects'),
|
11790
12014
|
|
11791
|
-
//
|
11792
|
-
//
|
11793
|
-
|
11794
|
-
|
11795
|
-
|
11796
|
-
|
12015
|
+
// ..........................................................
|
12016
|
+
// PRIVATE ENUMERABLE SUPPORT
|
12017
|
+
//
|
12018
|
+
|
12019
|
+
init: function(items) {
|
12020
|
+
this._super();
|
12021
|
+
if (items) this.addObjects(items);
|
11797
12022
|
},
|
11798
12023
|
|
11799
|
-
|
12024
|
+
// implement Ember.Enumerable
|
12025
|
+
nextObject: function(idx) {
|
11800
12026
|
return this[idx];
|
11801
12027
|
},
|
11802
12028
|
|
11803
|
-
//
|
11804
|
-
|
11805
|
-
|
11806
|
-
|
11807
|
-
|
11808
|
-
// if we replaced exactly the same number of items, then pass only the
|
11809
|
-
// replaced range. Otherwise, pass the full remaining array length
|
11810
|
-
// since everything has shifted
|
11811
|
-
var len = objects ? get(objects, 'length') : 0;
|
11812
|
-
this.arrayContentWillChange(idx, amt, len);
|
12029
|
+
// more optimized version
|
12030
|
+
firstObject: Ember.computed(function() {
|
12031
|
+
return this.length > 0 ? this[0] : undefined;
|
12032
|
+
}),
|
11813
12033
|
|
11814
|
-
|
11815
|
-
|
11816
|
-
|
11817
|
-
|
11818
|
-
this.splice.apply(this,args) ;
|
11819
|
-
}
|
12034
|
+
// more optimized version
|
12035
|
+
lastObject: Ember.computed(function() {
|
12036
|
+
return this.length > 0 ? this[this.length-1] : undefined;
|
12037
|
+
}),
|
11820
12038
|
|
11821
|
-
|
11822
|
-
|
11823
|
-
|
12039
|
+
// implements Ember.MutableEnumerable
|
12040
|
+
addObject: function(obj) {
|
12041
|
+
if (get(this, 'isFrozen')) throw new Error(Ember.FROZEN_ERROR);
|
12042
|
+
if (none(obj)) return this; // nothing to do
|
11824
12043
|
|
11825
|
-
|
11826
|
-
|
11827
|
-
|
11828
|
-
|
11829
|
-
if ((value !== undefined) && ret === undefined) {
|
11830
|
-
ret = this[key] = value;
|
11831
|
-
}
|
11832
|
-
return ret ;
|
11833
|
-
},
|
12044
|
+
var guid = guidFor(obj),
|
12045
|
+
idx = this[guid],
|
12046
|
+
len = get(this, 'length'),
|
12047
|
+
added ;
|
11834
12048
|
|
11835
|
-
|
11836
|
-
// specialized version
|
11837
|
-
indexOf: function(object, startAt) {
|
11838
|
-
var idx, len = this.length;
|
12049
|
+
if (idx>=0 && idx<len && (this[idx] === obj)) return this; // added
|
11839
12050
|
|
11840
|
-
|
11841
|
-
else startAt = (startAt < 0) ? Math.ceil(startAt) : Math.floor(startAt);
|
11842
|
-
if (startAt < 0) startAt += len;
|
12051
|
+
added = [obj];
|
11843
12052
|
|
11844
|
-
|
11845
|
-
|
11846
|
-
}
|
11847
|
-
return -1;
|
11848
|
-
},
|
12053
|
+
this.enumerableContentWillChange(null, added);
|
12054
|
+
Ember.propertyWillChange(this, 'lastObject');
|
11849
12055
|
|
11850
|
-
|
11851
|
-
|
12056
|
+
len = get(this, 'length');
|
12057
|
+
this[guid] = len;
|
12058
|
+
this[len] = obj;
|
12059
|
+
set(this, 'length', len+1);
|
11852
12060
|
|
11853
|
-
|
11854
|
-
|
11855
|
-
if (startAt < 0) startAt += len;
|
12061
|
+
Ember.propertyDidChange(this, 'lastObject');
|
12062
|
+
this.enumerableContentDidChange(null, added);
|
11856
12063
|
|
11857
|
-
|
11858
|
-
if (this[idx] === object) return idx ;
|
11859
|
-
}
|
11860
|
-
return -1;
|
12064
|
+
return this;
|
11861
12065
|
},
|
11862
12066
|
|
11863
|
-
|
11864
|
-
|
11865
|
-
|
11866
|
-
|
12067
|
+
// implements Ember.MutableEnumerable
|
12068
|
+
removeObject: function(obj) {
|
12069
|
+
if (get(this, 'isFrozen')) throw new Error(Ember.FROZEN_ERROR);
|
12070
|
+
if (none(obj)) return this; // nothing to do
|
11867
12071
|
|
11868
|
-
|
11869
|
-
|
11870
|
-
|
12072
|
+
var guid = guidFor(obj),
|
12073
|
+
idx = this[guid],
|
12074
|
+
len = get(this, 'length'),
|
12075
|
+
isFirst = idx === 0,
|
12076
|
+
isLast = idx === len-1,
|
12077
|
+
last, removed;
|
11871
12078
|
|
11872
|
-
// Remove any methods implemented natively so we don't override them
|
11873
|
-
var ignore = ['length'];
|
11874
|
-
Ember.EnumerableUtils.forEach(NativeArray.keys(), function(methodName) {
|
11875
|
-
if (Array.prototype[methodName]) ignore.push(methodName);
|
11876
|
-
});
|
11877
12079
|
|
11878
|
-
if (
|
11879
|
-
|
11880
|
-
}
|
12080
|
+
if (idx>=0 && idx<len && (this[idx] === obj)) {
|
12081
|
+
removed = [obj];
|
11881
12082
|
|
11882
|
-
|
11883
|
-
|
11884
|
-
|
11885
|
-
have `Ember.EXTEND_PROTOTYPES` or `Ember.EXTEND_PROTOTYPES.Array` set to
|
11886
|
-
false, this will be applied automatically. Otherwise you can apply the mixin
|
11887
|
-
at anytime by calling `Ember.NativeArray.activate`.
|
12083
|
+
this.enumerableContentWillChange(removed, null);
|
12084
|
+
if (isFirst) { Ember.propertyWillChange(this, 'firstObject'); }
|
12085
|
+
if (isLast) { Ember.propertyWillChange(this, 'lastObject'); }
|
11888
12086
|
|
11889
|
-
|
11890
|
-
|
11891
|
-
|
11892
|
-
|
11893
|
-
|
11894
|
-
|
11895
|
-
@uses Ember.Freezable
|
11896
|
-
*/
|
11897
|
-
Ember.NativeArray = NativeArray;
|
12087
|
+
// swap items - basically move the item to the end so it can be removed
|
12088
|
+
if (idx < len-1) {
|
12089
|
+
last = this[len-1];
|
12090
|
+
this[idx] = last;
|
12091
|
+
this[guidFor(last)] = idx;
|
12092
|
+
}
|
11898
12093
|
|
11899
|
-
|
11900
|
-
|
11901
|
-
|
12094
|
+
delete this[guid];
|
12095
|
+
delete this[len-1];
|
12096
|
+
set(this, 'length', len-1);
|
11902
12097
|
|
11903
|
-
|
11904
|
-
|
11905
|
-
|
11906
|
-
|
11907
|
-
Ember.A = function(arr){
|
11908
|
-
if (arr === undefined) { arr = []; }
|
11909
|
-
return Ember.Array.detect(arr) ? arr : Ember.NativeArray.apply(arr);
|
11910
|
-
};
|
12098
|
+
if (isFirst) { Ember.propertyDidChange(this, 'firstObject'); }
|
12099
|
+
if (isLast) { Ember.propertyDidChange(this, 'lastObject'); }
|
12100
|
+
this.enumerableContentDidChange(removed, null);
|
12101
|
+
}
|
11911
12102
|
|
11912
|
-
|
11913
|
-
|
11914
|
-
this method more than once is safe.
|
12103
|
+
return this;
|
12104
|
+
},
|
11915
12105
|
|
11916
|
-
|
11917
|
-
|
11918
|
-
|
11919
|
-
|
11920
|
-
*/
|
11921
|
-
Ember.NativeArray.activate = function() {
|
11922
|
-
NativeArray.apply(Array.prototype);
|
12106
|
+
// optimized version
|
12107
|
+
contains: function(obj) {
|
12108
|
+
return this[guidFor(obj)]>=0;
|
12109
|
+
},
|
11923
12110
|
|
11924
|
-
|
11925
|
-
|
12111
|
+
copy: function() {
|
12112
|
+
var C = this.constructor, ret = new C(), loc = get(this, 'length');
|
12113
|
+
set(ret, 'length', loc);
|
12114
|
+
while(--loc>=0) {
|
12115
|
+
ret[loc] = this[loc];
|
12116
|
+
ret[guidFor(this[loc])] = loc;
|
12117
|
+
}
|
12118
|
+
return ret;
|
12119
|
+
},
|
11926
12120
|
|
11927
|
-
|
11928
|
-
|
11929
|
-
|
12121
|
+
toString: function() {
|
12122
|
+
var len = this.length, idx, array = [];
|
12123
|
+
for(idx = 0; idx < len; idx++) {
|
12124
|
+
array[idx] = this[idx];
|
12125
|
+
}
|
12126
|
+
return fmt("Ember.Set<%@>", [array.join(',')]);
|
12127
|
+
}
|
11930
12128
|
|
12129
|
+
});
|
11931
12130
|
|
11932
12131
|
})();
|
11933
12132
|
|
@@ -11935,7 +12134,6 @@ if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.Array) {
|
|
11935
12134
|
|
11936
12135
|
(function() {
|
11937
12136
|
var DeferredMixin = Ember.DeferredMixin, // mixins/deferred
|
11938
|
-
EmberObject = Ember.Object, // system/object
|
11939
12137
|
get = Ember.get;
|
11940
12138
|
|
11941
12139
|
var Deferred = Ember.Object.extend(DeferredMixin);
|
@@ -12259,7 +12457,6 @@ Ember.SortableMixin = Ember.Mixin.create(Ember.MutableEnumerable, {
|
|
12259
12457
|
|
12260
12458
|
if (isSorted) {
|
12261
12459
|
var addedObjects = array.slice(idx, idx+addedCount);
|
12262
|
-
var arrangedContent = get(this, 'arrangedContent');
|
12263
12460
|
|
12264
12461
|
forEach(addedObjects, function(item) {
|
12265
12462
|
this.insertItemSorted(item);
|
@@ -12329,8 +12526,8 @@ Ember.SortableMixin = Ember.Mixin.create(Ember.MutableEnumerable, {
|
|
12329
12526
|
@submodule ember-runtime
|
12330
12527
|
*/
|
12331
12528
|
|
12332
|
-
var get = Ember.get, set = Ember.set,
|
12333
|
-
|
12529
|
+
var get = Ember.get, set = Ember.set, forEach = Ember.EnumerableUtils.forEach,
|
12530
|
+
replace = Ember.EnumerableUtils.replace;
|
12334
12531
|
|
12335
12532
|
/**
|
12336
12533
|
`Ember.ArrayController` provides a way for you to publish a collection of
|