embient 0.0.5 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
@@ -3311,6 +3311,20 @@ var Cp = ComputedProperty.prototype;
|
|
3311
3311
|
mode the computed property will automatically cache the return value of
|
3312
3312
|
your function until one of the dependent keys changes.
|
3313
3313
|
|
3314
|
+
MyApp.president = Ember.Object.create({
|
3315
|
+
fullName: function() {
|
3316
|
+
return this.get('firstName') + ' ' + this.get('lastName');
|
3317
|
+
|
3318
|
+
// After calculating the value of this function, Ember.js will
|
3319
|
+
// return that value without re-executing this function until
|
3320
|
+
// one of the dependent properties change.
|
3321
|
+
}.property('firstName', 'lastName').cacheable()
|
3322
|
+
});
|
3323
|
+
|
3324
|
+
It is common to use `cacheable()` on nearly every computed property
|
3325
|
+
you define.
|
3326
|
+
|
3327
|
+
@name Ember.ComputedProperty.cacheable
|
3314
3328
|
@param {Boolean} aFlag optional set to false to disable cacheing
|
3315
3329
|
@returns {Ember.ComputedProperty} receiver
|
3316
3330
|
*/
|
@@ -3323,6 +3337,16 @@ Cp.cacheable = function(aFlag) {
|
|
3323
3337
|
Sets the dependent keys on this computed property. Pass any number of
|
3324
3338
|
arguments containing key paths that this computed property depends on.
|
3325
3339
|
|
3340
|
+
MyApp.president = Ember.Object.create({
|
3341
|
+
fullName: Ember.computed(function() {
|
3342
|
+
return this.get('firstName') + ' ' + this.get('lastName');
|
3343
|
+
|
3344
|
+
// Tell Ember.js that this computed property depends on firstName
|
3345
|
+
// and lastName
|
3346
|
+
}).property('firstName', 'lastName')
|
3347
|
+
});
|
3348
|
+
|
3349
|
+
@name Ember.ComputedProperty.property
|
3326
3350
|
@param {String} path... zero or more property paths
|
3327
3351
|
@returns {Ember.ComputedProperty} receiver
|
3328
3352
|
*/
|
@@ -3348,6 +3372,10 @@ Cp.property = function() {
|
|
3348
3372
|
computed property descriptor under the `_meta` key. Ember runtime
|
3349
3373
|
exposes a public API for retrieving these values from classes,
|
3350
3374
|
via the `metaForProperty()` function.
|
3375
|
+
|
3376
|
+
@name Ember.ComputedProperty.meta
|
3377
|
+
@param {Hash} metadata
|
3378
|
+
@returns {Ember.ComputedProperty} property descriptor instance
|
3351
3379
|
*/
|
3352
3380
|
|
3353
3381
|
Cp.meta = function(meta) {
|
@@ -3458,8 +3486,8 @@ Ember.computed = function(func) {
|
|
3458
3486
|
var args;
|
3459
3487
|
|
3460
3488
|
if (arguments.length > 1) {
|
3461
|
-
args =
|
3462
|
-
func =
|
3489
|
+
args = a_slice.call(arguments, 0, -1);
|
3490
|
+
func = a_slice.call(arguments, -1)[0];
|
3463
3491
|
}
|
3464
3492
|
|
3465
3493
|
var cp = new ComputedProperty(func);
|
@@ -3474,7 +3502,11 @@ Ember.computed = function(func) {
|
|
3474
3502
|
})({});
|
3475
3503
|
|
3476
3504
|
(function(exports) {
|
3477
|
-
/*jshint newcap:
|
3505
|
+
/*jshint newcap:false*/
|
3506
|
+
|
3507
|
+
// NOTE: There is a bug in jshint that doesn't recognize `Object()` without `new`
|
3508
|
+
// as being ok unless both `newcap:false` and not `use strict`.
|
3509
|
+
// https://github.com/jshint/jshint/issues/392
|
3478
3510
|
|
3479
3511
|
// Testing this is not ideal, but we want ArrayUtils to use native functions
|
3480
3512
|
// if available, but not to use versions created by libraries like Prototype
|
@@ -3487,7 +3519,7 @@ var isNativeFunc = function(func) {
|
|
3487
3519
|
// From: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/array/map
|
3488
3520
|
/** @private */
|
3489
3521
|
var arrayMap = isNativeFunc(Array.prototype.map) ? Array.prototype.map : function(fun /*, thisp */) {
|
3490
|
-
"use strict";
|
3522
|
+
//"use strict";
|
3491
3523
|
|
3492
3524
|
if (this === void 0 || this === null) {
|
3493
3525
|
throw new TypeError();
|
@@ -3513,7 +3545,7 @@ var arrayMap = isNativeFunc(Array.prototype.map) ? Array.prototype.map : functio
|
|
3513
3545
|
// From: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/array/foreach
|
3514
3546
|
/** @private */
|
3515
3547
|
var arrayForEach = isNativeFunc(Array.prototype.forEach) ? Array.prototype.forEach : function(fun /*, thisp */) {
|
3516
|
-
"use strict";
|
3548
|
+
//"use strict";
|
3517
3549
|
|
3518
3550
|
if (this === void 0 || this === null) {
|
3519
3551
|
throw new TypeError();
|
@@ -3558,6 +3590,11 @@ Ember.ArrayUtils = {
|
|
3558
3590
|
indexOf: function(obj) {
|
3559
3591
|
var args = Array.prototype.slice.call(arguments, 1);
|
3560
3592
|
return obj.indexOf ? obj.indexOf.apply(obj, args) : arrayIndexOf.apply(obj, args);
|
3593
|
+
},
|
3594
|
+
|
3595
|
+
removeObject: function(array, item) {
|
3596
|
+
var index = this.indexOf(array, item);
|
3597
|
+
if (index !== -1) { array.splice(index, 1); }
|
3561
3598
|
}
|
3562
3599
|
};
|
3563
3600
|
|
@@ -3592,56 +3629,70 @@ var BEFORE_OBSERVERS = ':before';
|
|
3592
3629
|
var guidFor = Ember.guidFor;
|
3593
3630
|
var normalizePath = Ember.normalizePath;
|
3594
3631
|
|
3595
|
-
var
|
3632
|
+
var deferred = 0;
|
3596
3633
|
var array_Slice = Array.prototype.slice;
|
3597
3634
|
var array_ForEach = Ember.ArrayUtils.forEach;
|
3598
3635
|
|
3599
3636
|
/** @private */
|
3600
|
-
var ObserverSet = function(
|
3601
|
-
this.
|
3602
|
-
if (iterateable) { this.array = []; }
|
3637
|
+
var ObserverSet = function () {
|
3638
|
+
this.targetSet = {};
|
3603
3639
|
};
|
3604
|
-
|
3605
|
-
|
3606
|
-
|
3607
|
-
|
3608
|
-
if (!
|
3609
|
-
|
3610
|
-
|
3611
|
-
|
3640
|
+
ObserverSet.prototype.add = function (target, path) {
|
3641
|
+
var targetSet = this.targetSet,
|
3642
|
+
targetGuid = Ember.guidFor(target),
|
3643
|
+
pathSet = targetSet[targetGuid];
|
3644
|
+
if (!pathSet) {
|
3645
|
+
targetSet[targetGuid] = pathSet = {};
|
3646
|
+
}
|
3647
|
+
if (pathSet[path]) {
|
3648
|
+
return false;
|
3649
|
+
} else {
|
3650
|
+
return pathSet[path] = true;
|
3612
3651
|
}
|
3613
3652
|
};
|
3653
|
+
ObserverSet.prototype.clear = function () {
|
3654
|
+
this.targetSet = {};
|
3655
|
+
};
|
3614
3656
|
|
3615
|
-
|
3616
|
-
|
3617
|
-
|
3657
|
+
/** @private */
|
3658
|
+
var DeferredEventQueue = function() {
|
3659
|
+
this.targetSet = {};
|
3660
|
+
this.queue = [];
|
3618
3661
|
};
|
3619
3662
|
|
3620
|
-
|
3621
|
-
|
3622
|
-
|
3663
|
+
DeferredEventQueue.prototype.push = function(target, eventName) {
|
3664
|
+
var targetSet = this.targetSet,
|
3665
|
+
queue = this.queue,
|
3666
|
+
targetGuid = Ember.guidFor(target),
|
3667
|
+
eventNameSet = targetSet[targetGuid],
|
3668
|
+
index;
|
3669
|
+
|
3670
|
+
if (!eventNameSet) {
|
3671
|
+
targetSet[targetGuid] = eventNameSet = {};
|
3672
|
+
}
|
3673
|
+
index = eventNameSet[eventName];
|
3674
|
+
if (index === undefined) {
|
3675
|
+
eventNameSet[eventName] = queue.push(Ember.deferEvent(target, eventName)) - 1;
|
3676
|
+
} else {
|
3677
|
+
queue[index] = Ember.deferEvent(target, eventName);
|
3678
|
+
}
|
3623
3679
|
};
|
3624
3680
|
|
3625
|
-
|
3626
|
-
var
|
3627
|
-
this.
|
3628
|
-
|
3629
|
-
|
3630
|
-
|
3681
|
+
DeferredEventQueue.prototype.flush = function() {
|
3682
|
+
var queue = this.queue;
|
3683
|
+
this.queue = [];
|
3684
|
+
this.targetSet = {};
|
3685
|
+
for (var i=0, len=queue.length; i < len; ++i) {
|
3686
|
+
queue[i]();
|
3687
|
+
}
|
3631
3688
|
};
|
3632
3689
|
|
3633
|
-
var queue = new
|
3690
|
+
var queue = new DeferredEventQueue(), beforeObserverSet = new ObserverSet();
|
3634
3691
|
|
3635
3692
|
/** @private */
|
3636
3693
|
function notifyObservers(obj, eventName, forceNotification) {
|
3637
|
-
if (
|
3638
|
-
|
3639
|
-
// if suspended add to the queue to send event later - but only send
|
3640
|
-
// event once.
|
3641
|
-
if (!queue.contains(obj, eventName)) {
|
3642
|
-
queue.add(obj, eventName);
|
3643
|
-
}
|
3644
|
-
|
3694
|
+
if (deferred && !forceNotification) {
|
3695
|
+
queue.push(obj, eventName);
|
3645
3696
|
} else {
|
3646
3697
|
Ember.sendEvent(obj, eventName);
|
3647
3698
|
}
|
@@ -3649,20 +3700,19 @@ function notifyObservers(obj, eventName, forceNotification) {
|
|
3649
3700
|
|
3650
3701
|
/** @private */
|
3651
3702
|
function flushObserverQueue() {
|
3652
|
-
beforeObserverSet.
|
3703
|
+
beforeObserverSet.clear();
|
3653
3704
|
|
3654
|
-
|
3655
|
-
queue.forEach(function(target, event){ Ember.sendEvent(target, event); });
|
3705
|
+
queue.flush();
|
3656
3706
|
}
|
3657
3707
|
|
3658
3708
|
Ember.beginPropertyChanges = function() {
|
3659
|
-
|
3709
|
+
deferred++;
|
3660
3710
|
return this;
|
3661
3711
|
};
|
3662
3712
|
|
3663
3713
|
Ember.endPropertyChanges = function() {
|
3664
|
-
|
3665
|
-
if (
|
3714
|
+
deferred--;
|
3715
|
+
if (deferred<=0) flushObserverQueue();
|
3666
3716
|
};
|
3667
3717
|
|
3668
3718
|
/**
|
@@ -3674,15 +3724,30 @@ Ember.endPropertyChanges = function() {
|
|
3674
3724
|
obj2.set('bar', baz);
|
3675
3725
|
});
|
3676
3726
|
*/
|
3677
|
-
Ember.changeProperties = function(cb){
|
3727
|
+
Ember.changeProperties = function(cb, binding){
|
3678
3728
|
Ember.beginPropertyChanges();
|
3679
3729
|
try {
|
3680
|
-
cb();
|
3730
|
+
cb.call(binding);
|
3681
3731
|
} finally {
|
3682
3732
|
Ember.endPropertyChanges();
|
3683
3733
|
}
|
3684
3734
|
};
|
3685
3735
|
|
3736
|
+
/**
|
3737
|
+
Set a list of properties on an object. These properties are set inside
|
3738
|
+
a single `beginPropertyChanges` and `endPropertyChanges` batch, so
|
3739
|
+
observers will be buffered.
|
3740
|
+
*/
|
3741
|
+
Ember.setProperties = function(self, hash) {
|
3742
|
+
Ember.changeProperties(function(){
|
3743
|
+
for(var prop in hash) {
|
3744
|
+
if (hash.hasOwnProperty(prop)) Ember.set(self, prop, hash[prop]);
|
3745
|
+
}
|
3746
|
+
});
|
3747
|
+
return self;
|
3748
|
+
};
|
3749
|
+
|
3750
|
+
|
3686
3751
|
/** @private */
|
3687
3752
|
function changeEvent(keyName) {
|
3688
3753
|
return keyName+AFTER_OBSERVERS;
|
@@ -3759,6 +3824,15 @@ Ember.addBeforeObserver = function(obj, path, target, method) {
|
|
3759
3824
|
return this;
|
3760
3825
|
};
|
3761
3826
|
|
3827
|
+
// Suspend observer during callback.
|
3828
|
+
//
|
3829
|
+
// This should only be used by the target of the observer
|
3830
|
+
// while it is setting the observed path.
|
3831
|
+
/** @private */
|
3832
|
+
Ember._suspendObserver = function(obj, path, target, method, callback) {
|
3833
|
+
return Ember._suspendListener(obj, changeEvent(path), target, method, callback);
|
3834
|
+
};
|
3835
|
+
|
3762
3836
|
/** @private */
|
3763
3837
|
Ember.beforeObserversFor = function(obj, path) {
|
3764
3838
|
return Ember.listenersFor(obj, beforeEvent(path));
|
@@ -3773,16 +3847,19 @@ Ember.removeBeforeObserver = function(obj, path, target, method) {
|
|
3773
3847
|
|
3774
3848
|
/** @private */
|
3775
3849
|
Ember.notifyObservers = function(obj, keyName) {
|
3850
|
+
if (obj.isDestroying) { return; }
|
3851
|
+
|
3776
3852
|
notifyObservers(obj, changeEvent(keyName));
|
3777
3853
|
};
|
3778
3854
|
|
3779
3855
|
/** @private */
|
3780
3856
|
Ember.notifyBeforeObservers = function(obj, keyName) {
|
3857
|
+
if (obj.isDestroying) { return; }
|
3858
|
+
|
3781
3859
|
var guid, set, forceNotification = false;
|
3782
3860
|
|
3783
|
-
if (
|
3784
|
-
if (
|
3785
|
-
beforeObserverSet.add(obj, keyName);
|
3861
|
+
if (deferred) {
|
3862
|
+
if (beforeObserverSet.add(obj, keyName)) {
|
3786
3863
|
forceNotification = true;
|
3787
3864
|
} else {
|
3788
3865
|
return;
|
@@ -3857,6 +3934,8 @@ var WILL_SEEN, DID_SEEN;
|
|
3857
3934
|
// called whenever a property is about to change to clear the cache of any dependent keys (and notify those properties of changes, etc...)
|
3858
3935
|
/** @private */
|
3859
3936
|
function dependentKeysWillChange(obj, depKey, meta) {
|
3937
|
+
if (obj.isDestroying) { return; }
|
3938
|
+
|
3860
3939
|
var seen = WILL_SEEN, top = !seen;
|
3861
3940
|
if (top) seen = WILL_SEEN = {};
|
3862
3941
|
iterDeps(propertyWillChange, obj, depKey, seen, meta);
|
@@ -3866,6 +3945,8 @@ function dependentKeysWillChange(obj, depKey, meta) {
|
|
3866
3945
|
// called whenever a property has just changed to update dependent keys
|
3867
3946
|
/** @private */
|
3868
3947
|
function dependentKeysDidChange(obj, depKey, meta) {
|
3948
|
+
if (obj.isDestroying) { return; }
|
3949
|
+
|
3869
3950
|
var seen = DID_SEEN, top = !seen;
|
3870
3951
|
if (top) seen = DID_SEEN = {};
|
3871
3952
|
iterDeps(propertyDidChange, obj, depKey, seen, meta);
|
@@ -4413,7 +4494,7 @@ Ember.destroy = function (obj) {
|
|
4413
4494
|
var o_create = Ember.platform.create;
|
4414
4495
|
var meta = Ember.meta;
|
4415
4496
|
var guidFor = Ember.guidFor;
|
4416
|
-
var
|
4497
|
+
var a_slice = Array.prototype.slice;
|
4417
4498
|
|
4418
4499
|
/**
|
4419
4500
|
The event system uses a series of nested hashes to store listeners on an
|
@@ -4464,49 +4545,52 @@ function targetSetFor(obj, eventName) {
|
|
4464
4545
|
// meta system.
|
4465
4546
|
var SKIP_PROPERTIES = { __ember_source__: true };
|
4466
4547
|
|
4467
|
-
// For a given target, invokes all of the methods that have
|
4468
|
-
// been registered as a listener.
|
4469
4548
|
/** @private */
|
4470
|
-
function
|
4549
|
+
function iterateSet(targetSet, callback, params) {
|
4550
|
+
if (!targetSet) { return false; }
|
4471
4551
|
// Iterate through all elements of the target set
|
4472
4552
|
for(var targetGuid in targetSet) {
|
4473
4553
|
if (SKIP_PROPERTIES[targetGuid]) { continue; }
|
4474
4554
|
|
4475
4555
|
var actionSet = targetSet[targetGuid];
|
4476
|
-
|
4477
|
-
|
4478
|
-
|
4479
|
-
|
4480
|
-
|
4481
|
-
|
4482
|
-
|
4483
|
-
|
4484
|
-
|
4485
|
-
|
4486
|
-
|
4487
|
-
|
4488
|
-
// If there is no target, the target is the object
|
4489
|
-
// on which the event was fired.
|
4490
|
-
if (!target) { target = params[0]; }
|
4491
|
-
if ('string' === typeof method) { method = target[method]; }
|
4492
|
-
|
4493
|
-
// Listeners can provide an `xform` function, which can perform
|
4494
|
-
// arbitrary transformations, such as changing the order of
|
4495
|
-
// parameters.
|
4496
|
-
//
|
4497
|
-
// This is primarily used by ember-runtime's observer system, which
|
4498
|
-
// provides a higher level abstraction on top of events, including
|
4499
|
-
// dynamically looking up current values and passing them into the
|
4500
|
-
// registered listener.
|
4501
|
-
var xform = action.xform;
|
4502
|
-
|
4503
|
-
if (xform) {
|
4504
|
-
xform(target, method, params);
|
4505
|
-
} else {
|
4506
|
-
method.apply(target, params);
|
4556
|
+
if (actionSet) {
|
4557
|
+
// Iterate through the elements of the action set
|
4558
|
+
for(var methodGuid in actionSet) {
|
4559
|
+
if (SKIP_PROPERTIES[methodGuid]) { continue; }
|
4560
|
+
|
4561
|
+
var action = actionSet[methodGuid];
|
4562
|
+
if (action) {
|
4563
|
+
if (callback(action, params) === true) {
|
4564
|
+
return true;
|
4565
|
+
}
|
4566
|
+
}
|
4507
4567
|
}
|
4508
4568
|
}
|
4509
4569
|
}
|
4570
|
+
return false;
|
4571
|
+
}
|
4572
|
+
|
4573
|
+
/** @private */
|
4574
|
+
function invokeAction(action, params) {
|
4575
|
+
var method = action.method, target = action.target, xform = action.xform;
|
4576
|
+
// If there is no target, the target is the object
|
4577
|
+
// on which the event was fired.
|
4578
|
+
if (!target) { target = params[0]; }
|
4579
|
+
if ('string' === typeof method) { method = target[method]; }
|
4580
|
+
|
4581
|
+
// Listeners can provide an `xform` function, which can perform
|
4582
|
+
// arbitrary transformations, such as changing the order of
|
4583
|
+
// parameters.
|
4584
|
+
//
|
4585
|
+
// This is primarily used by ember-runtime's observer system, which
|
4586
|
+
// provides a higher level abstraction on top of events, including
|
4587
|
+
// dynamically looking up current values and passing them into the
|
4588
|
+
// registered listener.
|
4589
|
+
if (xform) {
|
4590
|
+
xform(target, method, params);
|
4591
|
+
} else {
|
4592
|
+
method.apply(target, params);
|
4593
|
+
}
|
4510
4594
|
}
|
4511
4595
|
|
4512
4596
|
/**
|
@@ -4560,6 +4644,31 @@ function removeListener(obj, eventName, target, method) {
|
|
4560
4644
|
}
|
4561
4645
|
}
|
4562
4646
|
|
4647
|
+
// Suspend listener during callback.
|
4648
|
+
//
|
4649
|
+
// This should only be used by the target of the event listener
|
4650
|
+
// when it is taking an action that would cause the event, e.g.
|
4651
|
+
// an object might suspend its property change listener while it is
|
4652
|
+
// setting that property.
|
4653
|
+
/** @private */
|
4654
|
+
function suspendListener(obj, eventName, target, method, callback) {
|
4655
|
+
if (!method && 'function' === typeof target) {
|
4656
|
+
method = target;
|
4657
|
+
target = null;
|
4658
|
+
}
|
4659
|
+
|
4660
|
+
var actionSet = actionSetFor(obj, eventName, target, true),
|
4661
|
+
methodGuid = guidFor(method),
|
4662
|
+
action = actionSet && actionSet[methodGuid];
|
4663
|
+
|
4664
|
+
actionSet[methodGuid] = null;
|
4665
|
+
try {
|
4666
|
+
return callback.call(target);
|
4667
|
+
} finally {
|
4668
|
+
actionSet[methodGuid] = action;
|
4669
|
+
}
|
4670
|
+
}
|
4671
|
+
|
4563
4672
|
// returns a list of currently watched events
|
4564
4673
|
/** @memberOf Ember */
|
4565
4674
|
function watchedEvents(obj) {
|
@@ -4580,30 +4689,37 @@ function sendEvent(obj, eventName) {
|
|
4580
4689
|
|
4581
4690
|
// first give object a chance to handle it
|
4582
4691
|
if (obj !== Ember && 'function' === typeof obj.sendEvent) {
|
4583
|
-
obj.sendEvent.apply(obj,
|
4692
|
+
obj.sendEvent.apply(obj, a_slice.call(arguments, 1));
|
4584
4693
|
}
|
4585
4694
|
|
4586
4695
|
var targetSet = targetSetFor(obj, eventName);
|
4587
|
-
|
4696
|
+
iterateSet(targetSet, invokeAction, arguments);
|
4588
4697
|
|
4589
|
-
invokeEvents(targetSet, arguments);
|
4590
4698
|
return true;
|
4591
4699
|
}
|
4592
4700
|
|
4593
|
-
|
4594
|
-
|
4595
|
-
|
4596
|
-
|
4597
|
-
|
4598
|
-
for(var targetGuid in targetSet) {
|
4599
|
-
if (SKIP_PROPERTIES[targetGuid] || !targetSet[targetGuid]) { continue; }
|
4701
|
+
function deferEvent(obj, eventName) {
|
4702
|
+
var targetSet = targetSetFor(obj, eventName), actions = [], params = arguments;
|
4703
|
+
iterateSet(targetSet, function (action) {
|
4704
|
+
actions.push(action);
|
4705
|
+
});
|
4600
4706
|
|
4601
|
-
|
4707
|
+
return function() {
|
4708
|
+
if (obj !== Ember && 'function' === typeof obj.sendEvent) {
|
4709
|
+
obj.sendEvent.apply(obj, a_slice.call(params, 1));
|
4710
|
+
}
|
4602
4711
|
|
4603
|
-
for(var
|
4604
|
-
|
4605
|
-
return true; // stop as soon as we find a valid listener
|
4712
|
+
for (var i=0, len=actions.length; i < len; ++i) {
|
4713
|
+
invokeAction(actions[i], params);
|
4606
4714
|
}
|
4715
|
+
};
|
4716
|
+
}
|
4717
|
+
|
4718
|
+
/** @memberOf Ember */
|
4719
|
+
function hasListeners(obj, eventName) {
|
4720
|
+
var targetSet = targetSetFor(obj, eventName);
|
4721
|
+
if (iterateSet(targetSet, function () {return true;})) {
|
4722
|
+
return true;
|
4607
4723
|
}
|
4608
4724
|
|
4609
4725
|
// no listeners! might as well clean this up so it is faster later.
|
@@ -4616,31 +4732,20 @@ function hasListeners(obj, eventName) {
|
|
4616
4732
|
/** @memberOf Ember */
|
4617
4733
|
function listenersFor(obj, eventName) {
|
4618
4734
|
var targetSet = targetSetFor(obj, eventName), ret = [];
|
4619
|
-
|
4620
|
-
|
4621
|
-
|
4622
|
-
for(var targetGuid in targetSet) {
|
4623
|
-
if (SKIP_PROPERTIES[targetGuid] || !targetSet[targetGuid]) { continue; }
|
4624
|
-
|
4625
|
-
var actionSet = targetSet[targetGuid];
|
4626
|
-
|
4627
|
-
for(var methodGuid in actionSet) {
|
4628
|
-
if (SKIP_PROPERTIES[methodGuid] || !actionSet[methodGuid]) { continue; }
|
4629
|
-
info = actionSet[methodGuid];
|
4630
|
-
ret.push([info.target, info.method]);
|
4631
|
-
}
|
4632
|
-
}
|
4633
|
-
|
4735
|
+
iterateSet(targetSet, function (action) {
|
4736
|
+
ret.push([action.target, action.method]);
|
4737
|
+
});
|
4634
4738
|
return ret;
|
4635
4739
|
}
|
4636
4740
|
|
4637
4741
|
Ember.addListener = addListener;
|
4638
4742
|
Ember.removeListener = removeListener;
|
4743
|
+
Ember._suspendListener = suspendListener;
|
4639
4744
|
Ember.sendEvent = sendEvent;
|
4640
4745
|
Ember.hasListeners = hasListeners;
|
4641
4746
|
Ember.watchedEvents = watchedEvents;
|
4642
4747
|
Ember.listenersFor = listenersFor;
|
4643
|
-
|
4748
|
+
Ember.deferEvent = deferEvent;
|
4644
4749
|
})({});
|
4645
4750
|
|
4646
4751
|
(function(exports) {
|
@@ -4808,6 +4913,12 @@ function applyMixin(obj, mixins, partial) {
|
|
4808
4913
|
|
4809
4914
|
var mixinBindings = Ember._mixinBindings;
|
4810
4915
|
|
4916
|
+
// Go through all mixins and hashes passed in, and:
|
4917
|
+
//
|
4918
|
+
// * Handle concatenated properties
|
4919
|
+
// * Set up _super wrapping if necessary
|
4920
|
+
// * Set up descriptors (simple, watched or computed properties)
|
4921
|
+
// * Copying `toString` in broken browsers
|
4811
4922
|
mergeMixins(mixins, meta(obj), descs, values, obj);
|
4812
4923
|
|
4813
4924
|
if (MixinDelegate.detect(obj)) {
|
@@ -5314,17 +5425,24 @@ RunLoop.prototype = {
|
|
5314
5425
|
while (this._queues && (queue = this._queues[queueName])) {
|
5315
5426
|
this._queues[queueName] = null;
|
5316
5427
|
|
5317
|
-
log = Ember.LOG_BINDINGS && queueName==='sync';
|
5318
|
-
if (log) Ember.Logger.log('Begin: Flush Sync Queue');
|
5319
|
-
|
5320
5428
|
// the sync phase is to allow property changes to propogate. don't
|
5321
5429
|
// invoke observers until that is finished.
|
5322
|
-
if (queueName === 'sync')
|
5323
|
-
|
5324
|
-
|
5430
|
+
if (queueName === 'sync') {
|
5431
|
+
log = Ember.LOG_BINDINGS;
|
5432
|
+
if (log) Ember.Logger.log('Begin: Flush Sync Queue');
|
5325
5433
|
|
5326
|
-
|
5434
|
+
Ember.beginPropertyChanges();
|
5435
|
+
try {
|
5436
|
+
forEach(queue, iter);
|
5437
|
+
} finally {
|
5438
|
+
Ember.endPropertyChanges();
|
5439
|
+
}
|
5327
5440
|
|
5441
|
+
if (log) Ember.Logger.log('End: Flush Sync Queue');
|
5442
|
+
|
5443
|
+
} else {
|
5444
|
+
forEach(queue, iter);
|
5445
|
+
}
|
5328
5446
|
}
|
5329
5447
|
|
5330
5448
|
} else {
|
@@ -5336,17 +5454,26 @@ RunLoop.prototype = {
|
|
5336
5454
|
queueName = queueNames[idx];
|
5337
5455
|
queue = queues[queueName];
|
5338
5456
|
|
5339
|
-
|
5340
|
-
|
5341
|
-
|
5342
|
-
|
5343
|
-
|
5344
|
-
|
5345
|
-
|
5346
|
-
|
5457
|
+
if (queue) {
|
5458
|
+
// the sync phase is to allow property changes to propogate. don't
|
5459
|
+
// invoke observers until that is finished.
|
5460
|
+
if (queueName === 'sync') {
|
5461
|
+
log = Ember.LOG_BINDINGS;
|
5462
|
+
if (log) Ember.Logger.log('Begin: Flush Sync Queue');
|
5463
|
+
|
5464
|
+
Ember.beginPropertyChanges();
|
5465
|
+
try {
|
5466
|
+
forEach(queue, iter);
|
5467
|
+
} finally {
|
5468
|
+
Ember.endPropertyChanges();
|
5469
|
+
}
|
5347
5470
|
|
5471
|
+
if (log) Ember.Logger.log('End: Flush Sync Queue');
|
5472
|
+
} else {
|
5473
|
+
forEach(queue, iter);
|
5474
|
+
}
|
5475
|
+
}
|
5348
5476
|
}
|
5349
|
-
|
5350
5477
|
} while (queues = this._queues); // go until queues stay clean
|
5351
5478
|
}
|
5352
5479
|
|
@@ -5891,19 +6018,21 @@ function getPathWithGlobals(obj, path) {
|
|
5891
6018
|
}
|
5892
6019
|
|
5893
6020
|
/** @private */
|
5894
|
-
function
|
5895
|
-
var operation = binding._operation
|
5896
|
-
|
6021
|
+
function getTransformedFromValue(obj, binding) {
|
6022
|
+
var operation = binding._operation,
|
6023
|
+
fromValue;
|
5897
6024
|
if (operation) {
|
5898
|
-
|
6025
|
+
fromValue = operation(obj, binding._from, binding._operand);
|
5899
6026
|
} else {
|
5900
|
-
|
6027
|
+
fromValue = getPathWithGlobals(obj, binding._from);
|
5901
6028
|
}
|
6029
|
+
return getTransformedValue(binding, fromValue, obj, 'to');
|
5902
6030
|
}
|
5903
6031
|
|
5904
6032
|
/** @private */
|
5905
|
-
function
|
5906
|
-
|
6033
|
+
function getTransformedToValue(obj, binding) {
|
6034
|
+
var toValue = getPath(obj, binding._to);
|
6035
|
+
return getTransformedValue(binding, toValue, obj, 'from');
|
5907
6036
|
}
|
5908
6037
|
|
5909
6038
|
/** @private */
|
@@ -5919,7 +6048,6 @@ var OR_OPERATION = function(obj, left, right) {
|
|
5919
6048
|
// ..........................................................
|
5920
6049
|
// BINDING
|
5921
6050
|
//
|
5922
|
-
|
5923
6051
|
/** @private */
|
5924
6052
|
var K = function() {};
|
5925
6053
|
|
@@ -5940,9 +6068,6 @@ var Binding = function(toPath, fromPath) {
|
|
5940
6068
|
self._from = fromPath;
|
5941
6069
|
self._to = toPath;
|
5942
6070
|
|
5943
|
-
/** @private */
|
5944
|
-
self._cache = {};
|
5945
|
-
|
5946
6071
|
return self;
|
5947
6072
|
};
|
5948
6073
|
|
@@ -6275,55 +6400,32 @@ Binding.prototype = /** @scope Ember.Binding.prototype */ {
|
|
6275
6400
|
// synchronizing from
|
6276
6401
|
var guid = guidFor(obj), direction = this[guid];
|
6277
6402
|
|
6278
|
-
var fromPath = this._from, toPath = this._to
|
6403
|
+
var fromPath = this._from, toPath = this._to;
|
6279
6404
|
|
6280
6405
|
delete this[guid];
|
6281
6406
|
|
6282
|
-
if (direction === 'fwd') {
|
6283
|
-
lastSet = this._cache.back;
|
6284
|
-
} else if (direction === 'back') {
|
6285
|
-
lastSet = this._cache.fwd;
|
6286
|
-
}
|
6287
|
-
|
6288
|
-
var fromValue, toValue;
|
6289
|
-
|
6290
|
-
// There's a bit of duplicate logic here, but the order is important.
|
6291
|
-
//
|
6292
|
-
// We want to avoid ping-pong bindings. To do this, we store off the
|
6293
|
-
// guid of the item we are setting. Later, we avoid synchronizing
|
6294
|
-
// bindings in the other direction if the raw value we are copying
|
6295
|
-
// is the same as the guid of the last thing we set.
|
6296
|
-
//
|
6297
|
-
// Use guids here to avoid unnecessarily holding hard references
|
6298
|
-
// to objects.
|
6299
|
-
if (direction === 'fwd') {
|
6300
|
-
fromValue = getFromValue(obj, this);
|
6301
|
-
if (this._cache.back === guidFor(fromValue)) { return; }
|
6302
|
-
this._cache.fwd = guidFor(fromValue);
|
6303
|
-
|
6304
|
-
toValue = getToValue(obj, this);
|
6305
|
-
} else if (direction === 'back') {
|
6306
|
-
toValue = getToValue(obj, this);
|
6307
|
-
if (this._cache.fwd === guidFor(toValue)) { return; }
|
6308
|
-
this._cache.back = guidFor(toValue);
|
6309
|
-
|
6310
|
-
fromValue = getFromValue(obj, this);
|
6311
|
-
}
|
6312
|
-
|
6313
|
-
fromValue = getTransformedValue(this, fromValue, obj, 'to');
|
6314
|
-
toValue = getTransformedValue(this, toValue, obj, 'from');
|
6315
|
-
|
6316
|
-
if (toValue === fromValue) { return; }
|
6317
|
-
|
6318
6407
|
// if we're synchronizing from the remote object...
|
6319
6408
|
if (direction === 'fwd') {
|
6320
|
-
|
6321
|
-
|
6322
|
-
|
6409
|
+
var fromValue = getTransformedFromValue(obj, this);
|
6410
|
+
if (log) {
|
6411
|
+
Ember.Logger.log(' ', this.toString(), '->', fromValue, obj);
|
6412
|
+
}
|
6413
|
+
if (this._oneWay) {
|
6414
|
+
Ember.trySetPath(Ember.isGlobalPath(toPath) ? window : obj, toPath, fromValue);
|
6415
|
+
} else {
|
6416
|
+
Ember._suspendObserver(obj, toPath, this, this.toDidChange, function () {
|
6417
|
+
Ember.trySetPath(Ember.isGlobalPath(toPath) ? window : obj, toPath, fromValue);
|
6418
|
+
});
|
6419
|
+
}
|
6323
6420
|
// if we're synchronizing *to* the remote object
|
6324
6421
|
} else if (direction === 'back') {// && !this._oneWay) {
|
6325
|
-
|
6326
|
-
|
6422
|
+
var toValue = getTransformedToValue(obj, this);
|
6423
|
+
if (log) {
|
6424
|
+
Ember.Logger.log(' ', this.toString(), '<-', toValue, obj);
|
6425
|
+
}
|
6426
|
+
Ember._suspendObserver(obj, fromPath, this, this.fromDidChange, function () {
|
6427
|
+
Ember.trySetPath(Ember.isGlobalPath(fromPath) ? window : obj, fromPath, toValue);
|
6428
|
+
});
|
6327
6429
|
}
|
6328
6430
|
}
|
6329
6431
|
|
@@ -6971,9 +7073,9 @@ Ember.inspect = function(obj) {
|
|
6971
7073
|
|
6972
7074
|
/**
|
6973
7075
|
Compares two objects, returning true if they are logically equal. This is
|
6974
|
-
a deeper comparison than a simple triple equal.
|
6975
|
-
|
6976
|
-
|
7076
|
+
a deeper comparison than a simple triple equal. For sets it will compare the
|
7077
|
+
internal objects. For any other object that implements `isEqual()` it will
|
7078
|
+
respect that method.
|
6977
7079
|
|
6978
7080
|
@param {Object} a first object to compare
|
6979
7081
|
@param {Object} b second object to compare
|
@@ -7321,16 +7423,95 @@ var a_slice = Array.prototype.slice;
|
|
7321
7423
|
|
7322
7424
|
if (Ember.EXTEND_PROTOTYPES) {
|
7323
7425
|
|
7426
|
+
/**
|
7427
|
+
The `property` extension of Javascript's Function prototype is available
|
7428
|
+
when Ember.EXTEND_PROTOTYPES is true, which is the default.
|
7429
|
+
|
7430
|
+
Computed properties allow you to treat a function like a property:
|
7431
|
+
|
7432
|
+
MyApp.president = Ember.Object.create({
|
7433
|
+
firstName: "Barack",
|
7434
|
+
lastName: "Obama",
|
7435
|
+
|
7436
|
+
fullName: function() {
|
7437
|
+
return this.get('firstName') + ' ' + this.get('lastName');
|
7438
|
+
|
7439
|
+
// Call this flag to mark the function as a property
|
7440
|
+
}.property()
|
7441
|
+
});
|
7442
|
+
|
7443
|
+
MyApp.president.get('fullName'); => "Barack Obama"
|
7444
|
+
|
7445
|
+
Treating a function like a property is useful because they can work with
|
7446
|
+
bindings, just like any other property.
|
7447
|
+
|
7448
|
+
Many computed properties have dependencies on other properties. For
|
7449
|
+
example, in the above example, the `fullName` property depends on
|
7450
|
+
`firstName` and `lastName` to determine its value. You can tell Ember.js
|
7451
|
+
about these dependencies like this:
|
7452
|
+
|
7453
|
+
MyApp.president = Ember.Object.create({
|
7454
|
+
firstName: "Barack",
|
7455
|
+
lastName: "Obama",
|
7456
|
+
|
7457
|
+
fullName: function() {
|
7458
|
+
return this.get('firstName') + ' ' + this.get('lastName');
|
7459
|
+
|
7460
|
+
// Tell Ember.js that this computed property depends on firstName
|
7461
|
+
// and lastName
|
7462
|
+
}.property('firstName', 'lastName')
|
7463
|
+
});
|
7464
|
+
|
7465
|
+
Make sure you list these dependencies so Ember.js knows when to update
|
7466
|
+
bindings that connect to a computed property.
|
7467
|
+
|
7468
|
+
Note: you will usually want to use `property(...)` with `cacheable()`.
|
7469
|
+
|
7470
|
+
@see Ember.ComputedProperty
|
7471
|
+
@see Ember.computed
|
7472
|
+
*/
|
7324
7473
|
Function.prototype.property = function() {
|
7325
7474
|
var ret = Ember.computed(this);
|
7326
7475
|
return ret.property.apply(ret, arguments);
|
7327
7476
|
};
|
7328
7477
|
|
7478
|
+
/**
|
7479
|
+
The `observes` extension of Javascript's Function prototype is available
|
7480
|
+
when Ember.EXTEND_PROTOTYPES is true, which is the default.
|
7481
|
+
|
7482
|
+
You can observe property changes simply by adding the `observes`
|
7483
|
+
call to the end of your method declarations in classes that you write.
|
7484
|
+
For example:
|
7485
|
+
|
7486
|
+
Ember.Object.create({
|
7487
|
+
valueObserver: function() {
|
7488
|
+
// Executes whenever the "value" property changes
|
7489
|
+
}.observes('value')
|
7490
|
+
});
|
7491
|
+
|
7492
|
+
@see Ember.Observable
|
7493
|
+
*/
|
7329
7494
|
Function.prototype.observes = function() {
|
7330
7495
|
this.__ember_observes__ = a_slice.call(arguments);
|
7331
7496
|
return this;
|
7332
7497
|
};
|
7333
7498
|
|
7499
|
+
/**
|
7500
|
+
The `observesBefore` extension of Javascript's Function prototype is
|
7501
|
+
available when Ember.EXTEND_PROTOTYPES is true, which is the default.
|
7502
|
+
|
7503
|
+
You can get notified when a property changes is about to happen by
|
7504
|
+
by adding the `observesBefore` call to the end of your method
|
7505
|
+
declarations in classes that you write. For example:
|
7506
|
+
|
7507
|
+
Ember.Object.create({
|
7508
|
+
valueObserver: function() {
|
7509
|
+
// Executes whenever the "value" property is about to change
|
7510
|
+
}.observesBefore('value')
|
7511
|
+
});
|
7512
|
+
|
7513
|
+
@see Ember.Observable
|
7514
|
+
*/
|
7334
7515
|
Function.prototype.observesBefore = function() {
|
7335
7516
|
this.__ember_observesBefore__ = a_slice.call(arguments);
|
7336
7517
|
return this;
|
@@ -9265,13 +9446,7 @@ Ember.Observable = Ember.Mixin.create(/** @scope Ember.Observable.prototype */ {
|
|
9265
9446
|
@returns {Ember.Observable}
|
9266
9447
|
*/
|
9267
9448
|
setProperties: function(hash) {
|
9268
|
-
|
9269
|
-
Ember.changeProperties(function(){
|
9270
|
-
for(var prop in hash) {
|
9271
|
-
if (hash.hasOwnProperty(prop)) set(self, prop, hash[prop]);
|
9272
|
-
}
|
9273
|
-
});
|
9274
|
-
return this;
|
9449
|
+
return Ember.setProperties(this, hash);
|
9275
9450
|
},
|
9276
9451
|
|
9277
9452
|
/**
|
@@ -9280,9 +9455,9 @@ Ember.Observable = Ember.Mixin.create(/** @scope Ember.Observable.prototype */ {
|
|
9280
9455
|
You can use this method to group property changes so that notifications
|
9281
9456
|
will not be sent until the changes are finished. If you plan to make a
|
9282
9457
|
large number of changes to an object at one time, you should call this
|
9283
|
-
method at the beginning of the changes to
|
9284
|
-
When you are done making changes, call endPropertyChanges()
|
9285
|
-
|
9458
|
+
method at the beginning of the changes to begin deferring change
|
9459
|
+
notifications. When you are done making changes, call endPropertyChanges()
|
9460
|
+
to deliver the deferred change notifications and end deferring.
|
9286
9461
|
|
9287
9462
|
@returns {Ember.Observable}
|
9288
9463
|
*/
|
@@ -9297,9 +9472,9 @@ Ember.Observable = Ember.Mixin.create(/** @scope Ember.Observable.prototype */ {
|
|
9297
9472
|
You can use this method to group property changes so that notifications
|
9298
9473
|
will not be sent until the changes are finished. If you plan to make a
|
9299
9474
|
large number of changes to an object at one time, you should call
|
9300
|
-
beginPropertyChanges() at the beginning of the changes to
|
9301
|
-
notifications. When you are done making changes, call this method to
|
9302
|
-
|
9475
|
+
beginPropertyChanges() at the beginning of the changes to defer change
|
9476
|
+
notifications. When you are done making changes, call this method to
|
9477
|
+
deliver the deferred change notifications and end deferring.
|
9303
9478
|
|
9304
9479
|
@returns {Ember.Observable}
|
9305
9480
|
*/
|
@@ -9614,11 +9789,11 @@ Ember.TargetActionSupport = Ember.Mixin.create({
|
|
9614
9789
|
})({});
|
9615
9790
|
|
9616
9791
|
(function(exports) {
|
9617
|
-
var get = Ember.get, set = Ember.set;
|
9792
|
+
var get = Ember.get, set = Ember.set, a_slice = Array.prototype.slice;
|
9618
9793
|
|
9619
9794
|
/** @private */
|
9620
9795
|
function xform(target, method, params) {
|
9621
|
-
var args =
|
9796
|
+
var args = a_slice.call(params, 2);
|
9622
9797
|
method.apply(target, args);
|
9623
9798
|
}
|
9624
9799
|
|
@@ -9633,7 +9808,7 @@ Ember.Evented = Ember.Mixin.create({
|
|
9633
9808
|
},
|
9634
9809
|
|
9635
9810
|
fire: function(name) {
|
9636
|
-
Ember.sendEvent.apply(null, [this, name].concat(
|
9811
|
+
Ember.sendEvent.apply(null, [this, name].concat(a_slice.call(arguments, 1)));
|
9637
9812
|
},
|
9638
9813
|
|
9639
9814
|
off: function(name, target, method) {
|
@@ -9671,6 +9846,7 @@ var classToString = Ember.Mixin.prototype.toString;
|
|
9671
9846
|
var set = Ember.set, get = Ember.get;
|
9672
9847
|
var o_create = Ember.platform.create,
|
9673
9848
|
o_defineProperty = Ember.platform.defineProperty,
|
9849
|
+
a_slice = Array.prototype.slice,
|
9674
9850
|
meta = Ember.meta;
|
9675
9851
|
|
9676
9852
|
/** @private */
|
@@ -9680,14 +9856,23 @@ function makeCtor() {
|
|
9680
9856
|
// method a lot faster. This is glue code so we want it to be as fast as
|
9681
9857
|
// possible.
|
9682
9858
|
|
9683
|
-
var
|
9859
|
+
var wasApplied = false, initMixins, defaults, init = false, hasChains = false;
|
9684
9860
|
|
9685
9861
|
var Class = function() {
|
9686
|
-
if (
|
9862
|
+
if (defaults) {
|
9863
|
+
for (var prop in defaults) {
|
9864
|
+
if (!defaults.hasOwnProperty(prop)) { continue; }
|
9865
|
+
Ember.defineProperty(this, prop, undefined, defaults[prop]);
|
9866
|
+
}
|
9867
|
+
|
9868
|
+
defaults = null;
|
9869
|
+
}
|
9870
|
+
|
9871
|
+
if (!wasApplied) { Class.proto(); } // prepare prototype...
|
9687
9872
|
if (initMixins) {
|
9688
9873
|
this.reopen.apply(this, initMixins);
|
9689
9874
|
initMixins = null;
|
9690
|
-
rewatch(this); //
|
9875
|
+
rewatch(this); // always rewatch just in case
|
9691
9876
|
this.init.apply(this, arguments);
|
9692
9877
|
} else {
|
9693
9878
|
if (hasChains) {
|
@@ -9704,20 +9889,29 @@ function makeCtor() {
|
|
9704
9889
|
};
|
9705
9890
|
|
9706
9891
|
Class.toString = classToString;
|
9707
|
-
Class.
|
9708
|
-
|
9709
|
-
|
9892
|
+
Class.willReopen = function() {
|
9893
|
+
if (wasApplied) {
|
9894
|
+
Class.PrototypeMixin = Ember.Mixin.create(Class.PrototypeMixin);
|
9895
|
+
}
|
9896
|
+
|
9897
|
+
wasApplied = false;
|
9710
9898
|
};
|
9711
9899
|
Class._initMixins = function(args) { initMixins = args; };
|
9900
|
+
Class._setDefaults = function(arg) { defaults = arg; };
|
9712
9901
|
|
9713
|
-
|
9714
|
-
|
9715
|
-
|
9902
|
+
Class.proto = function() {
|
9903
|
+
var superclass = Class.superclass;
|
9904
|
+
if (superclass) { superclass.proto(); }
|
9905
|
+
|
9906
|
+
if (!wasApplied) {
|
9907
|
+
wasApplied = true;
|
9716
9908
|
Class.PrototypeMixin.applyPartial(Class.prototype);
|
9909
|
+
Ember.rewatch(Class.prototype); // setup watch chains if needed.
|
9717
9910
|
hasChains = !!meta(Class.prototype, false).chains; // avoid rewatch
|
9718
9911
|
}
|
9912
|
+
|
9719
9913
|
return this.prototype;
|
9720
|
-
}
|
9914
|
+
};
|
9721
9915
|
|
9722
9916
|
return Class;
|
9723
9917
|
|
@@ -9738,6 +9932,7 @@ CoreObject.PrototypeMixin = Ember.Mixin.create(
|
|
9738
9932
|
init: function() {},
|
9739
9933
|
|
9740
9934
|
isDestroyed: false,
|
9935
|
+
isDestroying: false,
|
9741
9936
|
|
9742
9937
|
/**
|
9743
9938
|
Destroys an object by setting the isDestroyed flag and removing its
|
@@ -9752,6 +9947,12 @@ CoreObject.PrototypeMixin = Ember.Mixin.create(
|
|
9752
9947
|
@returns {Ember.Object} receiver
|
9753
9948
|
*/
|
9754
9949
|
destroy: function() {
|
9950
|
+
if (this.isDestroying) { return; }
|
9951
|
+
|
9952
|
+
this.isDestroying = true;
|
9953
|
+
|
9954
|
+
if (this.willDestroy) { this.willDestroy(); }
|
9955
|
+
|
9755
9956
|
set(this, 'isDestroyed', true);
|
9756
9957
|
Ember.run.schedule('destroy', this, this._scheduledDestroy);
|
9757
9958
|
return this;
|
@@ -9765,6 +9966,7 @@ CoreObject.PrototypeMixin = Ember.Mixin.create(
|
|
9765
9966
|
*/
|
9766
9967
|
_scheduledDestroy: function() {
|
9767
9968
|
Ember.destroy(this);
|
9969
|
+
if (this.didDestroy) { this.didDestroy(); }
|
9768
9970
|
},
|
9769
9971
|
|
9770
9972
|
bind: function(to, from) {
|
@@ -9808,7 +10010,6 @@ var ClassMixin = Ember.Mixin.create({
|
|
9808
10010
|
proto.constructor = Class;
|
9809
10011
|
Ember.generateGuid(proto, 'ember');
|
9810
10012
|
meta(proto).proto = proto; // this will disable observers on prototype
|
9811
|
-
Ember.rewatch(proto); // setup watch chains if needed.
|
9812
10013
|
|
9813
10014
|
|
9814
10015
|
Class.subclasses = Ember.Set ? new Ember.Set() : null;
|
@@ -9824,10 +10025,34 @@ var ClassMixin = Ember.Mixin.create({
|
|
9824
10025
|
return new C();
|
9825
10026
|
},
|
9826
10027
|
|
10028
|
+
/**
|
10029
|
+
@private
|
10030
|
+
|
10031
|
+
Right now, when a key is passed in `create` that is not already
|
10032
|
+
present in the superclass, we need to create a mixin object and
|
10033
|
+
apply the mixin to the object we're creating. This is
|
10034
|
+
unnecessarily expensive. Because Ember views are created a lot,
|
10035
|
+
this is a temporary convenience that will allow us to create
|
10036
|
+
a new object and set properties before `init` time.
|
10037
|
+
|
10038
|
+
The correct solution is for the default init code to detect
|
10039
|
+
properties that do not need special handling and call
|
10040
|
+
`setProperties` on them when `create` occurs. This will
|
10041
|
+
massively speed up `create` calls that do not need any special
|
10042
|
+
Ember features (like bindings, observers or computed properties)
|
10043
|
+
and are not overriding a computed property with a regular value.
|
10044
|
+
*/
|
10045
|
+
createWith: function(defaults) {
|
10046
|
+
var C = this;
|
10047
|
+
if (arguments.length>0) { this._initMixins(a_slice.call(arguments, 1)); }
|
10048
|
+
if (defaults) { this._setDefaults(defaults); }
|
10049
|
+
return new C();
|
10050
|
+
},
|
10051
|
+
|
9827
10052
|
reopen: function() {
|
10053
|
+
this.willReopen();
|
9828
10054
|
var PrototypeMixin = this.PrototypeMixin;
|
9829
10055
|
PrototypeMixin.reopen.apply(PrototypeMixin, arguments);
|
9830
|
-
this._prototypeMixinDidChange();
|
9831
10056
|
return this;
|
9832
10057
|
},
|
9833
10058
|
|
@@ -9848,7 +10073,7 @@ var ClassMixin = Ember.Mixin.create({
|
|
9848
10073
|
},
|
9849
10074
|
|
9850
10075
|
detectInstance: function(obj) {
|
9851
|
-
return this
|
10076
|
+
return obj instanceof this;
|
9852
10077
|
},
|
9853
10078
|
|
9854
10079
|
/**
|
@@ -9872,7 +10097,7 @@ var ClassMixin = Ember.Mixin.create({
|
|
9872
10097
|
This will return the original hash that was passed to `meta()`.
|
9873
10098
|
*/
|
9874
10099
|
metaForProperty: function(key) {
|
9875
|
-
var desc = meta(
|
10100
|
+
var desc = meta(this.proto(), false).descs[key];
|
9876
10101
|
|
9877
10102
|
ember_assert("metaForProperty() could not find a computed property with key '"+key+"'.", !!desc && desc instanceof Ember.ComputedProperty);
|
9878
10103
|
return desc._meta || {};
|
@@ -9883,7 +10108,7 @@ var ClassMixin = Ember.Mixin.create({
|
|
9883
10108
|
and any associated metadata (see `metaForProperty`) to the callback.
|
9884
10109
|
*/
|
9885
10110
|
eachComputedProperty: function(callback, binding) {
|
9886
|
-
var proto =
|
10111
|
+
var proto = this.proto(),
|
9887
10112
|
descs = meta(proto).descs,
|
9888
10113
|
empty = {},
|
9889
10114
|
property;
|
@@ -11905,8 +12130,6 @@ Ember.Application = Ember.Namespace.extend(
|
|
11905
12130
|
self.didBecomeReady();
|
11906
12131
|
});
|
11907
12132
|
}
|
11908
|
-
|
11909
|
-
this._super();
|
11910
12133
|
},
|
11911
12134
|
|
11912
12135
|
/** @private */
|
@@ -11988,7 +12211,7 @@ var childViewsProperty = Ember.computed(function() {
|
|
11988
12211
|
});
|
11989
12212
|
|
11990
12213
|
return ret;
|
11991
|
-
}).property(
|
12214
|
+
}).property().cacheable();
|
11992
12215
|
|
11993
12216
|
/**
|
11994
12217
|
@static
|
@@ -12176,7 +12399,7 @@ Ember.View = Ember.Object.extend(Ember.Evented,
|
|
12176
12399
|
*/
|
12177
12400
|
childViews: childViewsProperty,
|
12178
12401
|
|
12179
|
-
_childViews:
|
12402
|
+
_childViews: [],
|
12180
12403
|
|
12181
12404
|
/**
|
12182
12405
|
Return the nearest ancestor that is an instance of the provided
|
@@ -12261,6 +12484,8 @@ Ember.View = Ember.Object.extend(Ember.Evented,
|
|
12261
12484
|
collectionView, itemView, and contentView
|
12262
12485
|
*/
|
12263
12486
|
_parentViewDidChange: Ember.observer(function() {
|
12487
|
+
if (this.isDestroying) { return; }
|
12488
|
+
|
12264
12489
|
this.invokeRecursively(function(view) {
|
12265
12490
|
view.propertyDidChange('collectionView');
|
12266
12491
|
view.propertyDidChange('itemView');
|
@@ -13111,15 +13336,13 @@ Ember.View = Ember.Object.extend(Ember.Evented,
|
|
13111
13336
|
dispatch
|
13112
13337
|
*/
|
13113
13338
|
init: function() {
|
13114
|
-
var parentView = get(this, '_parentView');
|
13115
|
-
|
13116
13339
|
this._super();
|
13117
13340
|
|
13118
13341
|
// Register the view for event handling. This hash is used by
|
13119
13342
|
// Ember.RootResponder to dispatch incoming events.
|
13120
13343
|
Ember.View.views[get(this, 'elementId')] = this;
|
13121
13344
|
|
13122
|
-
var childViews =
|
13345
|
+
var childViews = get(this, '_childViews').slice();
|
13123
13346
|
|
13124
13347
|
// setup child views. be sure to clone the child views array first
|
13125
13348
|
set(this, '_childViews', childViews);
|
@@ -13150,12 +13373,19 @@ Ember.View = Ember.Object.extend(Ember.Evented,
|
|
13150
13373
|
@returns {Ember.View} receiver
|
13151
13374
|
*/
|
13152
13375
|
removeChild: function(view) {
|
13376
|
+
// If we're destroying, the entire subtree will be
|
13377
|
+
// freed, and the DOM will be handled separately,
|
13378
|
+
// so no need to mess with childViews.
|
13379
|
+
if (this.isDestroying) { return; }
|
13380
|
+
|
13153
13381
|
// update parent node
|
13154
13382
|
set(view, '_parentView', null);
|
13155
13383
|
|
13156
13384
|
// remove view from childViews array.
|
13157
13385
|
var childViews = get(this, '_childViews');
|
13158
|
-
|
13386
|
+
Ember.ArrayUtils.removeObject(childViews, view);
|
13387
|
+
|
13388
|
+
this.propertyDidChange('childViews');
|
13159
13389
|
|
13160
13390
|
return this;
|
13161
13391
|
},
|
@@ -13194,14 +13424,12 @@ Ember.View = Ember.Object.extend(Ember.Evented,
|
|
13194
13424
|
},
|
13195
13425
|
|
13196
13426
|
/**
|
13197
|
-
You must call
|
13427
|
+
You must call `destroy` on a view to destroy the view (and all of its
|
13198
13428
|
child views). This will remove the view from any parent node, then make
|
13199
13429
|
sure that the DOM element managed by the view can be released by the
|
13200
13430
|
memory manager.
|
13201
13431
|
*/
|
13202
|
-
|
13203
|
-
if (get(this, 'isDestroyed')) { return; }
|
13204
|
-
|
13432
|
+
willDestroy: function() {
|
13205
13433
|
// calling this._super() will nuke computed properties and observers,
|
13206
13434
|
// so collect any information we need before calling super.
|
13207
13435
|
var childViews = get(this, '_childViews'),
|
@@ -13226,9 +13454,7 @@ Ember.View = Ember.Object.extend(Ember.Evented,
|
|
13226
13454
|
// the DOM again.
|
13227
13455
|
if (parent) { parent.removeChild(this); }
|
13228
13456
|
|
13229
|
-
|
13230
|
-
|
13231
|
-
this._super();
|
13457
|
+
this.state = 'destroyed';
|
13232
13458
|
|
13233
13459
|
childLen = get(childViews, 'length');
|
13234
13460
|
for (var i=childLen-1; i>=0; i--) {
|
@@ -13238,8 +13464,6 @@ Ember.View = Ember.Object.extend(Ember.Evented,
|
|
13238
13464
|
|
13239
13465
|
// next remove view from global hash
|
13240
13466
|
delete Ember.View.views[get(this, 'elementId')];
|
13241
|
-
|
13242
|
-
return this; // done with cleanup
|
13243
13467
|
},
|
13244
13468
|
|
13245
13469
|
/**
|
@@ -13256,7 +13480,11 @@ Ember.View = Ember.Object.extend(Ember.Evented,
|
|
13256
13480
|
*/
|
13257
13481
|
createChildView: function(view, attrs) {
|
13258
13482
|
if (Ember.View.detect(view)) {
|
13259
|
-
|
13483
|
+
if (attrs) {
|
13484
|
+
view = view.createWith({ _parentView: this }, attrs);
|
13485
|
+
} else {
|
13486
|
+
view = view.createWith({ _parentView: this });
|
13487
|
+
}
|
13260
13488
|
|
13261
13489
|
var viewName = view.viewName;
|
13262
13490
|
|
@@ -13427,6 +13655,10 @@ var DOMManager = {
|
|
13427
13655
|
set(view, 'element', null);
|
13428
13656
|
|
13429
13657
|
Ember.$(elem).remove();
|
13658
|
+
},
|
13659
|
+
|
13660
|
+
empty: function(view) {
|
13661
|
+
view.$().empty();
|
13430
13662
|
}
|
13431
13663
|
};
|
13432
13664
|
|
@@ -13527,6 +13759,8 @@ Ember.View.states.preRender = {
|
|
13527
13759
|
return Ember.$();
|
13528
13760
|
},
|
13529
13761
|
|
13762
|
+
empty: Ember.K,
|
13763
|
+
|
13530
13764
|
// This exists for the removal warning, remove later
|
13531
13765
|
getElement: function(view){
|
13532
13766
|
if (view._willInsertElementAccessUnsupported) {
|
@@ -13590,8 +13824,12 @@ Ember.View.states.inBuffer = {
|
|
13590
13824
|
var buffer = view.buffer;
|
13591
13825
|
|
13592
13826
|
childView = this.createChildView(childView, options);
|
13593
|
-
get(view, '_childViews').
|
13827
|
+
get(view, '_childViews').push(childView);
|
13828
|
+
|
13594
13829
|
childView.renderToBuffer(buffer);
|
13830
|
+
|
13831
|
+
view.propertyDidChange('childViews');
|
13832
|
+
|
13595
13833
|
return childView;
|
13596
13834
|
},
|
13597
13835
|
|
@@ -13606,6 +13844,10 @@ Ember.View.states.inBuffer = {
|
|
13606
13844
|
return view;
|
13607
13845
|
},
|
13608
13846
|
|
13847
|
+
empty: function() {
|
13848
|
+
throw "EWOT";
|
13849
|
+
},
|
13850
|
+
|
13609
13851
|
// It should be impossible for a rendered view to be scheduled for
|
13610
13852
|
// insertion.
|
13611
13853
|
insertElement: function() {
|
@@ -13685,6 +13927,10 @@ Ember.View.states.hasElement = {
|
|
13685
13927
|
return view;
|
13686
13928
|
},
|
13687
13929
|
|
13930
|
+
empty: function(view) {
|
13931
|
+
view.domManager.empty(view);
|
13932
|
+
},
|
13933
|
+
|
13688
13934
|
// Handle events from `Ember.EventDispatcher`
|
13689
13935
|
handleEvent: function(view, eventName, evt) {
|
13690
13936
|
var handler = view[eventName];
|
@@ -13727,6 +13973,9 @@ Ember.View.states.destroyed = {
|
|
13727
13973
|
destroyElement: function() {
|
13728
13974
|
throw fmt(destroyedError, ['destroyElement']);
|
13729
13975
|
},
|
13976
|
+
empty: function() {
|
13977
|
+
throw fmt(destroyedError, ['empty']);
|
13978
|
+
},
|
13730
13979
|
|
13731
13980
|
setElement: function() {
|
13732
13981
|
throw fmt(destroyedError, ["set('element', ...)"]);
|
@@ -13788,6 +14037,9 @@ Ember.ContainerView = Ember.View.extend({
|
|
13788
14037
|
_childViews[idx] = view;
|
13789
14038
|
}, this);
|
13790
14039
|
|
14040
|
+
// Make the _childViews array observable
|
14041
|
+
Ember.A(_childViews);
|
14042
|
+
|
13791
14043
|
// Sets up an array observer on the child views array. This
|
13792
14044
|
// observer will detect when child views are added or removed
|
13793
14045
|
// and update the DOM to reflect the mutation.
|
@@ -13815,7 +14067,7 @@ Ember.ContainerView = Ember.View.extend({
|
|
13815
14067
|
|
13816
14068
|
@private
|
13817
14069
|
*/
|
13818
|
-
|
14070
|
+
willDestroy: function() {
|
13819
14071
|
get(this, 'childViews').removeArrayObserver(this, {
|
13820
14072
|
willChange: 'childViewsWillChange',
|
13821
14073
|
didChange: 'childViewsDidChange'
|
@@ -14037,13 +14289,11 @@ Ember.CollectionView = Ember.ContainerView.extend(
|
|
14037
14289
|
this.arrayDidChange(content, 0, null, len);
|
14038
14290
|
}, 'content'),
|
14039
14291
|
|
14040
|
-
|
14292
|
+
willDestroy: function() {
|
14041
14293
|
var content = get(this, 'content');
|
14042
14294
|
if (content) { content.removeArrayObserver(this); }
|
14043
14295
|
|
14044
14296
|
this._super();
|
14045
|
-
|
14046
|
-
return this;
|
14047
14297
|
},
|
14048
14298
|
|
14049
14299
|
arrayWillChange: function(content, start, removedCount) {
|
@@ -14060,8 +14310,17 @@ Ember.CollectionView = Ember.ContainerView.extend(
|
|
14060
14310
|
var childViews = get(this, 'childViews'), childView, idx, len;
|
14061
14311
|
|
14062
14312
|
len = get(childViews, 'length');
|
14313
|
+
|
14314
|
+
var removingAll = removedCount === len;
|
14315
|
+
|
14316
|
+
if (removingAll) {
|
14317
|
+
this.invokeForState('empty');
|
14318
|
+
}
|
14319
|
+
|
14063
14320
|
for (idx = start + removedCount - 1; idx >= start; idx--) {
|
14064
|
-
childViews[idx]
|
14321
|
+
childView = childViews[idx];
|
14322
|
+
if (removingAll) { childView.removedFromDOM = true; }
|
14323
|
+
childView.destroy();
|
14065
14324
|
}
|
14066
14325
|
},
|
14067
14326
|
|
@@ -15145,6 +15404,10 @@ var DOMManager = {
|
|
15145
15404
|
view.transitionTo('inDOM');
|
15146
15405
|
view._notifyDidInsertElement();
|
15147
15406
|
});
|
15407
|
+
},
|
15408
|
+
|
15409
|
+
empty: function(view) {
|
15410
|
+
view.morph.html("");
|
15148
15411
|
}
|
15149
15412
|
};
|
15150
15413
|
|
@@ -15369,7 +15632,6 @@ var get = Ember.get, getPath = Ember.Handlebars.getPath, set = Ember.set, fmt =
|
|
15369
15632
|
var forEach = Ember.ArrayUtils.forEach;
|
15370
15633
|
|
15371
15634
|
var EmberHandlebars = Ember.Handlebars, helpers = EmberHandlebars.helpers;
|
15372
|
-
var helpers = EmberHandlebars.helpers;
|
15373
15635
|
|
15374
15636
|
(function() {
|
15375
15637
|
// Binds a property into the DOM. This will create a hook in DOM that the
|
@@ -15947,7 +16209,7 @@ Ember.Handlebars.registerHelper('collection', function(path, options) {
|
|
15947
16209
|
|
15948
16210
|
// Extract item view class if provided else default to the standard class
|
15949
16211
|
var itemViewClass, itemViewPath = hash.itemViewClass;
|
15950
|
-
var collectionPrototype =
|
16212
|
+
var collectionPrototype = collectionClass.proto();
|
15951
16213
|
delete hash.itemViewClass;
|
15952
16214
|
itemViewClass = itemViewPath ? getPath(collectionPrototype, itemViewPath) : collectionPrototype.itemViewClass;
|
15953
16215
|
ember_assert(fmt("%@ #collection: Could not find %@", data.view, itemViewPath), !!itemViewClass);
|
@@ -15968,7 +16230,7 @@ Ember.Handlebars.registerHelper('collection', function(path, options) {
|
|
15968
16230
|
}
|
15969
16231
|
}
|
15970
16232
|
|
15971
|
-
var tagName = hash.tagName ||
|
16233
|
+
var tagName = hash.tagName || collectionPrototype.tagName;
|
15972
16234
|
|
15973
16235
|
if (fn) {
|
15974
16236
|
itemHash.template = fn;
|
@@ -16641,6 +16903,9 @@ Ember.Handlebars.bootstrap = function(ctx) {
|
|
16641
16903
|
var compile = (script.attr('type') === 'text/x-raw-handlebars') ?
|
16642
16904
|
Ember.$.proxy(Handlebars.compile, Handlebars) :
|
16643
16905
|
Ember.$.proxy(Ember.Handlebars.compile, Ember.Handlebars),
|
16906
|
+
// Get the id of the script, used by Ember.View's elementId property,
|
16907
|
+
// Look for data-element-id attribute.
|
16908
|
+
elementId = script.attr('data-element-id'),
|
16644
16909
|
// Get the name of the script, used by Ember.View's templateName property.
|
16645
16910
|
// First look for data-template-name attribute, then fall back to its
|
16646
16911
|
// id if no name is found.
|
@@ -16676,6 +16941,7 @@ Ember.Handlebars.bootstrap = function(ctx) {
|
|
16676
16941
|
tagName = script.attr('data-tag-name');
|
16677
16942
|
|
16678
16943
|
view = view.create({
|
16944
|
+
elementId: elementId,
|
16679
16945
|
template: template,
|
16680
16946
|
tagName: (tagName) ? tagName : undefined
|
16681
16947
|
});
|