Handle beforechange events for bound properties
This commit is contained in:
@@ -118,6 +118,13 @@ ol.Object = function(opt_values) {
|
|||||||
*/
|
*/
|
||||||
this.values_ = {};
|
this.values_ = {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lookup of beforechange listener keys.
|
||||||
|
* @type {Object.<string, goog.events.Key>}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
this.beforeChangeListeners_ = {};
|
||||||
|
|
||||||
if (goog.isDef(opt_values)) {
|
if (goog.isDef(opt_values)) {
|
||||||
this.setValues(opt_values);
|
this.setValues(opt_values);
|
||||||
}
|
}
|
||||||
@@ -240,11 +247,20 @@ ol.Object.getSetterName = function(key) {
|
|||||||
ol.Object.prototype.bindTo = function(key, target, opt_targetKey) {
|
ol.Object.prototype.bindTo = function(key, target, opt_targetKey) {
|
||||||
var targetKey = opt_targetKey || key;
|
var targetKey = opt_targetKey || key;
|
||||||
this.unbind(key);
|
this.unbind(key);
|
||||||
|
|
||||||
|
// listen for change:targetkey events
|
||||||
var eventType = ol.Object.getChangeEventType(targetKey);
|
var eventType = ol.Object.getChangeEventType(targetKey);
|
||||||
var listeners = ol.Object.getListeners(this);
|
var listeners = ol.Object.getListeners(this);
|
||||||
listeners[key] = goog.events.listen(target, eventType, function() {
|
listeners[key] = goog.events.listen(target, eventType, function() {
|
||||||
this.notifyInternal_(key);
|
this.notifyInternal_(key);
|
||||||
}, undefined, this);
|
}, undefined, this);
|
||||||
|
|
||||||
|
// listen for beforechange events and relay if key matches
|
||||||
|
this.beforeChangeListeners_[key] = goog.events.listen(target,
|
||||||
|
ol.ObjectEventType.BEFORECHANGE,
|
||||||
|
this.createBeforeChangeListener_(key, targetKey),
|
||||||
|
undefined, this);
|
||||||
|
|
||||||
var accessor = new ol.ObjectAccessor(target, targetKey);
|
var accessor = new ol.ObjectAccessor(target, targetKey);
|
||||||
var accessors = ol.Object.getAccessors(this);
|
var accessors = ol.Object.getAccessors(this);
|
||||||
accessors[key] = accessor;
|
accessors[key] = accessor;
|
||||||
@@ -253,6 +269,30 @@ ol.Object.prototype.bindTo = function(key, target, opt_targetKey) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a listener for beforechange events on a target object. This listener
|
||||||
|
* will relay events on this object if the event key matches the provided target
|
||||||
|
* key.
|
||||||
|
* @param {string} key The key on this object whose value will be changing.
|
||||||
|
* @param {string} targetKey The key on the target object.
|
||||||
|
* @return {function(this: ol.Object, ol.ObjectEvent)} Listener.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
ol.Object.prototype.createBeforeChangeListener_ = function(key, targetKey) {
|
||||||
|
/**
|
||||||
|
* Conditionally relay beforechange events if event key matches target key.
|
||||||
|
* @param {ol.ObjectEvent} event The beforechange event from the target.
|
||||||
|
* @this {ol.Object}
|
||||||
|
*/
|
||||||
|
return function(event) {
|
||||||
|
if (event.key === targetKey) {
|
||||||
|
this.dispatchEvent(
|
||||||
|
new ol.ObjectEvent(ol.ObjectEventType.BEFORECHANGE, key));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a value.
|
* Gets a value.
|
||||||
* @param {string} key Key name.
|
* @param {string} key Key name.
|
||||||
@@ -422,6 +462,13 @@ ol.Object.prototype.unbind = function(key) {
|
|||||||
delete accessors[key];
|
delete accessors[key];
|
||||||
this.values_[key] = value;
|
this.values_[key] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// unregister any beforechange listener
|
||||||
|
var listenerKey = this.beforeChangeListeners_[key];
|
||||||
|
if (listenerKey) {
|
||||||
|
goog.events.unlistenByKey(listenerKey);
|
||||||
|
delete this.beforeChangeListeners_[key];
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+102
-1
@@ -215,7 +215,7 @@ describe('ol.Object', function() {
|
|||||||
|
|
||||||
o2.set('k', 2);
|
o2.set('k', 2);
|
||||||
expect(beforeListener.calledOnce).to.be(true);
|
expect(beforeListener.calledOnce).to.be(true);
|
||||||
var args = listener2.firstCall.args;
|
var args = beforeListener.firstCall.args;
|
||||||
expect(args).to.have.length(1);
|
expect(args).to.have.length(1);
|
||||||
var event = args[0];
|
var event = args[0];
|
||||||
expect(event.key).to.be('k');
|
expect(event.key).to.be('k');
|
||||||
@@ -223,6 +223,54 @@ describe('ol.Object', function() {
|
|||||||
expect(oldValue).to.be(1);
|
expect(oldValue).to.be(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('relays beforechange events from bound objects', function() {
|
||||||
|
var target = new ol.Object({
|
||||||
|
foo: 'original value'
|
||||||
|
});
|
||||||
|
var object = new ol.Object();
|
||||||
|
object.bindTo('foo', target);
|
||||||
|
|
||||||
|
var oldValue;
|
||||||
|
var beforeListener = sinon.spy(function(event) {
|
||||||
|
oldValue = object.get(event.key);
|
||||||
|
});
|
||||||
|
object.on('beforechange', beforeListener);
|
||||||
|
|
||||||
|
target.set('foo', 'new value');
|
||||||
|
expect(beforeListener.calledOnce).to.be(true);
|
||||||
|
var args = beforeListener.firstCall.args;
|
||||||
|
expect(args).to.have.length(1);
|
||||||
|
var event = args[0];
|
||||||
|
expect(event.key).to.be('foo');
|
||||||
|
|
||||||
|
expect(oldValue).to.be('original value');
|
||||||
|
expect(object.get('foo')).to.be('new value');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('relays beforechange events when bound with a new key', function() {
|
||||||
|
var target = new ol.Object({
|
||||||
|
foo: 'original value'
|
||||||
|
});
|
||||||
|
var object = new ol.Object();
|
||||||
|
object.bindTo('bar', target, 'foo');
|
||||||
|
|
||||||
|
var oldValue;
|
||||||
|
var beforeListener = sinon.spy(function(event) {
|
||||||
|
oldValue = object.get(event.key);
|
||||||
|
});
|
||||||
|
object.on('beforechange', beforeListener);
|
||||||
|
|
||||||
|
target.set('foo', 'new value');
|
||||||
|
expect(beforeListener.calledOnce).to.be(true);
|
||||||
|
var args = beforeListener.firstCall.args;
|
||||||
|
expect(args).to.have.length(1);
|
||||||
|
var event = args[0];
|
||||||
|
expect(event.key).to.be('bar');
|
||||||
|
|
||||||
|
expect(oldValue).to.be('original value');
|
||||||
|
expect(object.get('bar')).to.be('new value');
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('bind', function() {
|
describe('bind', function() {
|
||||||
@@ -302,6 +350,59 @@ describe('ol.Object', function() {
|
|||||||
expect(o.get('k')).to.eql(1);
|
expect(o.get('k')).to.eql(1);
|
||||||
expect(o2.get('k')).to.eql(2);
|
expect(o2.get('k')).to.eql(2);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('stops relaying beforechange events', function() {
|
||||||
|
var target = new ol.Object({
|
||||||
|
foo: 'original value'
|
||||||
|
});
|
||||||
|
var object = new ol.Object();
|
||||||
|
object.bindTo('foo', target);
|
||||||
|
|
||||||
|
var listener = sinon.spy();
|
||||||
|
object.on('beforechange', listener);
|
||||||
|
|
||||||
|
target.set('foo', 'new value');
|
||||||
|
expect(listener.calledOnce).to.be(true);
|
||||||
|
var call = listener.firstCall;
|
||||||
|
expect(call.args).to.have.length(1);
|
||||||
|
expect(call.args[0].key).to.be('foo');
|
||||||
|
|
||||||
|
object.unbind('foo');
|
||||||
|
target.set('foo', 'another new value');
|
||||||
|
expect(listener.calledOnce).to.be(true);
|
||||||
|
|
||||||
|
expect(object.get('foo')).to.be('new value');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('selectively stops relaying beforechange events', function() {
|
||||||
|
var target = new ol.Object({
|
||||||
|
foo: 'original foo',
|
||||||
|
bar: 'original bar'
|
||||||
|
});
|
||||||
|
var object = new ol.Object();
|
||||||
|
object.bindTo('foo', target);
|
||||||
|
object.bindTo('bar', target);
|
||||||
|
|
||||||
|
var listener = sinon.spy();
|
||||||
|
object.on('beforechange', listener);
|
||||||
|
|
||||||
|
target.set('foo', 'new foo');
|
||||||
|
expect(listener.calledOnce).to.be(true);
|
||||||
|
|
||||||
|
target.set('bar', 'new bar');
|
||||||
|
expect(listener.callCount).to.be(2);
|
||||||
|
|
||||||
|
object.unbind('foo');
|
||||||
|
target.set('foo', 'another new foo');
|
||||||
|
expect(listener.callCount).to.be(2);
|
||||||
|
|
||||||
|
target.set('bar', 'another new bar');
|
||||||
|
expect(listener.callCount).to.be(3);
|
||||||
|
var lastCall = listener.getCall(2);
|
||||||
|
expect(lastCall.args).to.have.length(1);
|
||||||
|
expect(lastCall.args[0].key).to.be('bar');
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('unbindAll', function() {
|
describe('unbindAll', function() {
|
||||||
|
|||||||
Reference in New Issue
Block a user