diff --git a/lib/OpenLayers/Events.js b/lib/OpenLayers/Events.js deleted file mode 100644 index ddf375444a..0000000000 --- a/lib/OpenLayers/Events.js +++ /dev/null @@ -1,975 +0,0 @@ -/* Copyright (c) 2006-2012 by OpenLayers Contributors (see authors.txt for - * full list of contributors). Published under the 2-clause BSD license. - * See license.txt in the OpenLayers distribution or repository for the - * full text of the license. */ - - -/** - * @requires OpenLayers/Util.js - */ - -/** - * Namespace: OpenLayers.Event - * Utility functions for event handling. - */ -OpenLayers.Event = { - - /** - * Property: observers - * {Object} A hashtable cache of the event observers. Keyed by - * element._eventCacheID - */ - observers: false, - - /** - * Constant: KEY_SPACE - * {int} - */ - KEY_SPACE: 32, - - /** - * Constant: KEY_BACKSPACE - * {int} - */ - KEY_BACKSPACE: 8, - - /** - * Constant: KEY_TAB - * {int} - */ - KEY_TAB: 9, - - /** - * Constant: KEY_RETURN - * {int} - */ - KEY_RETURN: 13, - - /** - * Constant: KEY_ESC - * {int} - */ - KEY_ESC: 27, - - /** - * Constant: KEY_LEFT - * {int} - */ - KEY_LEFT: 37, - - /** - * Constant: KEY_UP - * {int} - */ - KEY_UP: 38, - - /** - * Constant: KEY_RIGHT - * {int} - */ - KEY_RIGHT: 39, - - /** - * Constant: KEY_DOWN - * {int} - */ - KEY_DOWN: 40, - - /** - * Constant: KEY_DELETE - * {int} - */ - KEY_DELETE: 46, - - - /** - * Method: element - * Cross browser event element detection. - * - * Parameters: - * event - {Event} - * - * Returns: - * {DOMElement} The element that caused the event - */ - element: function(event) { - return event.target || event.srcElement; - }, - - /** - * Method: isSingleTouch - * Determine whether event was caused by a single touch - * - * Parameters: - * event - {Event} - * - * Returns: - * {Boolean} - */ - isSingleTouch: function(event) { - return event.touches && event.touches.length == 1; - }, - - /** - * Method: isMultiTouch - * Determine whether event was caused by a multi touch - * - * Parameters: - * event - {Event} - * - * Returns: - * {Boolean} - */ - isMultiTouch: function(event) { - return event.touches && event.touches.length > 1; - }, - - /** - * Method: isLeftClick - * Determine whether event was caused by a left click. - * - * Parameters: - * event - {Event} - * - * Returns: - * {Boolean} - */ - isLeftClick: function(event) { - return (((event.which) && (event.which == 1)) || - ((event.button) && (event.button == 1))); - }, - - /** - * Method: isRightClick - * Determine whether event was caused by a right mouse click. - * - * Parameters: - * event - {Event} - * - * Returns: - * {Boolean} - */ - isRightClick: function(event) { - return (((event.which) && (event.which == 3)) || - ((event.button) && (event.button == 2))); - }, - - /** - * Method: stop - * Stops an event from propagating. - * - * Parameters: - * event - {Event} - * allowDefault - {Boolean} If true, we stop the event chain but - * still allow the default browser behaviour (text selection, - * radio-button clicking, etc). Default is false. - */ - stop: function(event, allowDefault) { - - if (!allowDefault) { - if (event.preventDefault) { - event.preventDefault(); - } else { - event.returnValue = false; - } - } - - if (event.stopPropagation) { - event.stopPropagation(); - } else { - event.cancelBubble = true; - } - }, - - /** - * Method: findElement - * - * Parameters: - * event - {Event} - * tagName - {String} - * - * Returns: - * {DOMElement} The first node with the given tagName, starting from the - * node the event was triggered on and traversing the DOM upwards - */ - findElement: function(event, tagName) { - var element = OpenLayers.Event.element(event); - while (element.parentNode && (!element.tagName || - (element.tagName.toUpperCase() != tagName.toUpperCase()))){ - element = element.parentNode; - } - return element; - }, - - /** - * Method: observe - * - * Parameters: - * elementParam - {DOMElement || String} - * name - {String} - * observer - {function} - * useCapture - {Boolean} - */ - observe: function(elementParam, name, observer, useCapture) { - var element = OpenLayers.Util.getElement(elementParam); - useCapture = useCapture || false; - - if (name == 'keypress' && - (navigator.appVersion.match(/Konqueror|Safari|KHTML/) - || element.attachEvent)) { - name = 'keydown'; - } - - //if observers cache has not yet been created, create it - if (!this.observers) { - this.observers = {}; - } - - //if not already assigned, make a new unique cache ID - if (!element._eventCacheID) { - var idPrefix = "eventCacheID_"; - if (element.id) { - idPrefix = element.id + "_" + idPrefix; - } - element._eventCacheID = OpenLayers.Util.createUniqueID(idPrefix); - } - - var cacheID = element._eventCacheID; - - //if there is not yet a hash entry for this element, add one - if (!this.observers[cacheID]) { - this.observers[cacheID] = []; - } - - //add a new observer to this element's list - this.observers[cacheID].push({ - 'element': element, - 'name': name, - 'observer': observer, - 'useCapture': useCapture - }); - - //add the actual browser event listener - if (element.addEventListener) { - element.addEventListener(name, observer, useCapture); - } else if (element.attachEvent) { - element.attachEvent('on' + name, observer); - } - }, - - /** - * Method: stopObservingElement - * Given the id of an element to stop observing, cycle through the - * element's cached observers, calling stopObserving on each one, - * skipping those entries which can no longer be removed. - * - * parameters: - * elementParam - {DOMElement || String} - */ - stopObservingElement: function(elementParam) { - var element = OpenLayers.Util.getElement(elementParam); - var cacheID = element._eventCacheID; - - this._removeElementObservers(OpenLayers.Event.observers[cacheID]); - }, - - /** - * Method: _removeElementObservers - * - * Parameters: - * elementObservers - {Array(Object)} Array of (element, name, - * observer, usecapture) objects, - * taken directly from hashtable - */ - _removeElementObservers: function(elementObservers) { - if (elementObservers) { - for(var i = elementObservers.length-1; i >= 0; i--) { - var entry = elementObservers[i]; - OpenLayers.Event.stopObserving.apply(this, [ - entry.element, entry.name, entry.observer, entry.useCapture - ]); - } - } - }, - - /** - * Method: stopObserving - * - * Parameters: - * elementParam - {DOMElement || String} - * name - {String} - * observer - {function} - * useCapture - {Boolean} - * - * Returns: - * {Boolean} Whether or not the event observer was removed - */ - stopObserving: function(elementParam, name, observer, useCapture) { - useCapture = useCapture || false; - - var element = OpenLayers.Util.getElement(elementParam); - var cacheID = element._eventCacheID; - - if (name == 'keypress') { - if ( navigator.appVersion.match(/Konqueror|Safari|KHTML/) || - element.detachEvent) { - name = 'keydown'; - } - } - - // find element's entry in this.observers cache and remove it - var foundEntry = false; - var elementObservers = OpenLayers.Event.observers[cacheID]; - if (elementObservers) { - - // find the specific event type in the element's list - var i=0; - while(!foundEntry && i < elementObservers.length) { - var cacheEntry = elementObservers[i]; - - if ((cacheEntry.name == name) && - (cacheEntry.observer == observer) && - (cacheEntry.useCapture == useCapture)) { - - elementObservers.splice(i, 1); - if (elementObservers.length == 0) { - delete OpenLayers.Event.observers[cacheID]; - } - foundEntry = true; - break; - } - i++; - } - } - - //actually remove the event listener from browser - if (foundEntry) { - if (element.removeEventListener) { - element.removeEventListener(name, observer, useCapture); - } else if (element && element.detachEvent) { - element.detachEvent('on' + name, observer); - } - } - return foundEntry; - }, - - /** - * Method: unloadCache - * Cycle through all the element entries in the events cache and call - * stopObservingElement on each. - */ - unloadCache: function() { - // check for OpenLayers.Event before checking for observers, because - // OpenLayers.Event may be undefined in IE if no map instance was - // created - if (OpenLayers.Event && OpenLayers.Event.observers) { - for (var cacheID in OpenLayers.Event.observers) { - var elementObservers = OpenLayers.Event.observers[cacheID]; - OpenLayers.Event._removeElementObservers.apply(this, - [elementObservers]); - } - OpenLayers.Event.observers = false; - } - }, - - CLASS_NAME: "OpenLayers.Event" -}; - -/* prevent memory leaks in IE */ -OpenLayers.Event.observe(window, 'unload', OpenLayers.Event.unloadCache, false); - -/** - * Class: OpenLayers.Events - */ -OpenLayers.Events = OpenLayers.Class({ - - /** - * Constant: BROWSER_EVENTS - * {Array(String)} supported events - */ - BROWSER_EVENTS: [ - "mouseover", "mouseout", - "mousedown", "mouseup", "mousemove", - "click", "dblclick", "rightclick", "dblrightclick", - "resize", "focus", "blur", - "touchstart", "touchmove", "touchend", - "keydown" - ], - - /** - * Property: listeners - * {Object} Hashtable of Array(Function): events listener functions - */ - listeners: null, - - /** - * Property: object - * {Object} the code object issuing application events - */ - object: null, - - /** - * Property: element - * {DOMElement} the DOM element receiving browser events - */ - element: null, - - /** - * Property: eventHandler - * {Function} bound event handler attached to elements - */ - eventHandler: null, - - /** - * APIProperty: fallThrough - * {Boolean} - */ - fallThrough: null, - - /** - * APIProperty: includeXY - * {Boolean} Should the .xy property automatically be created for browser - * mouse events? In general, this should be false. If it is true, then - * mouse events will automatically generate a '.xy' property on the - * event object that is passed. (Prior to OpenLayers 2.7, this was true - * by default.) Otherwise, you can call the getMousePosition on the - * relevant events handler on the object available via the 'evt.object' - * property of the evt object. So, for most events, you can call: - * function named(evt) { - * this.xy = this.object.events.getMousePosition(evt) - * } - * - * This option typically defaults to false for performance reasons: - * when creating an events object whose primary purpose is to manage - * relatively positioned mouse events within a div, it may make - * sense to set it to true. - * - * This option is also used to control whether the events object caches - * offsets. If this is false, it will not: the reason for this is that - * it is only expected to be called many times if the includeXY property - * is set to true. If you set this to true, you are expected to clear - * the offset cache manually (using this.clearMouseCache()) if: - * the border of the element changes - * the location of the element in the page changes - */ - includeXY: false, - - /** - * APIProperty: extensions - * {Object} Event extensions registered with this instance. Keys are - * event types, values are {OpenLayers.Events.*} extension instances or - * {Boolean} for events that an instantiated extension provides in - * addition to the one it was created for. - * - * Extensions create an event in addition to browser events, which usually - * fires when a sequence of browser events is completed. Extensions are - * automatically instantiated when a listener is registered for an event - * provided by an extension. - * - * Extensions are created in the namespace using - * , and named after the event they provide. - * The constructor receives the target instance as - * argument. Extensions that need to capture browser events before they - * propagate can register their listeners events using , with - * {extension: true} as 4th argument. - * - * If an extension creates more than one event, an alias for each event - * type should be created and reference the same class. The constructor - * should set a reference in the target's extensions registry to itself. - * - * Below is a minimal extension that provides the "foostart" and "fooend" - * event types, which replace the native "click" event type if clicked on - * an element with the css class "foo": - * - * (code) - * OpenLayers.Events.foostart = OpenLayers.Class({ - * initialize: function(target) { - * this.target = target; - * this.target.register("click", this, this.doStuff, {extension: true}); - * // only required if extension provides more than one event type - * this.target.extensions["foostart"] = true; - * this.target.extensions["fooend"] = true; - * }, - * destroy: function() { - * var target = this.target; - * target.unregister("click", this, this.doStuff); - * delete this.target; - * // only required if extension provides more than one event type - * delete target.extensions["foostart"]; - * delete target.extensions["fooend"]; - * }, - * doStuff: function(evt) { - * var propagate = true; - * if (OpenLayers.Event.element(evt).className === "foo") { - * propagate = false; - * var target = this.target; - * target.triggerEvent("foostart"); - * window.setTimeout(function() { - * target.triggerEvent("fooend"); - * }, 1000); - * } - * return propagate; - * } - * }); - * // only required if extension provides more than one event type - * OpenLayers.Events.fooend = OpenLayers.Events.foostart; - * (end) - * - */ - extensions: null, - - /** - * Property: extensionCount - * {Object} Keys are event types (like in ), values are the - * number of extension listeners for each event type. - */ - extensionCount: null, - - /** - * Method: clearMouseListener - * A version of that is bound to this instance so that - * it can be used with and - * . - */ - clearMouseListener: null, - - /** - * Constructor: OpenLayers.Events - * Construct an OpenLayers.Events object. - * - * Parameters: - * object - {Object} The js object to which this Events object is being added - * element - {DOMElement} A dom element to respond to browser events - * eventTypes - {Array(String)} Deprecated. Array of custom application - * events. A listener may be registered for any named event, regardless - * of the values provided here. - * fallThrough - {Boolean} Allow events to fall through after these have - * been handled? - * options - {Object} Options for the events object. - */ - initialize: function (object, element, eventTypes, fallThrough, options) { - OpenLayers.Util.extend(this, options); - this.object = object; - this.fallThrough = fallThrough; - this.listeners = {}; - this.extensions = {}; - this.extensionCount = {}; - - // if a dom element is specified, add a listeners list - // for browser events on the element and register them - if (element != null) { - this.attachToElement(element); - } - }, - - /** - * APIMethod: destroy - */ - destroy: function () { - for (var e in this.extensions) { - if (typeof this.extensions[e] !== "boolean") { - this.extensions[e].destroy(); - } - } - this.extensions = null; - if (this.element) { - OpenLayers.Event.stopObservingElement(this.element); - if(this.element.hasScrollEvent) { - OpenLayers.Event.stopObserving( - window, "scroll", this.clearMouseListener - ); - } - } - this.element = null; - - this.listeners = null; - this.object = null; - this.fallThrough = null; - this.eventHandler = null; - }, - - /** - * APIMethod: addEventType - * Deprecated. Any event can be triggered without adding it first. - * - * Parameters: - * eventName - {String} - */ - addEventType: function(eventName) { - }, - - /** - * Method: attachToElement - * - * Parameters: - * element - {HTMLDOMElement} a DOM element to attach browser events to - */ - attachToElement: function (element) { - if (this.element) { - OpenLayers.Event.stopObservingElement(this.element); - } else { - // keep a bound copy of handleBrowserEvent() so that we can - // pass the same function to both Event.observe() and .stopObserving() - this.eventHandler = OpenLayers.Function.bindAsEventListener( - this.handleBrowserEvent, this - ); - - // to be used with observe and stopObserving - this.clearMouseListener = OpenLayers.Function.bind( - this.clearMouseCache, this - ); - } - this.element = element; - for (var i = 0, len = this.BROWSER_EVENTS.length; i < len; i++) { - // register the event cross-browser - OpenLayers.Event.observe( - element, this.BROWSER_EVENTS[i], this.eventHandler - ); - } - // disable dragstart in IE so that mousedown/move/up works normally - OpenLayers.Event.observe(element, "dragstart", OpenLayers.Event.stop); - }, - - /** - * APIMethod: on - * Convenience method for registering listeners with a common scope. - * Internally, this method calls as shown in the examples - * below. - * - * Example use: - * (code) - * // register a single listener for the "loadstart" event - * events.on({"loadstart": loadStartListener}); - * - * // this is equivalent to the following - * events.register("loadstart", undefined, loadStartListener); - * - * // register multiple listeners to be called with the same `this` object - * events.on({ - * "loadstart": loadStartListener, - * "loadend": loadEndListener, - * scope: object - * }); - * - * // this is equivalent to the following - * events.register("loadstart", object, loadStartListener); - * events.register("loadend", object, loadEndListener); - * (end) - * - * Parameters: - * object - {Object} - */ - on: function(object) { - for(var type in object) { - if(type != "scope" && object.hasOwnProperty(type)) { - this.register(type, object.scope, object[type]); - } - } - }, - - /** - * APIMethod: register - * Register an event on the events object. - * - * When the event is triggered, the 'func' function will be called, in the - * context of 'obj'. Imagine we were to register an event, specifying an - * OpenLayers.Bounds Object as 'obj'. When the event is triggered, the - * context in the callback function will be our Bounds object. This means - * that within our callback function, we can access the properties and - * methods of the Bounds object through the "this" variable. So our - * callback could execute something like: - * : leftStr = "Left: " + this.left; - * - * or - * - * : centerStr = "Center: " + this.getCenterLonLat(); - * - * Parameters: - * type - {String} Name of the event to register - * obj - {Object} The object to bind the context to for the callback#. - * If no object is specified, default is the Events's 'object' property. - * func - {Function} The callback function. If no callback is - * specified, this function does nothing. - * priority - {Boolean|Object} If true, adds the new listener to the - * *front* of the events queue instead of to the end. - * - * Valid options for priority: - * extension - {Boolean} If true, then the event will be registered as - * extension event. Extension events are handled before all other - * events. - */ - register: function (type, obj, func, priority) { - if (type in OpenLayers.Events && !this.extensions[type]) { - this.extensions[type] = new OpenLayers.Events[type](this); - } - if (func != null) { - if (obj == null) { - obj = this.object; - } - var listeners = this.listeners[type]; - if (!listeners) { - listeners = []; - this.listeners[type] = listeners; - this.extensionCount[type] = 0; - } - var listener = {obj: obj, func: func}; - if (priority) { - listeners.splice(this.extensionCount[type], 0, listener); - if (typeof priority === "object" && priority.extension) { - this.extensionCount[type]++; - } - } else { - listeners.push(listener); - } - } - }, - - /** - * APIMethod: registerPriority - * Same as register() but adds the new listener to the *front* of the - * events queue instead of to the end. - * - * TODO: get rid of this in 3.0 - Decide whether listeners should be - * called in the order they were registered or in reverse order. - * - * - * Parameters: - * type - {String} Name of the event to register - * obj - {Object} The object to bind the context to for the callback#. - * If no object is specified, default is the Events's - * 'object' property. - * func - {Function} The callback function. If no callback is - * specified, this function does nothing. - */ - registerPriority: function (type, obj, func) { - this.register(type, obj, func, true); - }, - - /** - * APIMethod: un - * Convenience method for unregistering listeners with a common scope. - * Internally, this method calls as shown in the examples - * below. - * - * Example use: - * (code) - * // unregister a single listener for the "loadstart" event - * events.un({"loadstart": loadStartListener}); - * - * // this is equivalent to the following - * events.unregister("loadstart", undefined, loadStartListener); - * - * // unregister multiple listeners with the same `this` object - * events.un({ - * "loadstart": loadStartListener, - * "loadend": loadEndListener, - * scope: object - * }); - * - * // this is equivalent to the following - * events.unregister("loadstart", object, loadStartListener); - * events.unregister("loadend", object, loadEndListener); - * (end) - */ - un: function(object) { - for(var type in object) { - if(type != "scope" && object.hasOwnProperty(type)) { - this.unregister(type, object.scope, object[type]); - } - } - }, - - /** - * APIMethod: unregister - * - * Parameters: - * type - {String} - * obj - {Object} If none specified, defaults to this.object - * func - {Function} - */ - unregister: function (type, obj, func) { - if (obj == null) { - obj = this.object; - } - var listeners = this.listeners[type]; - if (listeners != null) { - for (var i=0, len=listeners.length; i} The current xy coordinate of the mouse, adjusted - * for offsets - */ - getMousePosition: function (evt) { - if (!this.includeXY) { - this.clearMouseCache(); - } else if (!this.element.hasScrollEvent) { - OpenLayers.Event.observe(window, "scroll", this.clearMouseListener); - this.element.hasScrollEvent = true; - } - - if (!this.element.scrolls) { - var viewportElement = OpenLayers.Util.getViewportElement(); - this.element.scrolls = [ - viewportElement.scrollLeft, - viewportElement.scrollTop - ]; - } - - if (!this.element.lefttop) { - this.element.lefttop = [ - (document.documentElement.clientLeft || 0), - (document.documentElement.clientTop || 0) - ]; - } - - if (!this.element.offsets) { - this.element.offsets = OpenLayers.Util.pagePosition(this.element); - } - - return new OpenLayers.Pixel( - (evt.clientX + this.element.scrolls[0]) - this.element.offsets[0] - - this.element.lefttop[0], - (evt.clientY + this.element.scrolls[1]) - this.element.offsets[1] - - this.element.lefttop[1] - ); - }, - - CLASS_NAME: "OpenLayers.Events" -}); diff --git a/src/ol.js b/src/ol.js index e3a5bdbef6..b8d7328208 100644 --- a/src/ol.js +++ b/src/ol.js @@ -1,9 +1,11 @@ goog.provide("ol"); goog.require('ol.bounds'); +goog.require('ol.event'); +goog.require('ol.event.Events'); goog.require("ol.map"); goog.require("ol.loc"); goog.require("ol.projection"); goog.require("ol.Tile"); goog.require("ol.TileSet"); goog.require("ol.geom.geometry"); -goog.require("ol.geom.point"); +goog.require("ol.geom.point"); \ No newline at end of file diff --git a/src/ol/event/Events.js b/src/ol/event/Events.js new file mode 100644 index 0000000000..beea8c4877 --- /dev/null +++ b/src/ol/event/Events.js @@ -0,0 +1,295 @@ +goog.provide('ol.event'); +goog.provide('ol.event.Events'); + +goog.require('goog.events'); +goog.require('goog.events.EventType'); +goog.require('goog.events.EventTarget'); +goog.require('goog.events.Listener'); +goog.require('goog.style'); + + +/** + * @param {goog.events.BrowserEvent} evt + * @return {boolean} + * + * Determine whether event was caused by a single touch + */ +ol.event.isSingleTouch = function(evt) { + return evt.touches && evt.touches.length == 1; +}; + +/** + * @param {goog.events.BrowserEvent} evt + * @return {boolean} + * + * Determine whether event was caused by a multi touch + */ +ol.event.isMultiTouch = function(evt) { + return evt.touches && evt.touches.length > 1; +}; + + +/** + * @constructor + * @extends {goog.events.EventTarget} + * @param {Object} object The object we are creating this instance for. + * @param {!EventTarget=} 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. + * + * Construct an ol.event.Events instance. + */ +ol.event.Events = function(object, opt_element, opt_includeXY) { + + goog.base(this); + + /** + * @type {Object} + * The object that this instance is bound to. + */ + this.object_ = object; + + /** + * @type {EventTarget|undefined} + * The element that this instance listens to mouse events on. + */ + this.element_ = opt_element; + + /** + * @type {boolean} + */ + this.includeXY_ = goog.isDef(opt_includeXY) ? opt_includeXY : false; + + // if a dom element is specified, add a listeners list + // for browser events on the element and register them + if (goog.isDef(opt_element)) { + this.attachToElement_(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 {!EventTarget} element A DOM element to attach + * browser events to. + * + * Attach this instance to a DOM element. If this is called, all browser events + * fired on the provided element will be relayed by this instance. + */ +ol.event.Events.prototype.attachToElement_ = function(element) { + if (this.element_) { + this.detachFromElement_(); + } + this.element_ = element; + var t, types = goog.events.EventType; + for (t in types) { + // register the event cross-browser + goog.events.listen( + element, types[t], this.handleBrowserEvent_, false, this + ); + } +}; + +/** + * Detach this instance from a DOM element. + */ +ol.event.Events.prototype.detachFromElement_ = function() { + var t, types = goog.events.EventType, + element = this.element_; + if (goog.isDef(element)) { + for (t in types) { + // register the event cross-browser + goog.events.unlisten( + element, types[t], this.handleBrowserEvent_, false, this + ); + } + delete this.element_; + + } +}; + +/** + * @param {Object} object + * + * Convenience method for registering listeners with a common scope. + * Internally, this method calls 'register' as shown in the examples below. + * + * // register a single listener for the "loadstart" event + * events.on({"loadstart": loadStartListener}); + * + * // this is equivalent to the following + * events.register("loadstart", loadStartListener); + * + * // register multiple listeners to be called with the same `this` object + * events.on({ + * "loadstart": loadStartListener, + * "loadend": loadEndListener, + * scope: object + * }); + * + * // this is equivalent to the following + * events.register("loadstart", loadStartListener, object); + * events.register("loadend", loadEndListener, object); + */ +ol.event.Events.prototype.on = function(object) { + for (var type in object) { + if (type != 'scope' && object.hasOwnProperty(type)) { + this.register(type, object[type], object['scope']); + } + } +}; + +/** + * @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. + * + * 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(); + */ +ol.event.Events.prototype.register = function(type, listener, opt_scope, + opt_priority) { + goog.events.listen( + this, type, listener, opt_priority, opt_scope || this.object_ + ); +}; + +/** + * @param {Object} object + * + * Convenience method for unregistering listeners with a common scope. + * Internally, this method calls 'unregister' as shown in the examples below. + * + * // unregister a single listener for the "loadstart" event + * events.un({"loadstart": loadStartListener}); + * + * // this is equivalent to the following + * events.unregister("loadstart", loadStartListener); + * + * // unregister multiple listeners with the same `this` object + * events.un({ + * "loadstart": loadStartListener, + * "loadend": loadEndListener, + * scope: object + * }); + * + * // this is equivalent to the following + * events.unregister("loadstart", loadStartListener, object); + * events.unregister("loadend", loadEndListener, object); + */ +ol.event.Events.prototype.un = function(object) { + for (var type in object) { + if (type != 'scope' && object.hasOwnProperty(type)) { + this.unregister(type, object[type], object['scope']); + } + } +}; + +/** + * @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. + * + * Unregister a listener for an egent + */ +ol.event.Events.prototype.unregister = function(type, listener, opt_scope) { + goog.events.unlisten( + this, type, listener, false, opt_scope || this.object_ + ); +}; + +/** + * @param {string} type The type of the event to trigger. + * @param {Object} evt The event object that will be passed to listeners. + * + * @return {Boolean} The last listener return. If a listener returns false, + * the chain of listeners will stop getting called. + * Trigger a specified registered event. + */ +ol.event.Events.prototype.triggerEvent = function(type, evt) { + var returnValue, + listeners = goog.events.getListeners(this, type, true) + .concat(goog.events.getListeners(this, type, false)); + for (var i=0, ii=listeners.length; i + diff --git a/test/spec/ol/Events.test.js b/test/spec/ol/Events.test.js new file mode 100644 index 0000000000..610d3a2032 --- /dev/null +++ b/test/spec/ol/Events.test.js @@ -0,0 +1,13 @@ +describe("ol.Events", function() { + + it("constructs instances", function() { + var events, element = document.createElement("div"); + events = new ol.event.Events("foo"); + expect(events.getObject()).toBe("foo"); + events.destroy(); + events = new ol.event.Events("foo", element, true); + expect(events.element_).toBe(element); + expect(events.includeXY_).toBe(true); + }); + +});