More convenience with condition chaining
This commit is contained in:
@@ -13,6 +13,29 @@ import {assert} from '../asserts.js';
|
|||||||
* @typedef {function(this: ?, import("../MapBrowserEvent.js").default): boolean} Condition
|
* @typedef {function(this: ?, import("../MapBrowserEvent.js").default): boolean} Condition
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a condition function that is only fulfilled when a chain of conditions pass.
|
||||||
|
* @param {...Condition} var_args Conditions to check.
|
||||||
|
* @return {Condition} Condition function that checks a chain of conditions.
|
||||||
|
*/
|
||||||
|
export function chain(var_args) {
|
||||||
|
const conditions = arguments;
|
||||||
|
/**
|
||||||
|
* @param {import("../MapBrowserEvent.js").default} event Event.
|
||||||
|
* @return {boolean} All conditions passed.
|
||||||
|
*/
|
||||||
|
return function (event) {
|
||||||
|
let pass = true;
|
||||||
|
for (let i = 0, ii = conditions.length; i < ii; ++i) {
|
||||||
|
pass = pass && conditions[i](event);
|
||||||
|
if (!pass) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return pass;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return `true` if only the alt-key is pressed, `false` otherwise (e.g. when
|
* Return `true` if only the alt-key is pressed, `false` otherwise (e.g. when
|
||||||
* additionally the shift-key is pressed).
|
* additionally the shift-key is pressed).
|
||||||
|
|||||||
@@ -3,9 +3,7 @@
|
|||||||
*/
|
*/
|
||||||
import Collection from './Collection.js';
|
import Collection from './Collection.js';
|
||||||
import DoubleClickZoom from './interaction/DoubleClickZoom.js';
|
import DoubleClickZoom from './interaction/DoubleClickZoom.js';
|
||||||
import DragPan, {
|
import DragPan from './interaction/DragPan.js';
|
||||||
defaultCondition as dragPanDefaultCondition,
|
|
||||||
} from './interaction/DragPan.js';
|
|
||||||
import DragRotate from './interaction/DragRotate.js';
|
import DragRotate from './interaction/DragRotate.js';
|
||||||
import DragZoom from './interaction/DragZoom.js';
|
import DragZoom from './interaction/DragZoom.js';
|
||||||
import KeyboardPan from './interaction/KeyboardPan.js';
|
import KeyboardPan from './interaction/KeyboardPan.js';
|
||||||
@@ -14,7 +12,6 @@ import Kinetic from './Kinetic.js';
|
|||||||
import MouseWheelZoom from './interaction/MouseWheelZoom.js';
|
import MouseWheelZoom from './interaction/MouseWheelZoom.js';
|
||||||
import PinchRotate from './interaction/PinchRotate.js';
|
import PinchRotate from './interaction/PinchRotate.js';
|
||||||
import PinchZoom from './interaction/PinchZoom.js';
|
import PinchZoom from './interaction/PinchZoom.js';
|
||||||
import {focusWithTabindex} from './events/condition.js';
|
|
||||||
|
|
||||||
export {default as DoubleClickZoom} from './interaction/DoubleClickZoom.js';
|
export {default as DoubleClickZoom} from './interaction/DoubleClickZoom.js';
|
||||||
export {default as DragAndDrop} from './interaction/DragAndDrop.js';
|
export {default as DragAndDrop} from './interaction/DragAndDrop.js';
|
||||||
@@ -114,11 +111,7 @@ export function defaults(opt_options) {
|
|||||||
if (dragPan) {
|
if (dragPan) {
|
||||||
interactions.push(
|
interactions.push(
|
||||||
new DragPan({
|
new DragPan({
|
||||||
condition: options.onFocusOnly
|
onFocusOnly: options.onFocusOnly,
|
||||||
? function (event) {
|
|
||||||
return focusWithTabindex(event) && dragPanDefaultCondition(event);
|
|
||||||
}
|
|
||||||
: undefined,
|
|
||||||
kinetic: kinetic,
|
kinetic: kinetic,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
@@ -155,7 +148,7 @@ export function defaults(opt_options) {
|
|||||||
if (mouseWheelZoom) {
|
if (mouseWheelZoom) {
|
||||||
interactions.push(
|
interactions.push(
|
||||||
new MouseWheelZoom({
|
new MouseWheelZoom({
|
||||||
condition: options.onFocusOnly ? focusWithTabindex : undefined,
|
onFocusOnly: options.onFocusOnly,
|
||||||
duration: options.zoomDuration,
|
duration: options.zoomDuration,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -5,8 +5,13 @@ import PointerInteraction, {
|
|||||||
centroid as centroidFromPointers,
|
centroid as centroidFromPointers,
|
||||||
} from './Pointer.js';
|
} from './Pointer.js';
|
||||||
import {FALSE} from '../functions.js';
|
import {FALSE} from '../functions.js';
|
||||||
|
import {
|
||||||
|
chain,
|
||||||
|
focusWithTabindex,
|
||||||
|
noModifierKeys,
|
||||||
|
primaryAction,
|
||||||
|
} from '../events/condition.js';
|
||||||
import {easeOut} from '../easing.js';
|
import {easeOut} from '../easing.js';
|
||||||
import {noModifierKeys, primaryAction} from '../events/condition.js';
|
|
||||||
import {
|
import {
|
||||||
rotate as rotateCoordinate,
|
rotate as rotateCoordinate,
|
||||||
scale as scaleCoordinate,
|
scale as scaleCoordinate,
|
||||||
@@ -17,8 +22,8 @@ import {
|
|||||||
* @property {import("../events/condition.js").Condition} [condition] A function that takes an {@link module:ol/MapBrowserEvent~MapBrowserEvent} and returns a boolean
|
* @property {import("../events/condition.js").Condition} [condition] A function that takes an {@link module:ol/MapBrowserEvent~MapBrowserEvent} and returns a boolean
|
||||||
* to indicate whether that event should be handled.
|
* to indicate whether that event should be handled.
|
||||||
* Default is {@link module:ol/events/condition~noModifierKeys} and {@link module:ol/events/condition~primaryAction}.
|
* Default is {@link module:ol/events/condition~noModifierKeys} and {@link module:ol/events/condition~primaryAction}.
|
||||||
* In addition, if there is a `tabindex` attribute on the map element,
|
* @property {boolean} [onFocusOnly=false] When the map's target has a `tabindex` attribute set,
|
||||||
* {@link module:ol/events/condition~focus} will also be applied.
|
* the interaction will only handle events when the map has the focus.
|
||||||
* @property {import("../Kinetic.js").default} [kinetic] Kinetic inertia to apply to the pan.
|
* @property {import("../Kinetic.js").default} [kinetic] Kinetic inertia to apply to the pan.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -59,11 +64,17 @@ class DragPan extends PointerInteraction {
|
|||||||
*/
|
*/
|
||||||
this.panning_ = false;
|
this.panning_ = false;
|
||||||
|
|
||||||
|
const condition = options.condition
|
||||||
|
? options.condition
|
||||||
|
: chain(noModifierKeys, primaryAction);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
* @type {import("../events/condition.js").Condition}
|
* @type {import("../events/condition.js").Condition}
|
||||||
*/
|
*/
|
||||||
this.condition_ = options.condition ? options.condition : defaultCondition;
|
this.condition_ = options.onFocusOnly
|
||||||
|
? chain(focusWithTabindex, condition)
|
||||||
|
: condition;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
@@ -175,12 +186,4 @@ class DragPan extends PointerInteraction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Browser event.
|
|
||||||
* @return {boolean} Combined condition result.
|
|
||||||
*/
|
|
||||||
export function defaultCondition(mapBrowserEvent) {
|
|
||||||
return noModifierKeys(mapBrowserEvent) && primaryAction(mapBrowserEvent);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default DragPan;
|
export default DragPan;
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
import EventType from '../events/EventType.js';
|
import EventType from '../events/EventType.js';
|
||||||
import Interaction, {zoomByDelta} from './Interaction.js';
|
import Interaction, {zoomByDelta} from './Interaction.js';
|
||||||
import {DEVICE_PIXEL_RATIO, FIREFOX} from '../has.js';
|
import {DEVICE_PIXEL_RATIO, FIREFOX} from '../has.js';
|
||||||
import {always} from '../events/condition.js';
|
import {always, chain, focusWithTabindex} from '../events/condition.js';
|
||||||
import {clamp} from '../math.js';
|
import {clamp} from '../math.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -21,8 +21,8 @@ export const Mode = {
|
|||||||
* takes an {@link module:ol/MapBrowserEvent~MapBrowserEvent} and returns a
|
* takes an {@link module:ol/MapBrowserEvent~MapBrowserEvent} and returns a
|
||||||
* boolean to indicate whether that event should be handled. Default is
|
* boolean to indicate whether that event should be handled. Default is
|
||||||
* {@link module:ol/events/condition~always}.
|
* {@link module:ol/events/condition~always}.
|
||||||
* In addition, if there is a `tabindex` attribute on the map element,
|
* @property {boolean} [onFocusOnly=false] When the map's target has a `tabindex` attribute set,
|
||||||
* {@link module:ol/events/condition~focus} will also be applied.
|
* the interaction will only handle events when the map has the focus.
|
||||||
* @property {number} [maxDelta=1] Maximum mouse wheel delta.
|
* @property {number} [maxDelta=1] Maximum mouse wheel delta.
|
||||||
* @property {number} [duration=250] Animation duration in milliseconds.
|
* @property {number} [duration=250] Animation duration in milliseconds.
|
||||||
* @property {number} [timeout=80] Mouse wheel timeout duration in milliseconds.
|
* @property {number} [timeout=80] Mouse wheel timeout duration in milliseconds.
|
||||||
@@ -96,11 +96,15 @@ class MouseWheelZoom extends Interaction {
|
|||||||
? options.constrainResolution
|
? options.constrainResolution
|
||||||
: false;
|
: false;
|
||||||
|
|
||||||
|
const condition = options.condition ? options.condition : always;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
* @type {import("../events/condition.js").Condition}
|
* @type {import("../events/condition.js").Condition}
|
||||||
*/
|
*/
|
||||||
this.condition_ = options.condition ? options.condition : always;
|
this.condition_ = options.onFocusOnly
|
||||||
|
? chain(focusWithTabindex, condition)
|
||||||
|
: condition;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
import DoubleClickZoom from '../../../src/ol/interaction/DoubleClickZoom.js';
|
import DoubleClickZoom from '../../../src/ol/interaction/DoubleClickZoom.js';
|
||||||
import DragPan, {
|
import DragPan from '../../../src/ol/interaction/DragPan.js';
|
||||||
defaultCondition,
|
|
||||||
} from '../../../src/ol/interaction/DragPan.js';
|
|
||||||
import Feature from '../../../src/ol/Feature.js';
|
import Feature from '../../../src/ol/Feature.js';
|
||||||
import GeoJSON from '../../../src/ol/format/GeoJSON.js';
|
import GeoJSON from '../../../src/ol/format/GeoJSON.js';
|
||||||
import ImageLayer from '../../../src/ol/layer/Image.js';
|
import ImageLayer from '../../../src/ol/layer/Image.js';
|
||||||
@@ -29,7 +27,6 @@ import {
|
|||||||
useGeographic,
|
useGeographic,
|
||||||
} from '../../../src/ol/proj.js';
|
} from '../../../src/ol/proj.js';
|
||||||
import {defaults as defaultInteractions} from '../../../src/ol/interaction.js';
|
import {defaults as defaultInteractions} from '../../../src/ol/interaction.js';
|
||||||
import {focusWithTabindex} from '../../../src/ol/events/condition.js';
|
|
||||||
|
|
||||||
describe('ol.Map', function () {
|
describe('ol.Map', function () {
|
||||||
describe('constructor', function () {
|
describe('constructor', function () {
|
||||||
@@ -705,7 +702,7 @@ describe('ol.Map', function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('create interactions', function () {
|
describe('create interactions', function () {
|
||||||
let options;
|
let options, event, hasTabIndex, hasFocus, isPrimary;
|
||||||
|
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
options = {
|
options = {
|
||||||
@@ -718,6 +715,33 @@ describe('ol.Map', function () {
|
|||||||
pinchRotate: false,
|
pinchRotate: false,
|
||||||
pinchZoom: false,
|
pinchZoom: false,
|
||||||
};
|
};
|
||||||
|
hasTabIndex = true;
|
||||||
|
hasFocus = true;
|
||||||
|
isPrimary = true;
|
||||||
|
event = {
|
||||||
|
map: {
|
||||||
|
getTargetElement: function () {
|
||||||
|
return {
|
||||||
|
hasAttribute: function (attribute) {
|
||||||
|
return hasTabIndex;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
},
|
||||||
|
originalEvent: {
|
||||||
|
isPrimary: isPrimary,
|
||||||
|
button: 0,
|
||||||
|
},
|
||||||
|
target: {
|
||||||
|
getTargetElement: function () {
|
||||||
|
return {
|
||||||
|
contains: function () {
|
||||||
|
return hasFocus;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('create mousewheel interaction', function () {
|
describe('create mousewheel interaction', function () {
|
||||||
@@ -731,11 +755,19 @@ describe('ol.Map', function () {
|
|||||||
expect(interactions.item(0).useAnchor_).to.eql(false);
|
expect(interactions.item(0).useAnchor_).to.eql(false);
|
||||||
expect(interactions.item(0).condition_).to.be(TRUE);
|
expect(interactions.item(0).condition_).to.be(TRUE);
|
||||||
});
|
});
|
||||||
it('uses the focus condition when onFocusOnly option is set', function () {
|
it('does not use the default condition when onFocusOnly option is set', function () {
|
||||||
options.onFocusOnly = true;
|
options.onFocusOnly = true;
|
||||||
options.mouseWheelZoom = true;
|
options.mouseWheelZoom = true;
|
||||||
const interactions = defaultInteractions(options);
|
const interactions = defaultInteractions(options);
|
||||||
expect(interactions.item(0).condition_).to.be(focusWithTabindex);
|
expect(interactions.item(0).condition_).to.not.be(TRUE);
|
||||||
|
hasTabIndex = true;
|
||||||
|
hasFocus = true;
|
||||||
|
expect(interactions.item(0).condition_(event)).to.be(true);
|
||||||
|
hasTabIndex = true;
|
||||||
|
hasFocus = false;
|
||||||
|
expect(interactions.item(0).condition_(event)).to.be(false);
|
||||||
|
hasTabIndex = false;
|
||||||
|
expect(interactions.item(0).condition_(event)).to.be(true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -745,13 +777,28 @@ describe('ol.Map', function () {
|
|||||||
const interactions = defaultInteractions(options);
|
const interactions = defaultInteractions(options);
|
||||||
expect(interactions.getLength()).to.eql(1);
|
expect(interactions.getLength()).to.eql(1);
|
||||||
expect(interactions.item(0)).to.be.a(DragPan);
|
expect(interactions.item(0)).to.be.a(DragPan);
|
||||||
expect(interactions.item(0).condition_).to.be(defaultCondition);
|
expect(interactions.item(0).condition_(event)).to.be(true);
|
||||||
|
hasTabIndex = true;
|
||||||
|
hasFocus = false;
|
||||||
|
expect(interactions.item(0).condition_(event)).to.be(true);
|
||||||
|
event.originalEvent.altKey = true;
|
||||||
|
expect(interactions.item(0).condition_(event)).to.be(false);
|
||||||
|
delete event.originalEvent.altKey;
|
||||||
|
event.originalEvent.button = 1;
|
||||||
|
expect(interactions.item(0).condition_(event)).to.be(false);
|
||||||
});
|
});
|
||||||
it('does not use the default condition when onFocusOnly option is set', function () {
|
it('does not use the default condition when onFocusOnly option is set', function () {
|
||||||
options.onFocusOnly = true;
|
options.onFocusOnly = true;
|
||||||
options.dragPan = true;
|
options.dragPan = true;
|
||||||
const interactions = defaultInteractions(options);
|
const interactions = defaultInteractions(options);
|
||||||
expect(interactions.item(0).condition_).to.not.be(defaultCondition);
|
hasTabIndex = true;
|
||||||
|
hasFocus = true;
|
||||||
|
expect(interactions.item(0).condition_(event)).to.be(true);
|
||||||
|
hasTabIndex = true;
|
||||||
|
hasFocus = false;
|
||||||
|
expect(interactions.item(0).condition_(event)).to.be(false);
|
||||||
|
hasTabIndex = false;
|
||||||
|
expect(interactions.item(0).condition_(event)).to.be(true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user