DSDSWeb/static/js/Cesium-1.53/Specs/Core/ScreenSpaceEventHandlerSpec.js

1291 lines
43 KiB
JavaScript

defineSuite([
'Core/ScreenSpaceEventHandler',
'Core/Cartesian2',
'Core/clone',
'Core/combine',
'Core/defined',
'Core/FeatureDetection',
'Core/KeyboardEventModifier',
'Core/ScreenSpaceEventType',
'Specs/DomEventSimulator'
], function(
ScreenSpaceEventHandler,
Cartesian2,
clone,
combine,
defined,
FeatureDetection,
KeyboardEventModifier,
ScreenSpaceEventType,
DomEventSimulator) {
'use strict';
var usePointerEvents;
var element;
var handler;
function createCloningSpy(name) {
var spy = jasmine.createSpy(name);
var cloningSpy = function() {
// deep clone arguments so they are captured correctly by the spy
var args = [].slice.apply(arguments).map(function(arg) {
return clone(arg, true);
});
spy.apply(this, args);
};
function createPropertyDescriptor(prop) {
return {
get : function() {
return spy[prop];
},
set : function(value) {
spy[prop] = value;
}
};
}
for ( var prop in spy) {
if (spy.hasOwnProperty(prop)) {
Object.defineProperty(cloningSpy, prop, createPropertyDescriptor(prop));
}
}
return cloningSpy;
}
var eventsToStop = 'pointerdown pointerup pointermove pointercancel mousedown mouseup mousemove touchstart touchend touchmove touchcancel dblclick wheel mousewheel DOMMouseScroll'.split(' ');
function stop(event) {
event.stopPropagation();
event.preventDefault();
}
beforeAll(function(){
usePointerEvents = FeatureDetection.supportsPointerEvents();
});
beforeEach(function() {
// ignore events that bubble up to the document.
// this prevents triggering the browser's "middle click to scroll" behavior
eventsToStop.forEach(function(e) {
document.addEventListener(e, stop, false);
});
element = document.createElement('div');
element.style.position = 'absolute';
element.style.top = '0';
element.style.left = '0';
document.body.appendChild(element);
element.disableRootEvents = true;
if (usePointerEvents) {
spyOn(element, 'setPointerCapture');
}
handler = new ScreenSpaceEventHandler(element);
});
afterEach(function() {
document.body.removeChild(element);
handler = !handler.isDestroyed() && handler.destroy();
eventsToStop.forEach(function(e) {
document.removeEventListener(e, stop, false);
});
});
describe('setInputAction', function() {
it('throws if action is undefined', function() {
expect(function() {
handler.setInputAction();
}).toThrowDeveloperError();
});
it('throws if type is undefined', function() {
expect(function() {
handler.setInputAction(function() {
});
}).toThrowDeveloperError();
});
});
describe('getInputAction', function() {
it('throws if type is undefined', function() {
expect(function() {
handler.getInputAction();
}).toThrowDeveloperError();
});
});
describe('removeInputAction', function() {
it('throws if type is undefined', function() {
expect(function() {
handler.removeInputAction();
}).toThrowDeveloperError();
});
});
var MouseButton = {
LEFT : 0,
MIDDLE : 1,
RIGHT : 2
};
function keyForValue(obj, val) {
for ( var key in obj) {
if (obj[key] === val) {
return key;
}
}
}
function createMouseSpec(specFunction, eventType, button, modifier) {
var specName = keyForValue(ScreenSpaceEventType, eventType) + ' action';
if (defined(modifier)) {
specName += ' with ' + keyForValue(KeyboardEventModifier, modifier) + ' modifier';
}
it(specName, function() {
var eventOptions = {
button : button,
ctrlKey : modifier === KeyboardEventModifier.CTRL,
altKey : modifier === KeyboardEventModifier.ALT,
shiftKey : modifier === KeyboardEventModifier.SHIFT
};
specFunction(eventType, modifier, eventOptions);
});
}
function createAllMouseSpecCombinations(specFunction, possibleButtons, possibleModifiers, possibleEventTypes) {
for (var i = 0; i < possibleButtons.length; ++i) {
var eventType = possibleEventTypes[i];
var button = possibleButtons[i];
for (var j = 0; j < possibleModifiers.length; ++j) {
var modifier = possibleModifiers[j];
createMouseSpec(specFunction, eventType, button, modifier);
}
}
}
function simulateMouseDown(element, options) {
if (usePointerEvents) {
DomEventSimulator.firePointerDown(element, combine(options, {
pointerType : 'mouse'
}));
} else {
DomEventSimulator.fireMouseDown(element, options);
}
}
function simulateMouseUp(element, options) {
if (usePointerEvents) {
DomEventSimulator.firePointerUp(element, combine(options, {
pointerType : 'mouse'
}));
} else {
DomEventSimulator.fireMouseUp(element, options);
}
}
function simulateMouseMove(element, options) {
if (usePointerEvents) {
DomEventSimulator.firePointerMove(element, combine(options, {
pointerType : 'mouse'
}));
} else {
DomEventSimulator.fireMouseMove(element, options);
}
}
describe('handles mouse down', function() {
function testMouseDownEvent(eventType, modifier, eventOptions) {
var action = createCloningSpy('action');
handler.setInputAction(action, eventType, modifier);
expect(handler.getInputAction(eventType, modifier)).toEqual(action);
function simulateInput() {
simulateMouseDown(element, combine({
clientX : 1,
clientY : 2
}, eventOptions));
}
simulateInput();
expect(action.calls.count()).toEqual(1);
expect(action).toHaveBeenCalledWith({
position : new Cartesian2(1, 2)
});
// should not be fired after removal
action.calls.reset();
handler.removeInputAction(eventType, modifier);
simulateInput();
expect(action).not.toHaveBeenCalled();
}
var possibleButtons = [MouseButton.LEFT, MouseButton.MIDDLE, MouseButton.RIGHT];
var possibleModifiers = [undefined, KeyboardEventModifier.SHIFT, KeyboardEventModifier.CTRL, KeyboardEventModifier.ALT];
var possibleEventTypes = [ScreenSpaceEventType.LEFT_DOWN, ScreenSpaceEventType.MIDDLE_DOWN, ScreenSpaceEventType.RIGHT_DOWN];
createAllMouseSpecCombinations(testMouseDownEvent, possibleButtons, possibleModifiers, possibleEventTypes);
});
describe('handles mouse up', function() {
function testMouseUpEvent(eventType, modifier, eventOptions) {
var action = createCloningSpy('action');
handler.setInputAction(action, eventType, modifier);
expect(handler.getInputAction(eventType, modifier)).toEqual(action);
// down, then up
function simulateInput() {
simulateMouseDown(element, combine({
clientX : 1,
clientY : 2
}, eventOptions));
simulateMouseUp(element, combine({
clientX : 1,
clientY : 2
}, eventOptions));
}
simulateInput();
expect(action.calls.count()).toEqual(1);
expect(action).toHaveBeenCalledWith({
position : new Cartesian2(1, 2)
});
action.calls.reset();
// down, move, then up
function simulateInput2() {
simulateMouseDown(element, combine({
clientX : 1,
clientY : 2
}, eventOptions));
simulateMouseMove(element, combine({
clientX : 10,
clientY : 11
}, eventOptions));
simulateMouseUp(element, combine({
clientX : 10,
clientY : 11
}, eventOptions));
}
simulateInput2();
expect(action.calls.count()).toEqual(1);
expect(action).toHaveBeenCalledWith({
position : new Cartesian2(10, 11)
});
// should not be fired after removal
action.calls.reset();
handler.removeInputAction(eventType, modifier);
simulateInput();
simulateInput2();
expect(action).not.toHaveBeenCalled();
}
var possibleButtons = [MouseButton.LEFT, MouseButton.MIDDLE, MouseButton.RIGHT];
var possibleModifiers = [undefined, KeyboardEventModifier.SHIFT, KeyboardEventModifier.CTRL, KeyboardEventModifier.ALT];
var possibleEventTypes = [ScreenSpaceEventType.LEFT_UP, ScreenSpaceEventType.MIDDLE_UP, ScreenSpaceEventType.RIGHT_UP];
createAllMouseSpecCombinations(testMouseUpEvent, possibleButtons, possibleModifiers, possibleEventTypes);
});
describe('handles mouse click', function() {
function testMouseClickEvent(eventType, modifier, eventOptions) {
var action = createCloningSpy('action');
handler.setInputAction(action, eventType, modifier);
expect(handler.getInputAction(eventType, modifier)).toEqual(action);
// down, then up
function simulateInput() {
simulateMouseDown(element, combine({
clientX : 1,
clientY : 2
}, eventOptions));
simulateMouseUp(element, combine({
clientX : 1,
clientY : 2
}, eventOptions));
}
simulateInput();
expect(action.calls.count()).toEqual(1);
expect(action).toHaveBeenCalledWith({
position : new Cartesian2(1, 2)
});
// mouse clicks are not fired if the mouse moves too far away from the down position
action.calls.reset();
simulateMouseDown(element, combine({
clientX : 1,
clientY : 2
}, eventOptions));
simulateMouseUp(element, combine({
clientX : 10,
clientY : 11
}, eventOptions));
expect(action).not.toHaveBeenCalled();
// should not be fired after removal
action.calls.reset();
handler.removeInputAction(eventType, modifier);
simulateInput();
expect(action).not.toHaveBeenCalled();
}
var possibleButtons = [MouseButton.LEFT, MouseButton.MIDDLE, MouseButton.RIGHT];
var possibleModifiers = [undefined, KeyboardEventModifier.SHIFT, KeyboardEventModifier.CTRL, KeyboardEventModifier.ALT];
var possibleEventTypes = [ScreenSpaceEventType.LEFT_CLICK, ScreenSpaceEventType.MIDDLE_CLICK, ScreenSpaceEventType.RIGHT_CLICK];
createAllMouseSpecCombinations(testMouseClickEvent, possibleButtons, possibleModifiers, possibleEventTypes);
});
describe('handles mouse double click', function() {
function testMouseDoubleClickEvent(eventType, modifier, eventOptions) {
var action = createCloningSpy('action');
handler.setInputAction(action, eventType, modifier);
expect(handler.getInputAction(eventType, modifier)).toEqual(action);
function simulateInput() {
DomEventSimulator.fireDoubleClick(element, combine({
clientX : 1,
clientY : 2
}, eventOptions));
}
simulateInput();
expect(action.calls.count()).toEqual(1);
expect(action).toHaveBeenCalledWith({
position : new Cartesian2(1, 2)
});
// should not be fired after removal
action.calls.reset();
handler.removeInputAction(eventType, modifier);
simulateInput();
expect(action).not.toHaveBeenCalled();
}
var possibleButtons = [MouseButton.LEFT];
var possibleModifiers = [undefined, KeyboardEventModifier.SHIFT, KeyboardEventModifier.CTRL, KeyboardEventModifier.ALT];
var possibleEventTypes = [ScreenSpaceEventType.LEFT_DOUBLE_CLICK];
createAllMouseSpecCombinations(testMouseDoubleClickEvent, possibleButtons, possibleModifiers, possibleEventTypes);
});
describe('handles mouse move', function() {
function testMouseMoveEvent(eventType, modifier, eventOptions) {
var action = createCloningSpy('action');
handler.setInputAction(action, eventType, modifier);
expect(handler.getInputAction(eventType, modifier)).toEqual(action);
function simulateInput() {
simulateMouseMove(element, combine({
clientX : 1,
clientY : 2
}, eventOptions));
simulateMouseMove(element, combine({
clientX : 2,
clientY : 3
}, eventOptions));
}
simulateInput();
expect(action.calls.count()).toEqual(2);
expect(action).toHaveBeenCalledWith({
startPosition : new Cartesian2(1, 2),
endPosition : new Cartesian2(2, 3)
});
// should not be fired after removal
action.calls.reset();
handler.removeInputAction(eventType, modifier);
simulateInput();
expect(action).not.toHaveBeenCalled();
}
var possibleButtons = [undefined];
var possibleModifiers = [undefined, KeyboardEventModifier.SHIFT, KeyboardEventModifier.CTRL, KeyboardEventModifier.ALT];
var possibleEventTypes = [ScreenSpaceEventType.MOUSE_MOVE];
createAllMouseSpecCombinations(testMouseMoveEvent, possibleButtons, possibleModifiers, possibleEventTypes);
});
describe('handles mouse wheel', function() {
if ('onwheel' in document) {
describe('using standard wheel event', function() {
function testWheelEvent(eventType, modifier, eventOptions) {
var action = createCloningSpy('action');
handler.setInputAction(action, eventType, modifier);
expect(handler.getInputAction(eventType, modifier)).toEqual(action);
function simulateInput() {
DomEventSimulator.fireWheel(element, combine({
deltaY : 120
}, eventOptions));
}
simulateInput();
expect(action.calls.count()).toEqual(1);
// NOTE: currently the action is passed the value of 'wheelDelta' which is inverted from the standard 'deltaY'
expect(action).toHaveBeenCalledWith(-120);
// should not be fired after removal
action.calls.reset();
handler.removeInputAction(eventType, modifier);
simulateInput();
expect(action).not.toHaveBeenCalled();
}
var possibleButtons = [undefined];
var possibleModifiers = [undefined, KeyboardEventModifier.SHIFT, KeyboardEventModifier.CTRL, KeyboardEventModifier.ALT];
var possibleEventTypes = [ScreenSpaceEventType.WHEEL];
createAllMouseSpecCombinations(testWheelEvent, possibleButtons, possibleModifiers, possibleEventTypes);
});
} else if (document.onmousewheel !== undefined) {
describe('using legacy mousewheel event', function() {
function testMouseWheelEvent(eventType, modifier, eventOptions) {
var action = createCloningSpy('action');
handler.setInputAction(action, eventType, modifier);
expect(handler.getInputAction(eventType, modifier)).toEqual(action);
function simulateInput() {
DomEventSimulator.fireMouseWheel(element, combine({
wheelDelta : -120
}, eventOptions));
}
simulateInput();
expect(action.calls.count()).toEqual(1);
expect(action).toHaveBeenCalledWith(-120);
// should not be fired after removal
action.calls.reset();
handler.removeInputAction(eventType, modifier);
simulateInput();
expect(action).not.toHaveBeenCalled();
}
var possibleButtons = [undefined];
var possibleModifiers = [undefined, KeyboardEventModifier.SHIFT, KeyboardEventModifier.CTRL, KeyboardEventModifier.ALT];
var possibleEventTypes = [ScreenSpaceEventType.WHEEL];
createAllMouseSpecCombinations(testMouseWheelEvent, possibleButtons, possibleModifiers, possibleEventTypes);
});
}
});
it('handles touch start', function() {
var eventType = ScreenSpaceEventType.LEFT_DOWN;
var action = createCloningSpy('action');
handler.setInputAction(action, eventType);
expect(handler.getInputAction(eventType)).toEqual(action);
function simulateInput() {
var touchStartPosition = {
clientX : 1,
clientY : 2
};
if (usePointerEvents) {
DomEventSimulator.firePointerDown(element, combine({
pointerType : 'touch',
pointerId : 1
}, touchStartPosition));
} else {
DomEventSimulator.fireTouchStart(element, {
changedTouches : [combine({
identifier : 0
}, touchStartPosition)]
});
}
}
simulateInput();
expect(action.calls.count()).toEqual(1);
expect(action).toHaveBeenCalledWith({
position : new Cartesian2(1, 2)
});
// should not be fired after removal
action.calls.reset();
handler.removeInputAction(eventType);
simulateInput();
expect(action).not.toHaveBeenCalled();
});
it('handles touch move', function() {
var eventType = ScreenSpaceEventType.MOUSE_MOVE;
var action = createCloningSpy('action');
handler.setInputAction(action, eventType);
expect(handler.getInputAction(eventType)).toEqual(action);
// start, then move
function simulateInput() {
var touchStartPosition = {
clientX : 1,
clientY : 2
};
var touchMovePosition = {
clientX : 10,
clientY : 11
};
if (usePointerEvents) {
DomEventSimulator.firePointerDown(element, combine({
pointerType : 'touch',
pointerId : 1
}, touchStartPosition));
DomEventSimulator.firePointerMove(element, combine({
pointerType : 'touch',
pointerId : 1
}, touchMovePosition));
} else {
DomEventSimulator.fireTouchStart(element, {
changedTouches : [combine({
identifier : 0
}, touchStartPosition)]
});
DomEventSimulator.fireTouchMove(element, {
changedTouches : [combine({
identifier : 0
}, touchMovePosition)]
});
}
}
simulateInput();
expect(action.calls.count()).toEqual(1);
expect(action).toHaveBeenCalledWith({
startPosition : new Cartesian2(1, 2),
endPosition : new Cartesian2(10, 11)
});
// should not be fired after removal
action.calls.reset();
handler.removeInputAction(eventType);
simulateInput();
expect(action).not.toHaveBeenCalled();
});
it('handles touch end', function() {
var eventType = ScreenSpaceEventType.LEFT_UP;
var action = createCloningSpy('action');
handler.setInputAction(action, eventType);
expect(handler.getInputAction(eventType)).toEqual(action);
// start, then end
function simulateInput() {
var touchStartPosition = {
clientX : 1,
clientY : 2
};
var touchEndPosition = {
clientX : 1,
clientY : 2
};
if (usePointerEvents) {
DomEventSimulator.firePointerDown(element, combine({
pointerType : 'touch',
pointerId : 1
}, touchStartPosition));
DomEventSimulator.firePointerUp(element, combine({
pointerType : 'touch',
pointerId : 1
}, touchEndPosition));
} else {
DomEventSimulator.fireTouchStart(element, {
changedTouches : [combine({
identifier : 0
}, touchStartPosition)]
});
DomEventSimulator.fireTouchEnd(element, {
changedTouches : [combine({
identifier : 0
}, touchEndPosition)]
});
}
}
simulateInput();
expect(action.calls.count()).toEqual(1);
expect(action).toHaveBeenCalledWith({
position : new Cartesian2(1, 2)
});
action.calls.reset();
// start, move, then end
function simulateInput2() {
var touchStartPosition = {
clientX : 1,
clientY : 2
};
var touchMovePosition = {
clientX : 10,
clientY : 11
};
var touchEndPosition = {
clientX : 10,
clientY : 11
};
if (usePointerEvents) {
DomEventSimulator.firePointerDown(element, combine({
pointerType : 'touch',
pointerId : 1
}, touchStartPosition));
DomEventSimulator.firePointerMove(element, combine({
pointerType : 'touch',
pointerId : 1
}, touchMovePosition));
DomEventSimulator.firePointerUp(element, combine({
pointerType : 'touch',
pointerId : 1
}, touchEndPosition));
} else {
DomEventSimulator.fireTouchStart(element, {
changedTouches : [combine({
identifier : 0
}, touchStartPosition)]
});
DomEventSimulator.fireTouchMove(element, {
changedTouches : [combine({
identifier : 0
}, touchMovePosition)]
});
DomEventSimulator.fireTouchEnd(element, {
changedTouches : [combine({
identifier : 0
}, touchEndPosition)]
});
}
}
simulateInput2();
expect(action.calls.count()).toEqual(1);
expect(action).toHaveBeenCalledWith({
position : new Cartesian2(10, 11)
});
// should not be fired after removal
action.calls.reset();
handler.removeInputAction(eventType);
simulateInput();
simulateInput2();
expect(action).not.toHaveBeenCalled();
});
it('treats touch end as touch cancel', function() {
var eventType = ScreenSpaceEventType.LEFT_UP;
var action = createCloningSpy('action');
handler.setInputAction(action, eventType);
expect(handler.getInputAction(eventType)).toEqual(action);
// start, then end
function simulateInput() {
var touchStartPosition = {
clientX : 1,
clientY : 2
};
var touchEndPosition = {
clientX : 1,
clientY : 2
};
if (usePointerEvents) {
DomEventSimulator.firePointerDown(element, combine({
pointerType : 'touch',
pointerId : 1
}, touchStartPosition));
DomEventSimulator.firePointerCancel(element, combine({
pointerType : 'touch',
pointerId : 1
}, touchEndPosition));
} else {
DomEventSimulator.fireTouchStart(element, {
changedTouches : [combine({
identifier : 0
}, touchStartPosition)]
});
DomEventSimulator.fireTouchCancel(element, {
changedTouches : [combine({
identifier : 0
}, touchEndPosition)]
});
}
}
simulateInput();
expect(action.calls.count()).toEqual(1);
expect(action).toHaveBeenCalledWith({
position : new Cartesian2(1, 2)
});
action.calls.reset();
// start, move, then end
function simulateInput2() {
var touchStartPosition = {
clientX : 1,
clientY : 2
};
var touchMovePosition = {
clientX : 10,
clientY : 11
};
var touchEndPosition = {
clientX : 10,
clientY : 11
};
if (usePointerEvents) {
DomEventSimulator.firePointerDown(element, combine({
pointerType : 'touch',
pointerId : 1
}, touchStartPosition));
DomEventSimulator.firePointerMove(element, combine({
pointerType : 'touch',
pointerId : 1
}, touchMovePosition));
DomEventSimulator.firePointerCancel(element, combine({
pointerType : 'touch',
pointerId : 1
}, touchEndPosition));
} else {
DomEventSimulator.fireTouchStart(element, {
changedTouches : [combine({
identifier : 0
}, touchStartPosition)]
});
DomEventSimulator.fireTouchMove(element, {
changedTouches : [combine({
identifier : 0
}, touchMovePosition)]
});
DomEventSimulator.fireTouchCancel(element, {
changedTouches : [combine({
identifier : 0
}, touchEndPosition)]
});
}
}
simulateInput2();
expect(action.calls.count()).toEqual(1);
expect(action).toHaveBeenCalledWith({
position : new Cartesian2(10, 11)
});
// should not be fired after removal
action.calls.reset();
handler.removeInputAction(eventType);
simulateInput();
simulateInput2();
expect(action).not.toHaveBeenCalled();
});
it('handles touch pinch start', function() {
var eventType = ScreenSpaceEventType.PINCH_START;
var action = createCloningSpy('action');
handler.setInputAction(action, eventType);
expect(handler.getInputAction(eventType)).toEqual(action);
// touch 1, then touch 2
function simulateInput() {
var touch1StartPosition = {
clientX : 1,
clientY : 2
};
var touch2StartPosition = {
clientX : 3,
clientY : 4
};
if (usePointerEvents) {
DomEventSimulator.firePointerDown(element, combine({
pointerType : 'touch',
pointerId : 1
}, touch1StartPosition));
DomEventSimulator.firePointerDown(element, combine({
pointerType : 'touch',
pointerId : 2
}, touch2StartPosition));
} else {
DomEventSimulator.fireTouchStart(element, {
changedTouches : [combine({
identifier : 0
}, touch1StartPosition)]
});
DomEventSimulator.fireTouchStart(element, {
changedTouches : [combine({
identifier : 0
}, touch1StartPosition), combine({
identifier : 1
}, touch2StartPosition)]
});
}
}
simulateInput();
expect(action.calls.count()).toEqual(1);
expect(action).toHaveBeenCalledWith({
position1 : new Cartesian2(1, 2),
position2 : new Cartesian2(3, 4)
});
// should not be fired after removal
action.calls.reset();
handler.removeInputAction(eventType);
simulateInput();
expect(action).not.toHaveBeenCalled();
});
it('handles touch pinch move', function() {
var eventType = ScreenSpaceEventType.PINCH_MOVE;
var action = createCloningSpy('action');
handler.setInputAction(action, eventType);
expect(handler.getInputAction(eventType)).toEqual(action);
// touch 1, then touch 2, then move
function simulateInput() {
var touch1StartPosition = {
clientX : 1,
clientY : 2
};
var touch2StartPosition = {
clientX : 4,
clientY : 3
};
var touch1MovePosition = {
clientX : 10,
clientY : 11
};
var touch2MovePosition = {
clientX : 21,
clientY : 20
};
if (usePointerEvents) {
DomEventSimulator.firePointerDown(element, combine({
pointerType : 'touch',
pointerId : 1
}, touch1StartPosition));
DomEventSimulator.firePointerDown(element, combine({
pointerType : 'touch',
pointerId : 2
}, touch2StartPosition));
DomEventSimulator.firePointerMove(element, combine({
pointerType : 'touch',
pointerId : 1
}, touch1MovePosition));
DomEventSimulator.firePointerMove(element, combine({
pointerType : 'touch',
pointerId : 2
}, touch2MovePosition));
} else {
DomEventSimulator.fireTouchStart(element, {
changedTouches : [combine({
identifier : 0
}, touch1StartPosition)]
});
DomEventSimulator.fireTouchStart(element, {
changedTouches : [combine({
identifier : 0
}, touch1StartPosition), combine({
identifier : 1
}, touch2StartPosition)]
});
DomEventSimulator.fireTouchMove(element, {
changedTouches : [combine({
identifier : 0
}, touch1MovePosition), combine({
identifier : 1
}, touch2MovePosition)]
});
}
}
simulateInput();
// original delta X: 3
// original delta Y: 1
// final delta X: 11
// final delta Y: 9
if (usePointerEvents) {
// because every pointer event is separate, one touch moves, then the other.
expect(action.calls.count()).toEqual(2);
// intermediate delta X: -6
// intermediate delta Y: -8
expect(action).toHaveBeenCalledWith({
distance : {
startPosition : new Cartesian2(0, Math.sqrt(3 * 3 + 1 * 1) * 0.25),
endPosition : new Cartesian2(0, Math.sqrt(-6 * -6 + -8 * -8) * 0.25)
},
angleAndHeight : {
startPosition : new Cartesian2(Math.atan2(1, 3), (3 + 2) * 0.125),
endPosition : new Cartesian2(Math.atan2(-8, -6), (3 + 11) * 0.125)
}
});
expect(action).toHaveBeenCalledWith({
distance : {
startPosition : new Cartesian2(0, Math.sqrt(-6 * -6 + -8 * -8) * 0.25),
endPosition : new Cartesian2(0, Math.sqrt(11 * 11 + 9 * 9) * 0.25)
},
angleAndHeight : {
startPosition : new Cartesian2(Math.atan2(-8, -6), (3 + 11) * 0.125),
endPosition : new Cartesian2(Math.atan2(9, 11), (11 + 20) * 0.125)
}
});
} else {
// touch events can move both touches simultaneously
expect(action.calls.count()).toEqual(1);
expect(action).toHaveBeenCalledWith({
distance : {
startPosition : new Cartesian2(0, Math.sqrt(3 * 3 + 1 * 1) * 0.25),
endPosition : new Cartesian2(0, Math.sqrt(11 * 11 + 9 * 9) * 0.25)
},
angleAndHeight : {
startPosition : new Cartesian2(Math.atan2(1, 3), (3 + 2) * 0.125),
endPosition : new Cartesian2(Math.atan2(9, 11), (11 + 20) * 0.125)
}
});
}
// should not be fired after removal
action.calls.reset();
handler.removeInputAction(eventType);
simulateInput();
expect(action).not.toHaveBeenCalled();
});
it('handles touch pinch release', function() {
var leftDownEventType = ScreenSpaceEventType.LEFT_DOWN;
var leftDownAction = createCloningSpy('LEFT_DOWN');
handler.setInputAction(leftDownAction, leftDownEventType);
var pinchStartEventType = ScreenSpaceEventType.PINCH_START;
var pinchStartAction = createCloningSpy('PINCH_START');
handler.setInputAction(pinchStartAction, pinchStartEventType);
var pinchEndEventType = ScreenSpaceEventType.PINCH_END;
var pinchEndAction = createCloningSpy('PINCH_END');
handler.setInputAction(pinchEndAction, pinchEndEventType);
var touch1Position = {
clientX : 1,
clientY : 2
};
var touch2Position = {
clientX : 4,
clientY : 3
};
if (usePointerEvents) {
DomEventSimulator.firePointerDown(element, combine(
{
pointerType : 'touch',
pointerId : 1
},
touch1Position
));
DomEventSimulator.firePointerDown(element, combine(
{
pointerType : 'touch',
pointerId : 2
},
touch2Position
));
// Releasing one of two fingers should not trigger
// PINCH_END or LEFT_DOWN:
leftDownAction.calls.reset();
DomEventSimulator.firePointerUp(element, combine(
{
pointerType : 'touch',
pointerId : 1
},
touch1Position
));
expect(pinchEndAction).not.toHaveBeenCalled();
expect(leftDownAction).not.toHaveBeenCalled();
pinchEndAction.calls.reset();
// Putting another finger down should not trigger
// PINCH_START:
pinchStartAction.calls.reset();
DomEventSimulator.firePointerDown(element, combine(
{
pointerType : 'touch',
pointerId : 1
},
touch2Position
));
expect(pinchStartAction).not.toHaveBeenCalled();
// Releasing both fingers should trigger PINCH_END:
DomEventSimulator.firePointerUp(element, combine(
{
pointerType : 'touch',
pointerId : 1
},
touch2Position
));
DomEventSimulator.firePointerUp(element, combine({
pointerType : 'touch',
pointerId : 2
}, touch2Position));
expect(pinchEndAction).toHaveBeenCalled();
} else {
DomEventSimulator.fireTouchStart(element, {
changedTouches : [
combine({ identifier : 0 }, touch1Position),
combine({ identifier : 1 }, touch2Position)
]
});
leftDownAction.calls.reset();
// Releasing one of two fingers should not trigger
// PINCH_END or LEFT_DOWN:
DomEventSimulator.fireTouchEnd(element, {
changedTouches : [
combine({ identifier : 0 }, touch1Position)
]
});
expect(pinchEndAction).not.toHaveBeenCalled();
expect(leftDownAction).not.toHaveBeenCalled();
// Releasing both fingers should trigger PINCH_END:
pinchEndAction.calls.reset();
DomEventSimulator.fireTouchEnd(element, {
changedTouches : [
combine({ identifier : 1 }, touch2Position)
]
});
expect(pinchEndAction).toHaveBeenCalled();
}
});
it('handles touch click', function() {
var eventType = ScreenSpaceEventType.LEFT_CLICK;
var action = createCloningSpy('action');
handler.setInputAction(action, eventType);
expect(handler.getInputAction(eventType)).toEqual(action);
// start, then end
function simulateInput() {
var touchStartPosition = {
clientX : 1,
clientY : 2
};
var touchEndPosition = {
clientX : 1,
clientY : 2
};
if (usePointerEvents) {
DomEventSimulator.firePointerDown(element, combine({
pointerType : 'touch',
pointerId : 1
}, touchStartPosition));
DomEventSimulator.firePointerUp(element, combine({
pointerType : 'touch',
pointerId : 1
}, touchEndPosition));
} else {
DomEventSimulator.fireTouchStart(element, {
changedTouches : [combine({
identifier : 0
}, touchStartPosition)]
});
DomEventSimulator.fireTouchEnd(element, {
changedTouches : [combine({
identifier : 0
}, touchEndPosition)]
});
}
}
simulateInput();
expect(action.calls.count()).toEqual(1);
expect(action).toHaveBeenCalledWith({
position : new Cartesian2(1, 2)
});
// should not be fired after removal
action.calls.reset();
handler.removeInputAction(eventType);
simulateInput();
expect(action).not.toHaveBeenCalled();
});
it('treats touch cancel as touch end for touch clicks', function() {
var eventType = ScreenSpaceEventType.LEFT_CLICK;
var action = createCloningSpy('action');
handler.setInputAction(action, eventType);
expect(handler.getInputAction(eventType)).toEqual(action);
// start, then end
function simulateInput() {
var touchStartPosition = {
clientX : 1,
clientY : 2
};
var touchEndPosition = {
clientX : 1,
clientY : 2
};
if (usePointerEvents) {
DomEventSimulator.firePointerDown(element, combine({
pointerType : 'touch',
pointerId : 1
}, touchStartPosition));
DomEventSimulator.firePointerCancel(element, combine({
pointerType : 'touch',
pointerId : 1
}, touchEndPosition));
} else {
DomEventSimulator.fireTouchStart(element, {
changedTouches : [combine({
identifier : 0
}, touchStartPosition)]
});
DomEventSimulator.fireTouchCancel(element, {
changedTouches : [combine({
identifier : 0
}, touchEndPosition)]
});
}
}
simulateInput();
expect(action.calls.count()).toEqual(1);
expect(action).toHaveBeenCalledWith({
position : new Cartesian2(1, 2)
});
// should not be fired after removal
action.calls.reset();
handler.removeInputAction(eventType);
simulateInput();
expect(action).not.toHaveBeenCalled();
});
it('sets isDestroyed when destroyed', function() {
expect(handler.isDestroyed()).toEqual(false);
handler.destroy();
expect(handler.isDestroyed()).toEqual(true);
});
it('unregisters event listeners when destroyed', function() {
handler = handler.destroy();
spyOn(element, 'addEventListener').and.callThrough();
spyOn(element, 'removeEventListener').and.callThrough();
handler = new ScreenSpaceEventHandler(element);
expect(element.addEventListener.calls.count()).not.toEqual(0);
expect(element.removeEventListener.calls.count()).toEqual(0);
handler.destroy();
expect(element.removeEventListener.calls.count()).toEqual(element.addEventListener.calls.count());
});
});