/**
* This class is the base for `Binding` and `MultiBinding`.
* @private
*/
Ext.define('Ext.app.bind.BaseBinding', {
extend: 'Ext.util.Schedulable',
isBinding: true,
calls: 0,
kind: 20,
defaultOptions: {},
lastValue: undefined,
/**
* @cfg {Boolean} [single=false]
* This option instructs the binding to call its `destroy` method immediately after
* delivering the initial value.
* @since 5.0.0
*/
constructor: function(owner, callback, scope, options) {
var me = this;
me.options = options;
me.owner = owner;
me.scope = scope;
me.callback = callback;
//<debug>
if (!callback) {
Ext.raise('Callback is required');
}
//</debug>
// If given a string callback name, preserve the late binding:
me.lateBound = Ext.isString(callback);
if (options && options.deep) {
me.deep = true;
}
me.callParent();
},
destroy: function() {
var me = this,
owner = me.owner;
if (owner) {
owner.onBindDestroy(me);
}
me.callParent();
me.scope = me.callback = me.owner = null;
},
isReadOnly: function() {
return true;
},
privates: {
getScheduler: function() {
var owner = this.owner;
return owner && owner.getScheduler();
},
getSession: function() {
var owner = this.owner;
return owner.isSession ? owner : owner.getSession();
},
notify: function(value) {
var me = this,
options = me.options || me.defaultOptions,
previous = me.lastValue;
// We want to deliver if:
// 1) We've never been called
// 2) We're a deep binding, which means that our object reference may not have changed,
// but something under us has changed. For example a link stub or a model field
// binding
// 3) If the value has changed
// 4) If the value is an array. It's difficult to tell if the underlying data changed
if (!me.calls || me.deep || me.valueChanged(value, previous)) {
++me.calls;
me.lastValue = value;
if (me.lateBound) {
// Interestingly, lateBound-ness may be more efficient since it does
// not use the "call" method.
me.scope[me.callback](value, previous, me);
}
else {
me.callback.call(me.scope, value, previous, me);
}
if (options.single) {
me.destroy();
}
}
},
valueChanged: function(value, previous) {
var ret = true;
if (previous !== value) {
if (value && previous && value instanceof Date && previous instanceof Date) {
ret = value.getTime() !== previous.getTime();
}
}
else {
ret = Ext.isArray(value);
}
return ret;
}
}
});