embient 0.0.5 → 0.0.6
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.
@@ -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
|
});
|