Merge pull request #10 from elemoine/event
make ol.Map inherit from goog.events.EventTarget
This commit is contained in:
@@ -7,6 +7,7 @@ goog.require('ol.loc');
|
||||
goog.require('ol.projection');
|
||||
goog.require('ol.error');
|
||||
|
||||
goog.require('goog.dispose');
|
||||
|
||||
/**
|
||||
* @typedef {ol.Map|{center, zoom, numZoomLevels, projection, userProjection, maxExtent, maxResolution, resolutions, renderTo, layers, controls}|string}
|
||||
@@ -247,3 +248,9 @@ ol.Map.prototype.renderTo = function(arg) {
|
||||
this.setContainer(goog.dom.getElement(arg));
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
*/
|
||||
ol.Map.prototype.destroy = function() {
|
||||
goog.dispose(this);
|
||||
};
|
||||
|
||||
@@ -130,4 +130,3 @@ goog.exportProperty(ol.renderer.Composite, 'isSupported', ol.renderer.Composite.
|
||||
goog.exportProperty(ol.renderer.TileLayerRenderer, 'isSupported', ol.renderer.TileLayerRenderer.isSupported);
|
||||
goog.exportProperty(ol.renderer.TileLayerRenderer, 'canRender', ol.renderer.TileLayerRenderer.canRender);
|
||||
goog.exportProperty(ol.renderer.TileLayerRenderer, 'getType', ol.renderer.TileLayerRenderer.getType);
|
||||
ol.control.addControl('navigation', ol.control.Navigation);
|
||||
|
||||
@@ -3,11 +3,10 @@ goog.provide("ol");
|
||||
goog.require('ol.base');
|
||||
goog.require('ol.bounds');
|
||||
goog.require('ol.control.Attribution');
|
||||
goog.require('ol.control.Navigation');
|
||||
goog.require('ol.control.Zoom');
|
||||
goog.require('ol.event.Drag');
|
||||
goog.require('ol.event.Events');
|
||||
goog.require('ol.event.Scroll');
|
||||
goog.require('ol.handler.Drag');
|
||||
goog.require('ol.handler.MouseWheel');
|
||||
goog.require('ol.handler.Click');
|
||||
goog.require("ol.map");
|
||||
goog.require("ol.loc");
|
||||
goog.require("ol.feature");
|
||||
|
||||
@@ -3,25 +3,44 @@ goog.provide('ol.Map');
|
||||
goog.require('ol.Loc');
|
||||
goog.require('ol.Bounds');
|
||||
goog.require('ol.Projection');
|
||||
goog.require('ol.event');
|
||||
goog.require('ol.event.Events');
|
||||
goog.require('ol.control.Control');
|
||||
goog.require('ol.renderer.MapRenderer');
|
||||
goog.require('ol.handler.Drag');
|
||||
goog.require('ol.handler.MouseWheel');
|
||||
goog.require('ol.handler.Click');
|
||||
|
||||
goog.require('goog.dom');
|
||||
goog.require('goog.math');
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.events.EventTarget');
|
||||
|
||||
/**
|
||||
* @define {boolean} Whether to enable the drag handler.
|
||||
*/
|
||||
ol.ENABLE_DRAG_HANDLER = true;
|
||||
|
||||
/**
|
||||
* @define {boolean} Whether to enable the mousewheel handler.
|
||||
*/
|
||||
ol.ENABLE_MOUSEWHEEL_HANDLER = true;
|
||||
|
||||
/**
|
||||
* @define {boolean} Whether to enable the click handler.
|
||||
*/
|
||||
ol.ENABLE_CLICK_HANDLER = true;
|
||||
|
||||
/**
|
||||
* @export
|
||||
* @constructor
|
||||
* @extends {goog.events.EventTarget}
|
||||
*
|
||||
* @event layeradd Fires when a layer is added to the map. The event object
|
||||
* contains a 'layer' property referencing the added layer.
|
||||
*/
|
||||
ol.Map = function() {
|
||||
|
||||
goog.base(this);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.Projection}
|
||||
@@ -106,21 +125,13 @@ ol.Map = function() {
|
||||
*/
|
||||
this.staticOverlay_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.event.Events}
|
||||
*/
|
||||
this.events_ = new ol.event.Events(
|
||||
this, undefined, false, ['drag', 'scroll']
|
||||
);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Element}
|
||||
*/
|
||||
this.container_ = null;
|
||||
|
||||
};
|
||||
goog.inherits(ol.Map, goog.events.EventTarget);
|
||||
|
||||
/**
|
||||
@const
|
||||
@@ -146,7 +157,7 @@ ol.Map.DEFAULT_TILE_SIZE = 256;
|
||||
@const
|
||||
@type {Array.<string>}
|
||||
*/
|
||||
ol.Map.DEFAULT_CONTROLS = ["attribution", "navigation", "zoom"];
|
||||
ol.Map.DEFAULT_CONTROLS = ["attribution", "zoom"];
|
||||
|
||||
/**
|
||||
* @return {ol.Loc} Map center in map projection.
|
||||
@@ -426,7 +437,7 @@ ol.Map.prototype.addLayers = function(layers) {
|
||||
for (var i=0, ii=layers.length; i<ii; ++i) {
|
||||
layer = layers[i];
|
||||
this.layers_.push(layer);
|
||||
this.events_.triggerEvent('layeradd', {'layer': layer});
|
||||
goog.events.dispatchEvent(this, {type: 'layeradd', 'layer': layer});
|
||||
}
|
||||
this.conditionallyRender();
|
||||
};
|
||||
@@ -502,11 +513,34 @@ ol.Map.prototype.setViewport = function() {
|
||||
'class': 'ol-viewport',
|
||||
'style': 'width:100%;height:100%;top:0;left:0;position:relative;overflow:hidden'
|
||||
}));
|
||||
this.initHandlers();
|
||||
}
|
||||
this.events_.setElement(this.viewport_);
|
||||
goog.dom.appendChild(this.container_, this.viewport_);
|
||||
};
|
||||
|
||||
/**
|
||||
* Init the map event handlers.
|
||||
*/
|
||||
ol.Map.prototype.initHandlers = function() {
|
||||
goog.asserts.assert(!goog.isNull(this.viewport_));
|
||||
|
||||
var handler,
|
||||
states = /** @type {ol.handler.states} */ ({});
|
||||
|
||||
if (ol.ENABLE_DRAG_HANDLER) {
|
||||
handler = new ol.handler.Drag(this, states);
|
||||
this.registerDisposable(handler);
|
||||
}
|
||||
if (ol.ENABLE_MOUSEWHEEL_HANDLER) {
|
||||
handler = new ol.handler.MouseWheel(this, states);
|
||||
this.registerDisposable(handler);
|
||||
}
|
||||
if (ol.ENABLE_CLICK_HANDLER) {
|
||||
handler = new ol.handler.Click(this, states);
|
||||
this.registerDisposable(handler);
|
||||
}
|
||||
};
|
||||
|
||||
ol.Map.prototype.createRenderer = function() {
|
||||
var Renderer = ol.renderer.MapRenderer.pickRendererType(
|
||||
ol.Map.preferredRenderers);
|
||||
@@ -527,13 +561,6 @@ ol.Map.prototype.createRenderer = function() {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @return {ol.event.Events} the events instance for this map
|
||||
*/
|
||||
ol.Map.prototype.getEvents = function() {
|
||||
return this.events_;
|
||||
};
|
||||
|
||||
/**
|
||||
* TODO: This method will need to be reworked/revisited when renderers can
|
||||
* display a map that is rotated or otherwise not aligned with pixel space.
|
||||
@@ -576,9 +603,10 @@ ol.Map.prototype.getStaticOverlay = function() {
|
||||
};
|
||||
|
||||
/**
|
||||
* @export
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.Map.prototype.destroy = function() {
|
||||
ol.Map.prototype.disposeInternal = function() {
|
||||
goog.base(this, 'disposeInternal');
|
||||
//remove layers, etc.
|
||||
for (var key in this) {
|
||||
delete this[key];
|
||||
|
||||
@@ -208,7 +208,8 @@ ol.Popup.prototype.doOpen = function(opt_arg) {
|
||||
goog.dom.appendChild(this.container_, closeButton);
|
||||
goog.dom.classes.add(closeButton, ol.Popup.CLASS_NAME+'-close');
|
||||
}
|
||||
this.map_.getEvents().register('click', this.clickHandler, this);
|
||||
goog.events.listen(this.map_.getViewport(), 'click', this.clickHandler,
|
||||
undefined, this);
|
||||
goog.dom.appendChild(this.map_.getMapOverlay(), this.container_);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
goog.provide('ol.Tile');
|
||||
|
||||
goog.require('ol.Bounds');
|
||||
|
||||
goog.require('goog.events.EventTarget');
|
||||
goog.require('goog.events');
|
||||
goog.require('goog.asserts');
|
||||
goog.require('ol.Bounds');
|
||||
goog.require('ol.event.Events');
|
||||
|
||||
/**
|
||||
* The Tile class.
|
||||
* @constructor
|
||||
* @extends {goog.events.EventTarget}
|
||||
* @param {string} url
|
||||
* @param {ol.Bounds|undefined} opt_bounds
|
||||
*/
|
||||
@@ -46,13 +48,8 @@ ol.Tile = function(url, opt_bounds) {
|
||||
this.handleImageLoad, false, this);
|
||||
goog.events.listenOnce(this.img_, goog.events.EventType.ERROR,
|
||||
this.handleImageError, false, this);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.event.Events}
|
||||
*/
|
||||
this.events_ = new ol.event.Events(this);
|
||||
};
|
||||
goog.inherits(ol.Tile, goog.events.EventTarget);
|
||||
|
||||
/**
|
||||
* @protected
|
||||
@@ -104,7 +101,7 @@ ol.Tile.prototype.handleImageLoad = function(evt) {
|
||||
this.loaded_ = true;
|
||||
this.img_.style.visibility = "inherit";
|
||||
this.img_.style.opacity = 1; // TODO: allow for layer opacity
|
||||
this.events_.triggerEvent('load');
|
||||
goog.events.dispatchEvent(this, 'load');
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -113,7 +110,7 @@ ol.Tile.prototype.handleImageLoad = function(evt) {
|
||||
*/
|
||||
ol.Tile.prototype.handleImageError = function(evt) {
|
||||
this.loading_ = false;
|
||||
this.events_.triggerEvent('error');
|
||||
goog.events.dispatchEvent(this, 'error');
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -136,7 +133,7 @@ ol.Tile.prototype.isLoading = function() {
|
||||
*
|
||||
*/
|
||||
ol.Tile.prototype.destroy = function() {
|
||||
this.events_.triggerEvent('destroy');
|
||||
goog.events.dispatchEvent(this, 'destroy');
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
goog.provide('ol.control.Attribution');
|
||||
|
||||
goog.require('ol.event');
|
||||
goog.require('ol.control.Control');
|
||||
|
||||
goog.require('goog.dom');
|
||||
goog.require('goog.events');
|
||||
goog.require('goog.events.Event');
|
||||
|
||||
|
||||
/**
|
||||
@@ -43,7 +44,8 @@ ol.control.Attribution.prototype.setMap = function(map) {
|
||||
var staticOverlay = map.getStaticOverlay();
|
||||
if (goog.isNull(this.container_)) {
|
||||
this.container_ = goog.dom.createDom('div', this.CLS);
|
||||
goog.events.listen(this.container_, 'click', ol.event.stopPropagation);
|
||||
goog.events.listen(this.container_, 'click',
|
||||
goog.events.Event.stopPropagation);
|
||||
}
|
||||
if (!goog.isNull(staticOverlay)) {
|
||||
goog.dom.append(staticOverlay, this.container_);
|
||||
@@ -55,7 +57,7 @@ ol.control.Attribution.prototype.setMap = function(map) {
|
||||
ol.control.Attribution.prototype.activate = function() {
|
||||
var active = goog.base(this, 'activate');
|
||||
if (active) {
|
||||
this.map_.getEvents().register('layeradd', this.update, this);
|
||||
goog.events.listen(this.map_, 'layeradd', this.update, false, this);
|
||||
this.update();
|
||||
}
|
||||
return active;
|
||||
@@ -65,7 +67,7 @@ ol.control.Attribution.prototype.activate = function() {
|
||||
ol.control.Attribution.prototype.deactivate = function() {
|
||||
var inactive = goog.base(this, 'deactivate');
|
||||
if (inactive) {
|
||||
this.map_.getEvents().unregister('layeradd', this.update, this);
|
||||
goog.events.unlisten(this.map_, 'layeradd', this.update, false, this);
|
||||
}
|
||||
return inactive;
|
||||
};
|
||||
@@ -84,9 +86,10 @@ ol.control.Attribution.prototype.update = function() {
|
||||
};
|
||||
|
||||
ol.control.Attribution.prototype.destroy = function() {
|
||||
goog.events.unlisten(this.container_, 'click', ol.event.stopPropagation);
|
||||
goog.events.unlisten(this.container_, 'click',
|
||||
goog.events.Event.stopPropagation);
|
||||
goog.dom.removeNode(this.container_);
|
||||
goog.base(this, 'destroy');
|
||||
};
|
||||
|
||||
ol.control.addControl('attribution', ol.control.Attribution);
|
||||
ol.control.addControl('attribution', ol.control.Attribution);
|
||||
|
||||
@@ -82,4 +82,4 @@ ol.control.Control.prototype.deactivate = function() {
|
||||
ol.control.Control.prototype.destroy = function() {
|
||||
this.deactivate();
|
||||
goog.object.clear(this);
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
goog.provide('ol.control.Navigation');
|
||||
|
||||
goog.require('ol.control.Control');
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.control.Control}
|
||||
* @param {boolean|undefined} opt_autoActivate
|
||||
*/
|
||||
ol.control.Navigation = function(opt_autoActivate) {
|
||||
|
||||
goog.base(this, opt_autoActivate);
|
||||
|
||||
/**
|
||||
* Activate this control when it is added to a map. Default is true.
|
||||
*
|
||||
* @type {boolean} autoActivate
|
||||
*/
|
||||
this.autoActivate_ =
|
||||
goog.isDef(opt_autoActivate) ? opt_autoActivate : true;
|
||||
|
||||
/**
|
||||
* @type {number?}
|
||||
* @private
|
||||
*/
|
||||
this.zoomBlocked_ = null;
|
||||
|
||||
};
|
||||
goog.inherits(ol.control.Navigation, ol.control.Control);
|
||||
|
||||
/** @inheritDoc */
|
||||
ol.control.Navigation.prototype.activate = function() {
|
||||
var active = goog.base(this, 'activate');
|
||||
if (active) {
|
||||
var events = this.map_.getEvents();
|
||||
events.register("drag", this.moveMap, this);
|
||||
events.register("scroll", this.zoomMap, this);
|
||||
}
|
||||
return active;
|
||||
};
|
||||
|
||||
/** @inheritDoc */
|
||||
ol.control.Navigation.prototype.deactivate = function() {
|
||||
var inactive = goog.base(this, 'deactivate');
|
||||
if (inactive) {
|
||||
var events = this.map_.getEvents();
|
||||
events.unregister("drag", this.moveMap, this);
|
||||
events.unregister("scroll", this.zoomMap, this);
|
||||
}
|
||||
return inactive;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {Object} evt
|
||||
*/
|
||||
ol.control.Navigation.prototype.moveMap = function(evt) {
|
||||
this.map_.moveByViewportPx(evt.deltaX, evt.deltaY);
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {Event} evt
|
||||
*/
|
||||
ol.control.Navigation.prototype.zoomMap = function(evt) {
|
||||
var me = this;
|
||||
if (evt.deltaY === 0 || me.zoomBlocked_) {
|
||||
return;
|
||||
}
|
||||
me.zoomBlocked_ = window.setTimeout(function() {
|
||||
me.zoomBlocked_ = null;
|
||||
}, 200);
|
||||
|
||||
var map = me.map_,
|
||||
step = evt.deltaY / Math.abs(evt.deltaY);
|
||||
map.setZoom(map.getZoom()-step, map.getEvents().getPointerPosition(evt));
|
||||
// We don't want the page to scroll.
|
||||
evt.preventDefault();
|
||||
return false;
|
||||
};
|
||||
|
||||
ol.control.addControl('navigation', ol.control.Navigation);
|
||||
@@ -1,6 +1,5 @@
|
||||
goog.provide('ol.control.Zoom');
|
||||
|
||||
goog.require('ol.event');
|
||||
goog.require('ol.control.Control');
|
||||
|
||||
goog.require('goog.dom');
|
||||
@@ -120,4 +119,4 @@ ol.control.Zoom.RES = {
|
||||
OUT_CLS: 'ol-control-zoom-out',
|
||||
IN_TEXT: '+',
|
||||
OUT_TEXT: '\u2013'
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,95 +0,0 @@
|
||||
goog.provide('ol.event.Drag');
|
||||
|
||||
goog.require('ol.event');
|
||||
goog.require('ol.event.ISequence');
|
||||
|
||||
goog.require('goog.functions');
|
||||
goog.require('goog.fx.Dragger');
|
||||
goog.require('goog.fx.DragEvent');
|
||||
goog.require('goog.fx.Dragger.EventType');
|
||||
|
||||
|
||||
/**
|
||||
* Event sequence that provides a 'dragstart', 'drag' and 'dragend' events.
|
||||
* Event objects of the 'drag' events have 'deltaX' and 'deltaY' values with
|
||||
* the relative pixel movement since the previous 'drag' or 'dragstart' event.
|
||||
*
|
||||
* @constructor
|
||||
* @param {ol.event.Events} target The Events instance that handles events.
|
||||
* @implements {ol.event.ISequence}
|
||||
* @export
|
||||
*/
|
||||
ol.event.Drag = function(target) {
|
||||
var previousX = 0, previousY = 0,
|
||||
element = target.getElement(),
|
||||
dragger = new goog.fx.Dragger(element);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {goog.fx.Dragger}
|
||||
*/
|
||||
this.dragger_ = dragger;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.event.Events}
|
||||
*/
|
||||
this.target_ = target;
|
||||
|
||||
// We want to swallow the click event that gets fired after dragging.
|
||||
var newSequence;
|
||||
function unregisterClickStopper() {
|
||||
target.unregister('click', goog.functions.FALSE, undefined, true);
|
||||
}
|
||||
|
||||
// no default for mousemove and touchmove events to avoid page scrolling.
|
||||
target.register('mousemove', ol.event.preventDefault);
|
||||
target.register('touchmove', ol.event.preventDefault);
|
||||
|
||||
dragger.defaultAction = function(x, y) {};
|
||||
dragger.addEventListener(goog.fx.Dragger.EventType.START, function(evt) {
|
||||
evt.target = element;
|
||||
evt.type = 'dragstart';
|
||||
previousX = evt.clientX;
|
||||
previousY = evt.clientY;
|
||||
newSequence = true;
|
||||
target.triggerEvent(evt.type, evt);
|
||||
});
|
||||
dragger.addEventListener(goog.fx.Dragger.EventType.DRAG, function(evt) {
|
||||
evt.target = element;
|
||||
evt.deltaX = evt.clientX - previousX;
|
||||
evt.deltaY = evt.clientY - previousY;
|
||||
previousX = evt.clientX;
|
||||
previousY = evt.clientY;
|
||||
if (newSequence) {
|
||||
// Once we are in the drag sequence, we know that we need to
|
||||
// get rid of the click event that gets fired when we are done
|
||||
// dragging.
|
||||
target.register('click', goog.functions.FALSE, undefined, true);
|
||||
newSequence = false;
|
||||
}
|
||||
target.triggerEvent(evt.type, evt);
|
||||
});
|
||||
dragger.addEventListener(goog.fx.Dragger.EventType.END, function(evt) {
|
||||
evt.target = element;
|
||||
evt.type = 'dragend';
|
||||
target.triggerEvent(evt.type, evt);
|
||||
// Unregister the click stopper in the next cycle
|
||||
window.setTimeout(unregisterClickStopper, 0);
|
||||
});
|
||||
// Don't swallow the click event if our sequence cancels early.
|
||||
dragger.addEventListener(
|
||||
goog.fx.Dragger.EventType.EARLY_CANCEL, unregisterClickStopper
|
||||
);
|
||||
};
|
||||
|
||||
/** @inheritDoc */
|
||||
ol.event.Drag.prototype.destroy = function() {
|
||||
this.target_.unregister('mousemove', ol.event.preventDefault);
|
||||
this.target_.unregister('touchmove', ol.event.preventDefault);
|
||||
this.dragger_.dispose();
|
||||
goog.object.clear(this);
|
||||
};
|
||||
|
||||
|
||||
ol.event.addSequenceProvider('drag', ol.event.Drag);
|
||||
@@ -1,327 +0,0 @@
|
||||
goog.provide('ol.event');
|
||||
goog.provide('ol.event.Events');
|
||||
|
||||
goog.require('goog.object');
|
||||
goog.require('goog.events');
|
||||
goog.require('goog.events.EventType');
|
||||
goog.require('goog.events.EventTarget');
|
||||
goog.require('goog.events.KeyCodes');
|
||||
goog.require('goog.style');
|
||||
|
||||
/**
|
||||
* @enum {Object}
|
||||
*/
|
||||
ol.event.SEQUENCE_PROVIDER_MAP = {};
|
||||
|
||||
/**
|
||||
* @param {string} name
|
||||
* @param {Function} Sequence
|
||||
*/
|
||||
ol.event.addSequenceProvider = function(name, Sequence) {
|
||||
ol.event.SEQUENCE_PROVIDER_MAP[name] = Sequence;
|
||||
};
|
||||
|
||||
/**
|
||||
* Determine whether event was caused by a single touch
|
||||
*
|
||||
* @param {!Event} evt
|
||||
* @return {boolean}
|
||||
*/
|
||||
ol.event.isSingleTouch = function(evt) {
|
||||
return !!(evt.touches && evt.touches.length == 1);
|
||||
};
|
||||
|
||||
/**
|
||||
* Determine whether event was caused by a multi touch
|
||||
*
|
||||
* @param {!Event} evt
|
||||
* @return {boolean}
|
||||
*/
|
||||
ol.event.isMultiTouch = function(evt) {
|
||||
return !!(evt.touches && evt.touches.length > 1);
|
||||
};
|
||||
|
||||
/**
|
||||
* Call preventDefault on the provided event.
|
||||
*
|
||||
* @param {!Event} evt
|
||||
*/
|
||||
ol.event.preventDefault = function(evt) {
|
||||
evt.preventDefault();
|
||||
};
|
||||
|
||||
/**
|
||||
* Call stopPropagation on the provided event.
|
||||
*
|
||||
* @param {!Event} evt
|
||||
*/
|
||||
ol.event.stopPropagation = function(evt) {
|
||||
evt.stopPropagation();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Construct an ol.event.Events instance.
|
||||
*
|
||||
* @constructor
|
||||
* @extends {goog.events.EventTarget}
|
||||
* @param {Object} object The object we are creating this instance for.
|
||||
* @param {!Element=} opt_element An optional element that we want to
|
||||
* listen to browser events on.
|
||||
* @param {boolean=} opt_includeXY Should the 'xy' property automatically be
|
||||
* created for browser pointer events? In general, this should be false. If
|
||||
* it is true, then pointer events will automatically generate an 'xy'
|
||||
* property on the event object that is passed, which represents the
|
||||
* relative position of the pointer to the {@code element}. Default is
|
||||
* false.
|
||||
* @param {Array.<String>=} opt_sequences Event sequences to register with
|
||||
* this Events instance.
|
||||
*/
|
||||
ol.event.Events = function(object, opt_element, opt_includeXY, opt_sequences) {
|
||||
|
||||
goog.base(this);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Object}
|
||||
* The object that this instance is bound to.
|
||||
*/
|
||||
this.object_ = object;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Element}
|
||||
* The element that this instance listens to mouse events on.
|
||||
*/
|
||||
this.element_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.includeXY_ = goog.isDef(opt_includeXY) ? opt_includeXY : false;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Array.<String>}
|
||||
*/
|
||||
this.sequenceProviders_ = goog.isDef(opt_sequences) ? opt_sequences : [];
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Array.<ol.event.ISequence>}
|
||||
*/
|
||||
this.sequences_ = [];
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Object}
|
||||
*/
|
||||
this.listenerCount_ = {};
|
||||
|
||||
if (goog.isDef(opt_element)) {
|
||||
this.setElement(opt_element);
|
||||
}
|
||||
};
|
||||
goog.inherits(ol.event.Events, goog.events.EventTarget);
|
||||
|
||||
/**
|
||||
* @return {Object} The object that this instance is bound to.
|
||||
*/
|
||||
ol.event.Events.prototype.getObject = function() {
|
||||
return this.object_;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {boolean} includeXY
|
||||
*/
|
||||
ol.event.Events.prototype.setIncludeXY = function(includeXY) {
|
||||
this.includeXY_ = includeXY;
|
||||
};
|
||||
|
||||
/**
|
||||
* @return {Element} The element that this instance currently
|
||||
* listens to browser events on.
|
||||
*/
|
||||
ol.event.Events.prototype.getElement = function() {
|
||||
return this.element_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Attach this instance to a DOM element. When called, all browser events fired
|
||||
* on the provided element will be relayed by this instance.
|
||||
*
|
||||
* @param {Element|Node} element A DOM element to attach
|
||||
* browser events to. If called without this argument, all browser events
|
||||
* will be detached from the element they are currently attached to.
|
||||
*/
|
||||
ol.event.Events.prototype.setElement = function(element) {
|
||||
var types = goog.events.EventType, t;
|
||||
if (this.element_) {
|
||||
for (t in types) {
|
||||
goog.events.unlisten(
|
||||
this.element_, types[t], this.handleBrowserEvent, false, this
|
||||
);
|
||||
}
|
||||
this.destroySequences();
|
||||
delete this.element_;
|
||||
}
|
||||
this.element_ = /** @type {Element} */ (element) || null;
|
||||
if (goog.isDefAndNotNull(element)) {
|
||||
this.createSequences();
|
||||
for (t in types) {
|
||||
goog.events.listen(
|
||||
element, types[t], this.handleBrowserEvent, false, this
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ol.event.Events.prototype.createSequences = function() {
|
||||
for (var i=0, ii=this.sequenceProviders_.length; i<ii; ++i) {
|
||||
this.sequences_.push(
|
||||
new ol.event.SEQUENCE_PROVIDER_MAP[this.sequenceProviders_[i]](
|
||||
this
|
||||
)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
ol.event.Events.prototype.destroySequences = function() {
|
||||
for (var i=this.sequences_.length-1; i>=0; --i) {
|
||||
this.sequences_[i].destroy();
|
||||
}
|
||||
this.sequences_ = [];
|
||||
};
|
||||
|
||||
/**
|
||||
* Register a listener for an event.
|
||||
*
|
||||
* When the event is triggered, the 'listener' function will be called, in the
|
||||
* context of 'scope'. Imagine we were to register an event, specifying an
|
||||
* ol.Bounds instance as 'scope'. When the event is triggered, the context in
|
||||
* the listener function will be our Bounds instance. This means that within
|
||||
* our listener function, we can access the properties and methods of the
|
||||
* Bounds instance through the 'this' keyword. So our listener could execute
|
||||
* something like:
|
||||
*
|
||||
* var leftStr = "Left: " + this.minX();
|
||||
*
|
||||
* @param {string} type Name of the event to register.
|
||||
* @param {Function} listener The callback function.
|
||||
* @param {Object=} opt_scope The object to bind the context to for the
|
||||
* listener. If no scope is specified, default is this intance's 'object'
|
||||
* property.
|
||||
* @param {boolean=} opt_priority Register the listener as priority listener,
|
||||
* so it gets executed before other listeners? Default is false.
|
||||
*/
|
||||
ol.event.Events.prototype.register = function(type, listener, opt_scope,
|
||||
opt_priority) {
|
||||
goog.events.listen(
|
||||
this, type, listener, opt_priority, opt_scope || this.object_
|
||||
);
|
||||
this.listenerCount_[type] = (this.listenerCount_[type] || 0) + 1;
|
||||
};
|
||||
|
||||
/**
|
||||
* Unregister a listener for an event
|
||||
*
|
||||
* @param {string} type Name of the event to unregister
|
||||
* @param {Function} listener The callback function.
|
||||
* @param {Object=} opt_scope The object to bind the context to for the
|
||||
* listener. If no scope is specified, default is the event's default
|
||||
* scope.
|
||||
* @param {boolean=} opt_priority Listener was registered as priority listener,
|
||||
* so it gets executed before other listeners. Default is false.
|
||||
*/
|
||||
ol.event.Events.prototype.unregister = function(type, listener, opt_scope,
|
||||
opt_priority) {
|
||||
var removed = goog.events.unlisten(
|
||||
this, type, listener, opt_priority, opt_scope || this.object_
|
||||
);
|
||||
if (removed) {
|
||||
this.listenerCount_[type] = (this.listenerCount_[type] || 1) - 1;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Trigger a specified registered event.
|
||||
*
|
||||
* @param {string} type The type of the event to trigger.
|
||||
* @param {Object=} opt_evt The event object that will be passed to listeners.
|
||||
* This object will always have a 'type' property with the event type and
|
||||
* an 'object' property referencing this Events instance.
|
||||
*
|
||||
* @return {boolean} The last listener return. If a listener returns false,
|
||||
* the chain of listeners will stop getting called. Returns undefined if
|
||||
* called for an event type that has no listeners.
|
||||
*/
|
||||
ol.event.Events.prototype.triggerEvent = function(type, opt_evt) {
|
||||
var returnValue;
|
||||
if (this.listenerCount_[type] > 0) {
|
||||
var listeners = goog.events.getListeners(this, type, true)
|
||||
.concat(goog.events.getListeners(this, type, false));
|
||||
if (arguments.length === 1) {
|
||||
opt_evt = {'type': type};
|
||||
}
|
||||
opt_evt['object'] = this.object_;
|
||||
for (var i=0, ii=listeners.length; i<ii; ++i) {
|
||||
returnValue = listeners[i].handleEvent(opt_evt);
|
||||
if (returnValue === false) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return returnValue;
|
||||
};
|
||||
|
||||
/**
|
||||
* Prepares browser events before they are dispatched. This takes care to set a
|
||||
* property 'xy' on the event with the current pointer position (if
|
||||
* {@code includeXY} is set to true), and normalizes clientX and clientY for
|
||||
* multi-touch events.
|
||||
*
|
||||
* @param {Event} evt Event object.
|
||||
*/
|
||||
ol.event.Events.prototype.handleBrowserEvent = function(evt) {
|
||||
var type = evt.type;
|
||||
if (this.listenerCount_[type] > 0) {
|
||||
// add clientX & clientY to all events - corresponds to average x, y
|
||||
var touches = evt.touches;
|
||||
if (touches && touches[0]) {
|
||||
var x = 0;
|
||||
var y = 0;
|
||||
var num = touches.length;
|
||||
var touch;
|
||||
for (var i=0; i<num; ++i) {
|
||||
touch = touches[i];
|
||||
x += touch.clientX;
|
||||
y += touch.clientY;
|
||||
}
|
||||
evt.clientX = x / num;
|
||||
evt.clientY = y / num;
|
||||
}
|
||||
if (this.includeXY_) {
|
||||
evt.xy = this.getPointerPosition(evt);
|
||||
}
|
||||
this.triggerEvent(evt.type, evt);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the mouse position relative to this Event instance's target element for
|
||||
* the provided event.
|
||||
*
|
||||
* @param {Event} evt Event object
|
||||
*/
|
||||
ol.event.Events.prototype.getPointerPosition = function(evt) {
|
||||
return goog.style.getRelativePosition(evt, this.element_);
|
||||
};
|
||||
|
||||
/**
|
||||
* Destroy this Events instance.
|
||||
*/
|
||||
ol.event.Events.prototype.destroy = function() {
|
||||
this.setElement(null);
|
||||
goog.object.clear(this);
|
||||
};
|
||||
@@ -1,22 +0,0 @@
|
||||
goog.provide('ol.event.ISequence');
|
||||
|
||||
/**
|
||||
* Interface for event sequences. Event sequences map sequences of native
|
||||
* browser events to high level events that the sequence provides.
|
||||
*
|
||||
* Implementations are expected to call {@code triggerEvent} on the
|
||||
* {@code target} to to fire their high level events.
|
||||
*
|
||||
* Implementations can expect the {@code target}'s {@code getElement} method
|
||||
* to return an {Element} at construction time.
|
||||
*
|
||||
* @interface
|
||||
* @param {ol.event.Events} target The Events instance that receives the
|
||||
* sequence's events.
|
||||
*/
|
||||
ol.event.ISequence = function(target) {};
|
||||
|
||||
/**
|
||||
* Destroys the sequence
|
||||
*/
|
||||
ol.event.ISequence.prototype.destroy = function() {};
|
||||
@@ -1,45 +0,0 @@
|
||||
goog.provide('ol.event.Scroll');
|
||||
|
||||
goog.require('ol.event.ISequence');
|
||||
goog.require('ol.event');
|
||||
|
||||
goog.require('goog.events.MouseWheelHandler');
|
||||
|
||||
|
||||
/**
|
||||
* Event sequence that provides a 'scroll' event. Event objects have 'deltaX'
|
||||
* and 'deltaY' values with the scroll delta since the previous 'scroll' event.
|
||||
*
|
||||
* @constructor
|
||||
* @param {ol.event.Events} target The Events instance that handles events.
|
||||
* @implements {ol.event.ISequence}
|
||||
* @export
|
||||
*/
|
||||
ol.event.Scroll = function(target) {
|
||||
var element = target.getElement(),
|
||||
handler = new goog.events.MouseWheelHandler(element);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {goog.events.MouseWheelHandler}
|
||||
*/
|
||||
this.handler_ = handler;
|
||||
|
||||
handler.addEventListener(
|
||||
goog.events.MouseWheelHandler.EventType.MOUSEWHEEL,
|
||||
function(evt) {
|
||||
evt.type = 'scroll';
|
||||
evt.target = element;
|
||||
target.triggerEvent(evt.type, evt);
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
/** @inheritDoc */
|
||||
ol.event.Scroll.prototype.destroy = function() {
|
||||
this.handler_.dispose();
|
||||
delete this.handler_;
|
||||
};
|
||||
|
||||
|
||||
ol.event.addSequenceProvider('scroll', ol.event.Scroll);
|
||||
53
src/ol/events/MapEvent.js
Normal file
53
src/ol/events/MapEvent.js
Normal file
@@ -0,0 +1,53 @@
|
||||
goog.provide('ol.events.MapEvent');
|
||||
goog.provide('ol.events.MapEventType');
|
||||
|
||||
goog.require('goog.events.Event');
|
||||
|
||||
|
||||
/**
|
||||
* @enum {string}
|
||||
*/
|
||||
ol.events.MapEventType = {
|
||||
// drag handler
|
||||
DRAGSTART: 'dragstart',
|
||||
DRAG: 'drag',
|
||||
DRAGEND: 'dragend',
|
||||
|
||||
// mousewheel handler
|
||||
MOUSEWHEEL: 'mousewheel',
|
||||
|
||||
// click handler
|
||||
CLICK: 'click'
|
||||
};
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {goog.events.Event}
|
||||
* @param {string} type Event type.
|
||||
* @param {goog.events.Event=} opt_evt The underlying event.
|
||||
*/
|
||||
ol.events.MapEvent = function(type, opt_evt) {
|
||||
goog.base(this, type);
|
||||
|
||||
/**
|
||||
* X displacement relative to the previous drag event, if any.
|
||||
*
|
||||
* @type {number|undefined}
|
||||
*/
|
||||
this.deltaX = undefined;
|
||||
|
||||
/**
|
||||
* Y displacement relative to the previous drag event, if any.
|
||||
*
|
||||
* @type {number|undefined}
|
||||
*/
|
||||
this.deltaY = undefined;
|
||||
|
||||
/**
|
||||
* The underlying event.
|
||||
*
|
||||
* @type {goog.events.Event}
|
||||
*/
|
||||
this.originalEvent = goog.isDef(opt_evt) ? opt_evt : null;
|
||||
};
|
||||
goog.inherits(ol.events.MapEvent, goog.events.Event);
|
||||
52
src/ol/handler/Click.js
Normal file
52
src/ol/handler/Click.js
Normal file
@@ -0,0 +1,52 @@
|
||||
/**
|
||||
* @fileoverview Click Handler.
|
||||
*
|
||||
* Provides a class for listening to click events on a DOM element
|
||||
* and dispatching click events to a map instance.
|
||||
*
|
||||
* This handler has no default behaviour.
|
||||
*/
|
||||
|
||||
goog.provide('ol.handler.Click');
|
||||
|
||||
goog.require('ol.handler.MapHandler');
|
||||
goog.require('ol.events.MapEvent');
|
||||
goog.require('ol.events.MapEventType');
|
||||
|
||||
goog.require('goog.events');
|
||||
goog.require('goog.events.EventType');
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.handler.MapHandler}
|
||||
* @param {ol.Map} map The map instance.
|
||||
* @param {ol.handler.states} states An object for the handlers to share
|
||||
* states.
|
||||
*/
|
||||
ol.handler.Click = function(map, states) {
|
||||
goog.base(this, map, states);
|
||||
|
||||
goog.events.listen(this.element_, goog.events.EventType.CLICK,
|
||||
this.handleClick, false, this);
|
||||
};
|
||||
goog.inherits(ol.handler.Click, ol.handler.MapHandler);
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.handler.Click.prototype.disposeInternal = function() {
|
||||
goog.events.unlisten(this.element_, goog.events.EventType.CLICK,
|
||||
this.handleClick, false, this);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {goog.events.BrowserEvent} e
|
||||
*/
|
||||
ol.handler.Click.prototype.handleClick = function(e) {
|
||||
// do not emit a map click event after a drag
|
||||
if (!this.states_.dragged) {
|
||||
var newE = new ol.events.MapEvent(ol.events.MapEventType.CLICK, e);
|
||||
goog.events.dispatchEvent(this.map_, newE);
|
||||
}
|
||||
};
|
||||
137
src/ol/handler/Drag.js
Normal file
137
src/ol/handler/Drag.js
Normal file
@@ -0,0 +1,137 @@
|
||||
/**
|
||||
* @fileoverview Drag Handler.
|
||||
*
|
||||
* Provides a class for listening to drag sequences on a DOM element and
|
||||
* dispatching dragstart, drag and dragend events to a map object.
|
||||
*
|
||||
* The default behavior for the drag event is moving the map.
|
||||
*/
|
||||
|
||||
goog.provide('ol.handler.Drag');
|
||||
|
||||
goog.require('ol.handler.MapHandler');
|
||||
goog.require('ol.events.MapEvent');
|
||||
goog.require('ol.events.MapEventType');
|
||||
|
||||
goog.require('goog.events');
|
||||
goog.require('goog.events.Event');
|
||||
goog.require('goog.events.EventType');
|
||||
goog.require('goog.fx.Dragger');
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.handler.MapHandler}
|
||||
* @param {ol.Map} map The map instance.
|
||||
* @param {ol.handler.states} states An object for the handlers to share
|
||||
* states.
|
||||
*/
|
||||
ol.handler.Drag = function(map, states) {
|
||||
goog.base(this, map, states);
|
||||
|
||||
/**
|
||||
* @type {goog.fx.Dragger}
|
||||
*/
|
||||
this.dragger_ = new goog.fx.Dragger(this.element_);
|
||||
|
||||
var dragger = this.dragger_;
|
||||
dragger.defaultAction = function() {};
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
this.prevX_ = 0;
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
**/
|
||||
this.prevY_ = 0;
|
||||
|
||||
goog.events.listen(dragger, goog.fx.Dragger.EventType.START,
|
||||
this.handleDragStart, false, this);
|
||||
goog.events.listen(dragger, goog.fx.Dragger.EventType.DRAG,
|
||||
this.handleDrag, false, this);
|
||||
goog.events.listen(dragger, goog.fx.Dragger.EventType.END,
|
||||
this.handleDragEnd, false, this);
|
||||
goog.events.listen(dragger, goog.fx.Dragger.EventType.EARLY_CANCEL,
|
||||
this.handleDragEarlyCancel, false, this);
|
||||
|
||||
};
|
||||
goog.inherits(ol.handler.Drag, ol.handler.MapHandler);
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.handler.Drag.prototype.disposeInternal = function() {
|
||||
goog.base(this, 'disposeInternal');
|
||||
goog.dispose(this.dragger_);
|
||||
goog.events.unlisten(this.element_,
|
||||
[goog.events.EventType.TOUCHMOVE,
|
||||
goog.events.EventType.MOUSEMOVE],
|
||||
goog.events.Event.preventDefault, false, this);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {goog.fx.DragEvent} e
|
||||
*/
|
||||
ol.handler.Drag.prototype.handleDragStart = function(e) {
|
||||
this.states_.dragged = false;
|
||||
this.prevX_ = e.clientX;
|
||||
this.prevY_ = e.clientY;
|
||||
var newE = new ol.events.MapEvent(ol.events.MapEventType.DRAGSTART, e);
|
||||
goog.events.dispatchEvent(this.map_, newE);
|
||||
|
||||
// this is to prevent page scrolling
|
||||
goog.events.listen(this.element_,
|
||||
[goog.events.EventType.TOUCHMOVE,
|
||||
goog.events.EventType.MOUSEMOVE],
|
||||
goog.events.Event.preventDefault, false, this);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {goog.fx.DragEvent} e
|
||||
*/
|
||||
ol.handler.Drag.prototype.handleDrag = function(e) {
|
||||
this.states_.dragged = true;
|
||||
var newE = new ol.events.MapEvent(ol.events.MapEventType.DRAG, e);
|
||||
newE.deltaX = e.clientX - this.prevX_;
|
||||
newE.deltaY = e.clientY - this.prevY_;
|
||||
this.prevX_ = e.clientX;
|
||||
this.prevY_ = e.clientY;
|
||||
var rt = goog.events.dispatchEvent(this.map_, newE);
|
||||
if (rt) {
|
||||
this.defaultDrag(newE);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {ol.events.MapEvent} e
|
||||
*/
|
||||
ol.handler.Drag.prototype.defaultDrag = function(e) {
|
||||
var deltaX = /** @type {number} */ e.deltaX;
|
||||
var deltaY = /** @type {number} */ e.deltaY;
|
||||
this.map_.moveByViewportPx(deltaX, deltaY);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {goog.fx.DragEvent} e
|
||||
*/
|
||||
ol.handler.Drag.prototype.handleDragEnd = function(e) {
|
||||
var newE = new ol.events.MapEvent(ol.events.MapEventType.DRAGEND, e);
|
||||
goog.events.dispatchEvent(this.map_, newE);
|
||||
goog.events.unlisten(this.element_,
|
||||
[goog.events.EventType.TOUCHMOVE,
|
||||
goog.events.EventType.MOUSEMOVE],
|
||||
goog.events.Event.preventDefault, false, this);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {goog.fx.DragEvent} e
|
||||
*/
|
||||
ol.handler.Drag.prototype.handleDragEarlyCancel = function(e) {
|
||||
goog.events.unlisten(this.element_,
|
||||
[goog.events.EventType.TOUCHMOVE,
|
||||
goog.events.EventType.MOUSEMOVE],
|
||||
goog.events.Event.preventDefault, false, this);
|
||||
};
|
||||
56
src/ol/handler/MapHandler.js
Normal file
56
src/ol/handler/MapHandler.js
Normal file
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* @fileoverview Map Handler.
|
||||
*
|
||||
* Type definitions and base class for map event handlers that share states,
|
||||
* listen for events on a map related dom element (usually the map's viewport),
|
||||
* dispatch events to an ol.Map instance, and optionally perform default
|
||||
* actions on an ol.Map instance.
|
||||
*/
|
||||
|
||||
goog.provide('ol.handler.states');
|
||||
goog.provide('ol.handler.MapHandler');
|
||||
|
||||
goog.require('goog.Disposable');
|
||||
|
||||
/**
|
||||
* Type definition for shared states between handlers. The following states
|
||||
* are defined:
|
||||
*
|
||||
* * dragged (boolean) - Set by the Drag handler when we are dragging. Read by
|
||||
* the click handler to determine if a click is a real click or the result
|
||||
* of a mouseup/touchend at the end of a drag sequence.
|
||||
*
|
||||
* @typedef {{dragged: boolean}}
|
||||
*/
|
||||
ol.handler.states;
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {goog.Disposable}
|
||||
* @param {ol.Map} map The map instance.
|
||||
* @param {ol.handler.states} states An object for the handlers to share
|
||||
* states.
|
||||
*/
|
||||
ol.handler.MapHandler = function(map, states) {
|
||||
goog.base(this);
|
||||
|
||||
/**
|
||||
* @type {ol.Map}
|
||||
* @protected
|
||||
*/
|
||||
this.map_ = map;
|
||||
|
||||
/**
|
||||
* @type {Element}
|
||||
* @protected
|
||||
*/
|
||||
this.element_ = map.getViewport();
|
||||
|
||||
/**
|
||||
* @type {ol.handler.states}
|
||||
* @protected
|
||||
*/
|
||||
this.states_ = states;
|
||||
|
||||
};
|
||||
goog.inherits(ol.handler.MapHandler, goog.Disposable);
|
||||
79
src/ol/handler/MouseWheel.js
Normal file
79
src/ol/handler/MouseWheel.js
Normal file
@@ -0,0 +1,79 @@
|
||||
/**
|
||||
* @fileoverview Mouse Wheel Handler.
|
||||
*
|
||||
* Provides a class for listening to mousewheel events on a DOM element
|
||||
* and dispatching mousewheel events to a map instance.
|
||||
*
|
||||
* The default behavior for the mousewheel event is zooming the map.
|
||||
*/
|
||||
|
||||
goog.provide('ol.handler.MouseWheel');
|
||||
|
||||
goog.require('ol.handler.MapHandler');
|
||||
goog.require('ol.events.MapEvent');
|
||||
goog.require('ol.events.MapEventType');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.events');
|
||||
goog.require('goog.style');
|
||||
goog.require('goog.events.MouseWheelHandler');
|
||||
goog.require('goog.events.MouseWheelHandler.EventType');
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.handler.MapHandler}
|
||||
* @param {ol.Map} map The map instance.
|
||||
* @param {ol.handler.states} states An object for the handlers to share
|
||||
* states.
|
||||
*/
|
||||
ol.handler.MouseWheel = function(map, states) {
|
||||
goog.base(this, map, states);
|
||||
|
||||
/**
|
||||
* @type {goog.events.MouseWheelHandler}
|
||||
*/
|
||||
this.handler_ = new goog.events.MouseWheelHandler(this.element_);
|
||||
|
||||
var handler = this.handler_;
|
||||
this.registerDisposable(handler);
|
||||
|
||||
goog.events.listen(handler,
|
||||
goog.events.MouseWheelHandler.EventType.MOUSEWHEEL,
|
||||
this.handleMouseWheel, false, this);
|
||||
|
||||
};
|
||||
goog.inherits(ol.handler.MouseWheel, ol.handler.MapHandler);
|
||||
|
||||
/**
|
||||
* @param {goog.events.MouseWheelEvent} e
|
||||
*/
|
||||
ol.handler.MouseWheel.prototype.handleMouseWheel = function(e) {
|
||||
var newE = new ol.events.MapEvent(ol.events.MapEventType.MOUSEWHEEL, e);
|
||||
var rt = goog.events.dispatchEvent(this.map_, newE);
|
||||
if (rt) {
|
||||
this.defaultMouseWheel(e);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {goog.events.MouseWheelEvent} e
|
||||
*/
|
||||
ol.handler.MouseWheel.prototype.defaultMouseWheel = function(e) {
|
||||
var me = this;
|
||||
if (e.deltaY === 0 || me.zoomBlocked_) {
|
||||
return;
|
||||
}
|
||||
me.zoomBlocked_ = window.setTimeout(function() {
|
||||
me.zoomBlocked_ = null;
|
||||
}, 200);
|
||||
|
||||
var map = me.map_,
|
||||
step = e.deltaY / Math.abs(e.deltaY);
|
||||
map.setZoom(map.getZoom() - step,
|
||||
goog.style.getRelativePosition(e, this.element_));
|
||||
|
||||
// We don't want the page to scroll.
|
||||
// (MouseWheelEvent is a BrowserEvent)
|
||||
e.preventDefault();
|
||||
};
|
||||
@@ -8,6 +8,7 @@ goog.require('ol.renderer.MapRenderer');
|
||||
goog.require('ol.layer.Layer');
|
||||
goog.require('ol.Loc');
|
||||
|
||||
goog.require('goog.events');
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.vec.Mat4');
|
||||
@@ -237,8 +238,10 @@ ol.renderer.WebGL.prototype.draw = function(layers, center, resolution, animate)
|
||||
tile = row[j];
|
||||
if (!tile.isLoaded()) {
|
||||
if (!tile.isLoading()) {
|
||||
tile.register('load', this.handleTileLoad, this);
|
||||
tile.register('destroy', this.handleTileDestroy, this);
|
||||
goog.events.listen(tile, 'load', this.handleTileLoad,
|
||||
undefined, this);
|
||||
goog.events.listen(tile, 'destroy', this.handleTileDestroy,
|
||||
undefined, this);
|
||||
tile.load();
|
||||
}
|
||||
continue;
|
||||
|
||||
@@ -74,7 +74,6 @@
|
||||
<script type="text/javascript" src="jasmine-extensions.js"></script>
|
||||
|
||||
<!-- include spec files here... -->
|
||||
<script type="text/javascript" src="spec/ol/Events.test.js"></script>
|
||||
<script type="text/javascript" src="spec/ol/UnreferencedBounds.test.js"></script>
|
||||
<script type="text/javascript" src="spec/ol/Projection.test.js"></script>
|
||||
<script type="text/javascript" src="spec/ol/Bounds.test.js"></script>
|
||||
@@ -88,6 +87,9 @@
|
||||
<script type="text/javascript" src="spec/ol/geom/LineString.test.js"></script>
|
||||
<script type="text/javascript" src="spec/ol/geom/MultiLineString.test.js"></script>
|
||||
<script type="text/javascript" src="spec/ol/geom/Collection.test.js"></script>
|
||||
<script type="text/javascript" src="spec/ol/handler/Drag.test.js"></script>
|
||||
<script type="text/javascript" src="spec/ol/handler/MouseWheel.test.js"></script>
|
||||
<script type="text/javascript" src="spec/ol/handler/Click.test.js"></script>
|
||||
<script type="text/javascript" src="spec/ol/layer/TileLayer.test.js"></script>
|
||||
<script type="text/javascript" src="spec/ol/layer/XYZ.test.js"></script>
|
||||
<script type="text/javascript" src="spec/ol/layer/WMS.test.js"></script>
|
||||
|
||||
@@ -1,175 +0,0 @@
|
||||
describe("ol.event.Events", function() {
|
||||
|
||||
var log = [],
|
||||
logFn = function(e) {log.push({scope: this, evt: e});};
|
||||
|
||||
|
||||
it("constructs instances", function() {
|
||||
var events, element = document.createElement("div");
|
||||
|
||||
events = new ol.event.Events("foo");
|
||||
expect(events.getObject()).toBe("foo");
|
||||
expect(events.getElement()).toBe(null);
|
||||
events.destroy();
|
||||
|
||||
events = new ol.event.Events("foo", element, true);
|
||||
expect(events.getElement()).toBe(element);
|
||||
expect(events.includeXY_).toBe(true);
|
||||
events.destroy();
|
||||
});
|
||||
|
||||
it("destroys properly", function() {
|
||||
var events = new ol.event.Events("foo");
|
||||
events.destroy();
|
||||
expect(events.getObject()).toBe(undefined);
|
||||
});
|
||||
|
||||
it("relays browser events and knows about pointer position", function() {
|
||||
var element = document.createElement("div"),
|
||||
events = new ol.event.Events("foo", element);
|
||||
|
||||
//TODO Figure out a good way to deal with fixtures
|
||||
element.style.position = "absolute";
|
||||
element.style.left = "5px";
|
||||
element.style.top = "10px";
|
||||
document.body.appendChild(element);
|
||||
// mock dom element so we can trigger events on it
|
||||
goog.object.extend(element, new goog.events.EventTarget());
|
||||
|
||||
log = [];
|
||||
events.register("click", logFn);
|
||||
element.dispatchEvent("click");
|
||||
expect(log.length).toBe(1);
|
||||
|
||||
// detach from the element
|
||||
events.setElement(null);
|
||||
element.dispatchEvent("click");
|
||||
expect(log.length).toBe(1);
|
||||
|
||||
// attach to the element again
|
||||
events.setElement(element);
|
||||
events.setIncludeXY(true);
|
||||
element.dispatchEvent({
|
||||
type: "click",
|
||||
touches: [{clientX: 9, clientY: 22}, {clientX: 11, clientY: 18}]
|
||||
});
|
||||
expect(log.length).toBe(2);
|
||||
expect(log[1].evt.xy.x).toBe(5);
|
||||
expect(log[1].evt.xy.y).toBe(10);
|
||||
expect(log[1].evt.clientX).toBe(10);
|
||||
expect(log[1].evt.clientY).toBe(20);
|
||||
|
||||
events.destroy();
|
||||
document.body.removeChild(element);
|
||||
});
|
||||
|
||||
it("calls listeners with a scope and an event object", function() {
|
||||
var scope = {}, evt = {}, events = new ol.event.Events("foo");
|
||||
|
||||
log = [];
|
||||
events.register("bar", logFn, scope);
|
||||
events.triggerEvent("bar", evt);
|
||||
expect(log[0].scope).toBe(scope);
|
||||
expect(log[0].evt).toBe(evt);
|
||||
expect(log[0].evt.object).toBe("foo");
|
||||
});
|
||||
|
||||
it("respects event priority", function() {
|
||||
var log = [], events = new ol.event.Events("foo");
|
||||
|
||||
// register a normal listener
|
||||
events.register("bar", function() {log.push("normal");});
|
||||
// register a priority listener
|
||||
events.register(
|
||||
"bar", function() {log.push("priority");}, undefined, true);
|
||||
events.triggerEvent("bar");
|
||||
expect(log[0]).toBe("priority");
|
||||
expect(log[1]).toBe("normal");
|
||||
|
||||
events.destroy();
|
||||
});
|
||||
|
||||
it("allows to abort the event chain", function() {
|
||||
var events = new ol.event.Events("foo");
|
||||
|
||||
log = [];
|
||||
// register a listener that aborts the event chain
|
||||
events.register("bar", function(e) {logFn(e); return false;});
|
||||
// register a listener that just does something
|
||||
events.register("bar", logFn);
|
||||
events.triggerEvent("bar");
|
||||
expect(log.length).toBe(1);
|
||||
|
||||
log = [];
|
||||
// register a priority listener that just does something
|
||||
events.register("bar", logFn, undefined, true);
|
||||
events.triggerEvent("bar");
|
||||
expect(log.length).toBe(2);
|
||||
|
||||
events.destroy();
|
||||
});
|
||||
|
||||
it("allows to unregister events", function() {
|
||||
var events = new ol.event.Events("foo");
|
||||
|
||||
log = [];
|
||||
events.register("bar", logFn);
|
||||
expect(events.listenerCount_["bar"]).toBe(1);
|
||||
|
||||
events.triggerEvent("bar");
|
||||
expect(log.length).toBe(1);
|
||||
|
||||
events.unregister("bar", logFn);
|
||||
events.triggerEvent("bar");
|
||||
expect(log.length).toBe(1);
|
||||
|
||||
events.unregister("bar", logFn);
|
||||
expect(events.listenerCount_["bar"]).toBe(0);
|
||||
|
||||
events.destroy();
|
||||
});
|
||||
|
||||
it("can be extended with sequences implementing ol.event.ISequence", function() {
|
||||
var sequence;
|
||||
var Sequence = function(target) {
|
||||
sequence = this;
|
||||
this.target = target;
|
||||
};
|
||||
Sequence.prototype.fire = function() {
|
||||
this.target.triggerEvent("myevent");
|
||||
};
|
||||
Sequence.prototype.destroy = function() {
|
||||
this.destroyed = true;
|
||||
};
|
||||
ol.event.addSequenceProvider("myseq", Sequence);
|
||||
|
||||
var element = document.createElement("div");
|
||||
events = new ol.event.Events("foo", undefined, false, ["myseq"]);
|
||||
|
||||
expect(sequence).toBeUndefined();
|
||||
|
||||
log = [];
|
||||
events.setElement(element);
|
||||
events.register('myevent', logFn);
|
||||
sequence.fire();
|
||||
|
||||
expect(log.length).toBe(1);
|
||||
expect(log[0].evt.type).toBe("myevent");
|
||||
|
||||
events.destroy();
|
||||
expect(sequence.destroyed).toBe(true);
|
||||
});
|
||||
|
||||
it("provides an isSingleTouch() function", function() {
|
||||
expect(ol.event.isSingleTouch({touches: [{}, {}]})).toBe(false);
|
||||
expect(ol.event.isSingleTouch({touches: [{}]})).toBe(true);
|
||||
expect(ol.event.isSingleTouch({})).toBe(false);
|
||||
});
|
||||
|
||||
it("provides an isMultiTouch() function", function() {
|
||||
expect(ol.event.isMultiTouch({touches: [{}, {}]})).toBe(true);
|
||||
expect(ol.event.isMultiTouch({touches: [{}]})).toBe(false);
|
||||
expect(ol.event.isMultiTouch({})).toBe(false);
|
||||
});
|
||||
|
||||
});
|
||||
@@ -34,7 +34,7 @@ describe("ol.Tile", function() {
|
||||
});
|
||||
it("fires a load event", function() {
|
||||
var spy = jasmine.createSpy();
|
||||
tile.events_.register('load', spy);
|
||||
goog.events.listen(tile, 'load', spy);
|
||||
tile.handleImageLoad();
|
||||
expect(spy).toHaveBeenCalled();
|
||||
});
|
||||
@@ -57,7 +57,7 @@ describe("ol.Tile", function() {
|
||||
});
|
||||
it("fires a load event", function() {
|
||||
var spy = jasmine.createSpy();
|
||||
tile.events_.register('error', spy);
|
||||
goog.events.listen(tile, 'error', spy);
|
||||
tile.handleImageError();
|
||||
expect(spy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
47
test/spec/ol/handler/Click.test.js
Normal file
47
test/spec/ol/handler/Click.test.js
Normal file
@@ -0,0 +1,47 @@
|
||||
describe('ol.handler.Click', function() {
|
||||
var map, elt, listener;
|
||||
|
||||
beforeEach(function() {
|
||||
map = new ol.Map();
|
||||
elt = new goog.events.EventTarget();
|
||||
map.viewport_ = elt;
|
||||
listener = {fn: function() {}};
|
||||
spyOn(listener, 'fn');
|
||||
});
|
||||
|
||||
describe('creating a drag handler', function() {
|
||||
|
||||
it('returns an ol.handler.Click instance', function() {
|
||||
var handler = new ol.handler.Click(map, {});
|
||||
expect(handler).toBeA(ol.handler.Click);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('dispatching events', function() {
|
||||
|
||||
it('dispatches a click event which is an ol.events.MapEvent', function() {
|
||||
new ol.handler.Click(map, {});
|
||||
goog.events.listen(map, 'click', listener.fn);
|
||||
|
||||
goog.events.fireListeners(elt, 'click', false, 'foo');
|
||||
var evt = listener.fn.calls[0].args[0];
|
||||
expect(evt).toBeA(ol.events.MapEvent);
|
||||
expect(evt.originalEvent).toBe('foo');
|
||||
});
|
||||
|
||||
it('ignores click events when the dragged state is set', function() {
|
||||
var states = {};
|
||||
new ol.handler.Click(map, states);
|
||||
goog.events.listen(map, 'click', listener.fn);
|
||||
|
||||
goog.events.fireListeners(elt, 'click', false);
|
||||
expect(listener.fn.calls.length).toBe(1);
|
||||
|
||||
states.dragged = true;
|
||||
goog.events.fireListeners(elt, 'click', false);
|
||||
expect(listener.fn.calls.length).toBe(1);
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
77
test/spec/ol/handler/Drag.test.js
Normal file
77
test/spec/ol/handler/Drag.test.js
Normal file
@@ -0,0 +1,77 @@
|
||||
describe('ol.handler.Drag', function() {
|
||||
var map;
|
||||
|
||||
beforeEach(function() {
|
||||
map = new ol.Map();
|
||||
var elt = new goog.events.EventTarget();
|
||||
map.viewport_ = elt;
|
||||
});
|
||||
|
||||
describe('creating a drag handler', function() {
|
||||
|
||||
it('returns an ol.handler.Drag instance', function() {
|
||||
var handler = new ol.handler.Drag(map, {});
|
||||
expect(handler).toBeA(ol.handler.Drag);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('dispatching events', function() {
|
||||
var handler, states;
|
||||
|
||||
beforeEach(function() {
|
||||
states = {};
|
||||
handler = new ol.handler.Drag(map, states);
|
||||
});
|
||||
|
||||
it('dragstart, drag and dragend events', function() {
|
||||
var spy = spyOn(goog.events.Event, 'preventDefault').andCallThrough();
|
||||
goog.events.listen(map, ol.events.MapEventType.DRAGSTART, spy);
|
||||
goog.events.listen(map, ol.events.MapEventType.DRAG, spy);
|
||||
goog.events.listen(map, ol.events.MapEventType.DRAGEND, spy);
|
||||
|
||||
handler.dragger_.dispatchEvent({type: goog.fx.Dragger.EventType.START});
|
||||
handler.dragger_.dispatchEvent({type: goog.fx.Dragger.EventType.DRAG});
|
||||
handler.dragger_.dispatchEvent({type: goog.fx.Dragger.EventType.END});
|
||||
|
||||
expect(spy.callCount).toEqual(3);
|
||||
expect(spy.argsForCall[0][0].type).toEqual(ol.events.MapEventType.DRAGSTART);
|
||||
expect(spy.argsForCall[1][0].type).toEqual(ol.events.MapEventType.DRAG);
|
||||
expect(spy.argsForCall[2][0].type).toEqual(ol.events.MapEventType.DRAGEND);
|
||||
});
|
||||
|
||||
it('sets the dragged state during a drag sequence', function() {
|
||||
handler.dragger_.dispatchEvent({type: goog.fx.Dragger.EventType.DRAG});
|
||||
expect(states.dragged).toBeTruthy();
|
||||
|
||||
handler.dragger_.dispatchEvent({type: goog.fx.Dragger.EventType.START});
|
||||
expect(states.dragged).toBeFalsy();
|
||||
});
|
||||
|
||||
it('sets deltaX and deltaY on the ol.event.MapEvent', function() {
|
||||
var spy = spyOn(goog.events.Event, 'preventDefault').andCallThrough();
|
||||
goog.events.listen(map, ol.events.MapEventType.DRAG, spy);
|
||||
|
||||
handler.dragger_.dispatchEvent({type: goog.fx.Dragger.EventType.START,
|
||||
clientX: 2, clientY: 4});
|
||||
handler.dragger_.dispatchEvent({type: goog.fx.Dragger.EventType.DRAG,
|
||||
clientX: 1, clientY: 2});
|
||||
handler.dragger_.dispatchEvent({type: goog.fx.Dragger.EventType.DRAG,
|
||||
clientX: 2, clientY: 4});
|
||||
|
||||
expect(spy.callCount).toEqual(2);
|
||||
expect(spy.argsForCall[0][0].deltaX).toEqual(-1);
|
||||
expect(spy.argsForCall[0][0].deltaY).toEqual(-2);
|
||||
expect(spy.argsForCall[1][0].deltaX).toEqual(1);
|
||||
expect(spy.argsForCall[1][0].deltaY).toEqual(2);
|
||||
});
|
||||
|
||||
it('calls the default action', function() {
|
||||
var handler = new ol.handler.Drag(map, {});
|
||||
var spy spyOn(handler, 'defaultDrag');
|
||||
|
||||
handler.dragger_.dispatchEvent({type: goog.fx.Dragger.EventType.DRAG});
|
||||
expect(spy).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
49
test/spec/ol/handler/MouseWheel.test.js
Normal file
49
test/spec/ol/handler/MouseWheel.test.js
Normal file
@@ -0,0 +1,49 @@
|
||||
describe('ol.handler.MouseWheel', function() {
|
||||
var map;
|
||||
|
||||
beforeEach(function() {
|
||||
map = new ol.Map();
|
||||
var elt = new goog.events.EventTarget();
|
||||
map.viewport_ = elt;
|
||||
});
|
||||
|
||||
describe('create a mouse wheel handler', function() {
|
||||
|
||||
it('returns an ol.handler.MouseWheel instance', function() {
|
||||
var handler = new ol.handler.MouseWheel(map, {});
|
||||
expect(handler).toBeA(ol.handler.MouseWheel);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('dispatching events', function() {
|
||||
|
||||
var handler;
|
||||
|
||||
beforeEach(function() {
|
||||
handler = new ol.handler.MouseWheel(map, {});
|
||||
});
|
||||
|
||||
it('dispatches a mousewheel event', function() {
|
||||
var spy = spyOn(goog.events.Event, 'preventDefault').andCallThrough();
|
||||
goog.events.listen(map, ol.events.MapEventType.MOUSEWHEEL, spy);
|
||||
|
||||
var evt = new goog.events.MouseWheelEvent(1, 'foo', 0, 1);
|
||||
handler.handler_.dispatchEvent(evt);
|
||||
|
||||
expect(spy).toHaveBeenCalled();
|
||||
expect(spy.argsForCall[0][0].type).toEqual(ol.events.MapEventType.MOUSEWHEEL);
|
||||
});
|
||||
|
||||
it('calls the default action', function() {
|
||||
var handler = new ol.handler.MouseWheel(map, {});
|
||||
spyOn(handler, 'defaultMouseWheel');
|
||||
|
||||
var evt = new goog.events.MouseWheelEvent(1, 'foo', 0, 1);
|
||||
handler.handler_.dispatchEvent(evt);
|
||||
|
||||
expect(handler.defaultMouseWheel).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user