allow dragging for mouse/ms/native when pointer is outside map viewport element

This commit is contained in:
tsauerwein
2014-02-07 15:31:49 +01:00
parent ee2174785f
commit c4c1eb7d45
6 changed files with 190 additions and 5 deletions

View File

@@ -224,6 +224,12 @@ ol.MapBrowserEventHandler.prototype.handlePointerUp_ = function(browserEvent) {
this.dispatchEvent(newEvent);
if (this.activePointers_ <= 0) {
this.pointerEventHandler_.unlistenOnDocument(
ol.MapBrowserEvent.EventType.POINTERMOVE,
this.handlePointerMove_, false, this);
this.pointerEventHandler_.unlistenOnDocument(
ol.MapBrowserEvent.EventType.POINTERUP,
this.handlePointerUp_, false, this);
goog.array.forEach(this.dragListenerKeys_, goog.events.unlistenByKey);
this.dragListenerKeys_ = null;
}
@@ -254,13 +260,16 @@ ol.MapBrowserEventHandler.prototype.handlePointerDown_ =
this.dragged_ = false;
if (goog.isNull(this.dragListenerKeys_)) {
this.pointerEventHandler_.listenOnDocument(
ol.MapBrowserEvent.EventType.POINTERMOVE,
this.handlePointerMove_, false, this);
this.pointerEventHandler_.listenOnDocument(
ol.MapBrowserEvent.EventType.POINTERUP,
this.handlePointerUp_, false, this);
this.dragListenerKeys_ = [
goog.events.listen(this.pointerEventHandler_,
ol.MapBrowserEvent.EventType.POINTERMOVE,
this.handlePointerMove_, false, this),
goog.events.listen(this.pointerEventHandler_,
[ol.MapBrowserEvent.EventType.POINTERUP,
ol.MapBrowserEvent.EventType.POINTERCANCEL],
[ol.MapBrowserEvent.EventType.POINTERCANCEL],
this.handlePointerUp_, false, this)
];
}
@@ -341,6 +350,7 @@ ol.MapBrowserEvent.EventType = {
POINTERDOWN: 'pointerdown',
POINTERUP: 'pointerup',
POINTEROVER: 'pointerover',
POINTEROUT: 'pointerout',
POINTERENTER: 'pointerenter',
POINTERLEAVE: 'pointerleave',
POINTERCANCEL: 'pointercancel'

View File

@@ -38,3 +38,21 @@ ol.pointer.EventSource.prototype.getMapping = goog.abstractMethod;
ol.pointer.EventSource.prototype.getHandlerForEvent = function(eventType) {
return this.getMapping()[eventType];
};
/**
* Setup source listeners for the given pointer event type on the `document`
* element. See also `PointerEventHandler.listenOnDocument()`.
* @param {string} type Pointer event type.
*/
ol.pointer.EventSource.prototype.listenOnDocument = function(type) {
};
/**
* Remove source listeners for the given pointer event type from the `document`
* element. See also `PointerEventHandler.unlistenOnDocument()`.
* @param {string} type Pointer event type.
*/
ol.pointer.EventSource.prototype.unlistenOnDocument = function(type) {
};

View File

@@ -82,6 +82,30 @@ ol.pointer.MouseSource.prototype.getMapping = function() {
};
/** @inheritDoc */
ol.pointer.MouseSource.prototype.listenOnDocument = function(type) {
if (type === 'pointermove') {
this.dispatcher.removeEvent('mousemove');
this.dispatcher.addEvent('mousemove', goog.global.document);
} else if (type === 'pointerup') {
this.dispatcher.removeEvent('mouseup');
this.dispatcher.addEvent('mouseup', goog.global.document);
}
};
/** @inheritDoc */
ol.pointer.MouseSource.prototype.unlistenOnDocument = function(type) {
if (type === 'pointermove') {
this.dispatcher.removeEvent('mousemove', goog.global.document);
this.dispatcher.addEvent('mousemove');
} else if (type === 'pointerup') {
this.dispatcher.removeEvent('mouseup', goog.global.document);
this.dispatcher.addEvent('mouseup');
}
};
/**
* Collide with the global mouse listener
*

View File

@@ -90,6 +90,30 @@ ol.pointer.MsSource.prototype.getMapping = function() {
};
/** @inheritDoc */
ol.pointer.MsSource.prototype.listenOnDocument = function(type) {
if (type === 'pointermove') {
this.dispatcher.removeEvent('MSPointerMove');
this.dispatcher.addEvent('MSPointerMove', goog.global.document);
} else if (type === 'pointerup') {
this.dispatcher.removeEvent('MSPointerUp');
this.dispatcher.addEvent('MSPointerUp', goog.global.document);
}
};
/** @inheritDoc */
ol.pointer.MsSource.prototype.unlistenOnDocument = function(type) {
if (type === 'pointermove') {
this.dispatcher.removeEvent('MSPointerMove', goog.global.document);
this.dispatcher.addEvent('MSPointerMove');
} else if (type === 'pointerup') {
this.dispatcher.removeEvent('MSPointerUp', goog.global.document);
this.dispatcher.addEvent('MSPointerUp');
}
};
/**
* @suppress {missingProperties}
* @return {boolean}

View File

@@ -80,6 +80,30 @@ ol.pointer.NativeSource.prototype.getMapping = function() {
};
/** @inheritDoc */
ol.pointer.NativeSource.prototype.listenOnDocument = function(type) {
if (type === 'pointermove') {
this.dispatcher.removeEvent('pointermove');
this.dispatcher.addEvent('pointermove', goog.global.document);
} else if (type === 'pointerup') {
this.dispatcher.removeEvent('pointerup');
this.dispatcher.addEvent('pointerup', goog.global.document);
}
};
/** @inheritDoc */
ol.pointer.NativeSource.prototype.unlistenOnDocument = function(type) {
if (type === 'pointermove') {
this.dispatcher.removeEvent('pointermove', goog.global.document);
this.dispatcher.addEvent('pointermove');
} else if (type === 'pointerup') {
this.dispatcher.removeEvent('pointerup', goog.global.document);
this.dispatcher.addEvent('pointerup');
}
};
/**
* Handler for `pointerdown`.
*

View File

@@ -231,6 +231,65 @@ ol.pointer.PointerEventHandler.prototype.eventHandler_ = function(inEvent) {
};
/**
* Set up an event listener for the given pointer event type
* by adding source event listeners to the `document` element. The
* original listener on the map viewport is removed.
* This is required for mouse and pointer devices when dragging,
* because no `*move` events are fired, when the mouse/pointer is
* outside the map viewport.
* To remove these listeners again, use `unlistenOnDocument()`.
*
* @param {string} type Pointer event type.
* @param {!Function} listener Callback method, or an object
* with a handleEvent function.
* @param {boolean=} opt_useCapture Whether to fire in capture phase
* (defaults to false).
* @param {Object=} opt_listenerScope Object in whose scope to call the
* listener.
* @return {goog.events.ListenableKey} Unique key for the listener.
*/
ol.pointer.PointerEventHandler.prototype.listenOnDocument = function(
type, listener, opt_useCapture, opt_listenerScope) {
var l = this.eventSourceList.length;
var eventSource;
for (var i = 0; i < l; i++) {
eventSource = this.eventSourceList[i];
eventSource.listenOnDocument(type);
}
return this.listen(
type, listener, opt_useCapture, opt_listenerScope);
};
/**
* Removes the source event listeners on the `document` element,
* and listenes to the orginal map viewport element again.
*
* @param {string} type Pointer event type.
* @param {!Function} listener Callback method, or an object
* with a handleEvent function.
* @param {boolean=} opt_useCapture Whether to fire in capture phase
* (defaults to false).
* @param {Object=} opt_listenerScope Object in whose scope to call the
* listener.
* @return {boolean} Whether any listener was removed.
*/
ol.pointer.PointerEventHandler.prototype.unlistenOnDocument = function(
type, listener, opt_useCapture, opt_listenerScope) {
var l = this.eventSourceList.length;
var eventSource;
for (var i = 0; i < l; i++) {
eventSource = this.eventSourceList[i];
eventSource.listenOnDocument(type);
}
return this.unlisten(
type, listener, opt_useCapture, opt_listenerScope);
};
/**
* Setup listeners for the given events.
* @private
@@ -244,6 +303,19 @@ ol.pointer.PointerEventHandler.prototype.addEvents_ = function(events) {
};
/**
* Setup listener for the given event.
* @param {string} eventName Event type.
* @param {HTMLDocument|Element=} opt_element Optional element.
*/
ol.pointer.PointerEventHandler.prototype.addEvent = function(
eventName, opt_element) {
var element = goog.isDef(opt_element) ? opt_element : this.element_;
goog.events.listen(element, eventName,
this.boundHandler_);
};
/**
* Unregister listeners for the given events.
* @private
@@ -257,6 +329,19 @@ ol.pointer.PointerEventHandler.prototype.removeEvents_ = function(events) {
};
/**
* Unregister listener for the given event.
* @param {string} eventName Event type.
* @param {HTMLDocument|Element=} opt_element Optional element.
*/
ol.pointer.PointerEventHandler.prototype.removeEvent = function(
eventName, opt_element) {
var element = goog.isDef(opt_element) ? opt_element : this.element_;
goog.events.unlisten(element, eventName,
this.boundHandler_);
};
/**
* Returns a snapshot of inEvent, with writable properties.
*