Merge pull request #1198 from fredj/bindTo_transform
ol.Object#bindTo: getter and setter
This commit is contained in:
+14
-7
@@ -36,23 +36,30 @@ var visible = new ol.dom.Input(document.getElementById('visible'));
|
|||||||
visible.bindTo('checked', layer, 'visible');
|
visible.bindTo('checked', layer, 'visible');
|
||||||
|
|
||||||
var opacity = new ol.dom.Input(document.getElementById('opacity'));
|
var opacity = new ol.dom.Input(document.getElementById('opacity'));
|
||||||
opacity.bindTo('valueAsNumber', layer, 'opacity');
|
opacity.bindTo('value', layer, 'opacity')
|
||||||
|
.transform(parseFloat, String);
|
||||||
|
|
||||||
var hue = new ol.dom.Input(document.getElementById('hue'));
|
var hue = new ol.dom.Input(document.getElementById('hue'));
|
||||||
hue.bindTo('valueAsNumber', layer, 'hue');
|
hue.bindTo('value', layer, 'hue')
|
||||||
|
.transform(parseFloat, String);
|
||||||
|
|
||||||
var saturation = new ol.dom.Input(document.getElementById('saturation'));
|
var saturation = new ol.dom.Input(document.getElementById('saturation'));
|
||||||
saturation.bindTo('valueAsNumber', layer, 'saturation');
|
saturation.bindTo('value', layer, 'saturation')
|
||||||
|
.transform(parseFloat, String);
|
||||||
|
|
||||||
var contrast = new ol.dom.Input(document.getElementById('contrast'));
|
var contrast = new ol.dom.Input(document.getElementById('contrast'));
|
||||||
contrast.bindTo('valueAsNumber', layer, 'contrast');
|
contrast.bindTo('value', layer, 'contrast')
|
||||||
|
.transform(parseFloat, String);
|
||||||
|
|
||||||
var brightness = new ol.dom.Input(document.getElementById('brightness'));
|
var brightness = new ol.dom.Input(document.getElementById('brightness'));
|
||||||
brightness.bindTo('valueAsNumber', layer, 'brightness');
|
brightness.bindTo('value', layer, 'brightness')
|
||||||
|
.transform(parseFloat, String);
|
||||||
|
|
||||||
|
|
||||||
var rotation = new ol.dom.Input(document.getElementById('rotation'));
|
var rotation = new ol.dom.Input(document.getElementById('rotation'));
|
||||||
rotation.bindTo('valueAsNumber', map.getView(), 'rotation');
|
rotation.bindTo('value', map.getView(), 'rotation')
|
||||||
|
.transform(parseFloat, String);
|
||||||
|
|
||||||
var resolution = new ol.dom.Input(document.getElementById('resolution'));
|
var resolution = new ol.dom.Input(document.getElementById('resolution'));
|
||||||
resolution.bindTo('valueAsNumber', map.getView(), 'resolution');
|
resolution.bindTo('value', map.getView(), 'resolution')
|
||||||
|
.transform(parseFloat, String);
|
||||||
|
|||||||
@@ -45,7 +45,8 @@ function bindInputs(layerid, layer) {
|
|||||||
$.each(['opacity', 'hue', 'saturation', 'contrast', 'brightness'],
|
$.each(['opacity', 'hue', 'saturation', 'contrast', 'brightness'],
|
||||||
function(i, v) {
|
function(i, v) {
|
||||||
new ol.dom.Input($(layerid + ' .' + v)[0])
|
new ol.dom.Input($(layerid + ' .' + v)[0])
|
||||||
.bindTo('valueAsNumber', layer, v);
|
.bindTo('value', layer, v)
|
||||||
|
.transform(parseFloat, String);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,9 +35,16 @@ var map = new ol.Map({
|
|||||||
});
|
});
|
||||||
|
|
||||||
var projectionSelect = new ol.dom.Input(document.getElementById('projection'));
|
var projectionSelect = new ol.dom.Input(document.getElementById('projection'));
|
||||||
projectionSelect.on('change:value', function() {
|
projectionSelect.bindTo('value', mousePositionControl, 'projection')
|
||||||
mousePositionControl.setProjection(ol.proj.get(projectionSelect.getValue()));
|
.transform(
|
||||||
});
|
function(code) {
|
||||||
|
// projectionSelect.value -> mousePositionControl.projection
|
||||||
|
return ol.proj.get(/** @type {string} */ (code));
|
||||||
|
},
|
||||||
|
function(projection) {
|
||||||
|
// mousePositionControl.projection -> projectionSelect.value
|
||||||
|
return projection.getCode();
|
||||||
|
});
|
||||||
|
|
||||||
var precisionInput = document.getElementById('precision');
|
var precisionInput = document.getElementById('precision');
|
||||||
precisionInput.addEventListener('change', function() {
|
precisionInput.addEventListener('change', function() {
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ goog.require('ol.Object');
|
|||||||
*/
|
*/
|
||||||
ol.dom.InputProperty = {
|
ol.dom.InputProperty = {
|
||||||
VALUE: 'value',
|
VALUE: 'value',
|
||||||
VALUE_AS_NUMBER: 'valueAsNumber',
|
|
||||||
CHECKED: 'checked'
|
CHECKED: 'checked'
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -50,9 +49,6 @@ ol.dom.Input = function(target) {
|
|||||||
goog.events.listen(this,
|
goog.events.listen(this,
|
||||||
ol.Object.getChangeEventType(ol.dom.InputProperty.VALUE),
|
ol.Object.getChangeEventType(ol.dom.InputProperty.VALUE),
|
||||||
this.handleValueChanged_, false, this);
|
this.handleValueChanged_, false, this);
|
||||||
goog.events.listen(this,
|
|
||||||
ol.Object.getChangeEventType(ol.dom.InputProperty.VALUE_AS_NUMBER),
|
|
||||||
this.handleValueAsNumberChanged_, false, this);
|
|
||||||
goog.events.listen(this,
|
goog.events.listen(this,
|
||||||
ol.Object.getChangeEventType(ol.dom.InputProperty.CHECKED),
|
ol.Object.getChangeEventType(ol.dom.InputProperty.CHECKED),
|
||||||
this.handleCheckedChanged_, false, this);
|
this.handleCheckedChanged_, false, this);
|
||||||
@@ -88,20 +84,6 @@ goog.exportProperty(
|
|||||||
ol.dom.Input.prototype.getValue);
|
ol.dom.Input.prototype.getValue);
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the value of the input as a number.
|
|
||||||
* @return {number|null|undefined} input value as number.
|
|
||||||
* @todo stability experimental
|
|
||||||
*/
|
|
||||||
ol.dom.Input.prototype.getValueAsNumber = function() {
|
|
||||||
return /** @type {number} */ (this.get(ol.dom.InputProperty.VALUE_AS_NUMBER));
|
|
||||||
};
|
|
||||||
goog.exportProperty(
|
|
||||||
ol.dom.Input.prototype,
|
|
||||||
'getValueAsNumber',
|
|
||||||
ol.dom.Input.prototype.getValueAsNumber);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the value of the input.
|
* Sets the value of the input.
|
||||||
* @param {string} value Value.
|
* @param {string} value Value.
|
||||||
@@ -116,20 +98,6 @@ goog.exportProperty(
|
|||||||
ol.dom.Input.prototype.setValue);
|
ol.dom.Input.prototype.setValue);
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the number value of the input.
|
|
||||||
* @param {number} value Number value.
|
|
||||||
* @todo stability experimental
|
|
||||||
*/
|
|
||||||
ol.dom.Input.prototype.setValueAsNumber = function(value) {
|
|
||||||
this.set(ol.dom.InputProperty.VALUE_AS_NUMBER, value);
|
|
||||||
};
|
|
||||||
goog.exportProperty(
|
|
||||||
ol.dom.Input.prototype,
|
|
||||||
'setValueAsNumber',
|
|
||||||
ol.dom.Input.prototype.setValueAsNumber);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set whether or not a checkbox is checked.
|
* Set whether or not a checkbox is checked.
|
||||||
* @param {boolean} checked Checked.
|
* @param {boolean} checked Checked.
|
||||||
@@ -152,10 +120,6 @@ ol.dom.Input.prototype.handleInputChanged_ = function() {
|
|||||||
this.setChecked(this.target_.checked);
|
this.setChecked(this.target_.checked);
|
||||||
} else {
|
} else {
|
||||||
this.setValue(this.target_.value);
|
this.setValue(this.target_.value);
|
||||||
var number = this.target_.valueAsNumber;
|
|
||||||
if (goog.isDef(number) && !isNaN(number)) {
|
|
||||||
this.setValueAsNumber(number);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -174,12 +138,3 @@ ol.dom.Input.prototype.handleCheckedChanged_ = function() {
|
|||||||
ol.dom.Input.prototype.handleValueChanged_ = function() {
|
ol.dom.Input.prototype.handleValueChanged_ = function() {
|
||||||
this.target_.value = this.getValue();
|
this.target_.value = this.getValue();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
ol.dom.Input.prototype.handleValueAsNumberChanged_ = function() {
|
|
||||||
// firefox raises an exception if this.target_.valueAsNumber is set instead
|
|
||||||
this.target_.value = this.getValueAsNumber();
|
|
||||||
};
|
|
||||||
|
|||||||
+76
-5
@@ -11,6 +11,7 @@ goog.provide('ol.ObjectEventType');
|
|||||||
goog.require('goog.array');
|
goog.require('goog.array');
|
||||||
goog.require('goog.events');
|
goog.require('goog.events');
|
||||||
goog.require('goog.events.EventTarget');
|
goog.require('goog.events.EventTarget');
|
||||||
|
goog.require('goog.functions');
|
||||||
goog.require('goog.object');
|
goog.require('goog.object');
|
||||||
|
|
||||||
|
|
||||||
@@ -22,6 +23,51 @@ ol.ObjectEventType = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
* @param {ol.Object} target
|
||||||
|
* @param {string} key
|
||||||
|
* @todo stability experimental
|
||||||
|
*/
|
||||||
|
ol.ObjectAccessor = function(target, key) {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {ol.Object}
|
||||||
|
*/
|
||||||
|
this.target = target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
this.key = key;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {function(?): ?}
|
||||||
|
*/
|
||||||
|
this.from = goog.functions.identity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {function(?): ?}
|
||||||
|
*/
|
||||||
|
this.to = goog.functions.identity;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {function(?): ?} from A function that transforms the source value
|
||||||
|
* before it is set to the target.
|
||||||
|
* @param {function(?): ?} to A function that transforms the target value
|
||||||
|
* before it is set to the source.
|
||||||
|
*/
|
||||||
|
ol.ObjectAccessor.prototype.transform = function(from, to) {
|
||||||
|
this.from = from;
|
||||||
|
this.to = to;
|
||||||
|
|
||||||
|
this.target.notify(this.key);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @enum {string}
|
* @enum {string}
|
||||||
*/
|
*/
|
||||||
@@ -87,7 +133,7 @@ ol.Object.capitalize = function(str) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {ol.Object} obj Object.
|
* @param {ol.Object} obj Object.
|
||||||
* @return {Object.<string, {target: ol.Object, key: string}>} Accessors.
|
* @return {Object.<string, ol.ObjectAccessor>} Accessors.
|
||||||
*/
|
*/
|
||||||
ol.Object.getAccessors = function(obj) {
|
ol.Object.getAccessors = function(obj) {
|
||||||
return obj[ol.ObjectProperty.ACCESSORS] ||
|
return obj[ol.ObjectProperty.ACCESSORS] ||
|
||||||
@@ -139,14 +185,35 @@ ol.Object.getSetterName = function(key) {
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Binds a View to a Model.
|
* The bindTo method allows you to set up a two-way binding between a
|
||||||
|
* `source` and `target` object. The method returns an
|
||||||
|
* ol.ObjectAccessor with a transform method that lets you transform
|
||||||
|
* values on the way from the source to the target and on the way back.
|
||||||
|
*
|
||||||
|
* For example, if you had two map views (sourceView and targetView)
|
||||||
|
* and you wanted the target view to have double the resolution of the
|
||||||
|
* source view, you could transform the resolution on the way to and
|
||||||
|
* from the target with the following:
|
||||||
|
*
|
||||||
|
* sourceView.bindTo('resolution', targetView)
|
||||||
|
* .transform(
|
||||||
|
* function(sourceResolution) {
|
||||||
|
* // from sourceView.resolution to targetView.resolution
|
||||||
|
* return 2 * sourceResolution;
|
||||||
|
* },
|
||||||
|
* function(targetResolution) {
|
||||||
|
* // from targetView.resolution to sourceView.resolution
|
||||||
|
* return targetResolution / 2;
|
||||||
|
* }
|
||||||
|
* );
|
||||||
|
*
|
||||||
* @param {string} key Key.
|
* @param {string} key Key.
|
||||||
* @param {ol.Object} target Target.
|
* @param {ol.Object} target Target.
|
||||||
* @param {string=} opt_targetKey Target key.
|
* @param {string=} opt_targetKey Target key.
|
||||||
|
* @return {ol.ObjectAccessor}
|
||||||
* @todo stability experimental
|
* @todo stability experimental
|
||||||
*/
|
*/
|
||||||
ol.Object.prototype.bindTo =
|
ol.Object.prototype.bindTo = function(key, target, opt_targetKey) {
|
||||||
function(key, target, opt_targetKey) {
|
|
||||||
var targetKey = opt_targetKey || key;
|
var targetKey = opt_targetKey || key;
|
||||||
this.unbind(key);
|
this.unbind(key);
|
||||||
var eventType = ol.Object.getChangeEventType(targetKey);
|
var eventType = ol.Object.getChangeEventType(targetKey);
|
||||||
@@ -154,9 +221,11 @@ ol.Object.prototype.bindTo =
|
|||||||
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);
|
||||||
|
var accessor = new ol.ObjectAccessor(target, targetKey);
|
||||||
var accessors = ol.Object.getAccessors(this);
|
var accessors = ol.Object.getAccessors(this);
|
||||||
accessors[key] = {target: target, key: targetKey};
|
accessors[key] = accessor;
|
||||||
this.notifyInternal_(key);
|
this.notifyInternal_(key);
|
||||||
|
return accessor;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -179,6 +248,7 @@ ol.Object.prototype.get = function(key) {
|
|||||||
} else {
|
} else {
|
||||||
value = target.get(targetKey);
|
value = target.get(targetKey);
|
||||||
}
|
}
|
||||||
|
value = accessor.to(value);
|
||||||
} else if (this.values_.hasOwnProperty(key)) {
|
} else if (this.values_.hasOwnProperty(key)) {
|
||||||
value = this.values_[key];
|
value = this.values_[key];
|
||||||
}
|
}
|
||||||
@@ -289,6 +359,7 @@ ol.Object.prototype.set = function(key, value) {
|
|||||||
var target = accessor.target;
|
var target = accessor.target;
|
||||||
var targetKey = accessor.key;
|
var targetKey = accessor.key;
|
||||||
var setterName = ol.Object.getSetterName(targetKey);
|
var setterName = ol.Object.getSetterName(targetKey);
|
||||||
|
value = accessor.from(value);
|
||||||
if (target[setterName]) {
|
if (target[setterName]) {
|
||||||
target[setterName](value);
|
target[setterName](value);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -473,6 +473,95 @@ describe('ol.Object', function() {
|
|||||||
expect(o.getKeys()).to.eql(['K']);
|
expect(o.getKeys()).to.eql(['K']);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('transforms', function() {
|
||||||
|
|
||||||
|
describe('with multiple binds to a single property', function() {
|
||||||
|
|
||||||
|
var original, plusOne, asString;
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
original = new ol.Object();
|
||||||
|
original.set('x', 1);
|
||||||
|
plusOne = new ol.Object();
|
||||||
|
plusOne.bindTo('x', original).transform(
|
||||||
|
function(x) { return x - 1; },
|
||||||
|
function(x) { return x + 1; }
|
||||||
|
);
|
||||||
|
asString = new ol.Object();
|
||||||
|
asString.bindTo('x', original).transform(
|
||||||
|
function(x) { return +x; },
|
||||||
|
function(x) { return x + ''; }
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns the expected value', function() {
|
||||||
|
expect(original.get('x')).to.be(1);
|
||||||
|
expect(plusOne.get('x')).to.be(2);
|
||||||
|
expect(asString.get('x')).to.be('1');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('allows the original value to be set correctly', function() {
|
||||||
|
original.set('x', 2);
|
||||||
|
expect(plusOne.get('x')).to.be(3);
|
||||||
|
expect(asString.get('x')).to.be('2');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('allows the transformed values to be set correctly', function() {
|
||||||
|
plusOne.set('x', 3);
|
||||||
|
expect(original.get('x')).to.be(2);
|
||||||
|
expect(asString.get('x')).to.be('2');
|
||||||
|
asString.set('x', '3');
|
||||||
|
expect(original.get('x')).to.be(3);
|
||||||
|
expect(plusOne.get('x')).to.be(4);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('with transitive binds', function() {
|
||||||
|
|
||||||
|
var original, plusOne, plusOneAsString;
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
original = new ol.Object();
|
||||||
|
original.set('x', 1);
|
||||||
|
plusOne = new ol.Object();
|
||||||
|
plusOne.bindTo('x', original).transform(
|
||||||
|
function(x) { return x - 1; },
|
||||||
|
function(x) { return x + 1; }
|
||||||
|
);
|
||||||
|
plusOneAsString = new ol.Object();
|
||||||
|
plusOneAsString.bindTo('x', plusOne).transform(
|
||||||
|
parseFloat,
|
||||||
|
function(x) { return x + ''; }
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns the expected value', function() {
|
||||||
|
expect(original.get('x')).to.be(1);
|
||||||
|
expect(plusOne.get('x')).to.be(2);
|
||||||
|
expect(plusOneAsString.get('x')).to.be('2');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('allows the original value to be set correctly', function() {
|
||||||
|
original.set('x', 2);
|
||||||
|
expect(plusOne.get('x')).to.be(3);
|
||||||
|
expect(plusOneAsString.get('x')).to.be('3');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('allows the transformed values to be set correctly', function() {
|
||||||
|
plusOne.set('x', 3);
|
||||||
|
expect(original.get('x')).to.be(2);
|
||||||
|
expect(plusOneAsString.get('x')).to.be('3');
|
||||||
|
plusOneAsString.set('x', '4');
|
||||||
|
expect(original.get('x')).to.be(3);
|
||||||
|
expect(plusOne.get('x')).to.be(4);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user