diff --git a/lib/OpenLayers/Events.js b/lib/OpenLayers/Events.js index c6ab5592c9..754e13e975 100644 --- a/lib/OpenLayers/Events.js +++ b/lib/OpenLayers/Events.js @@ -157,16 +157,9 @@ OpenLayers.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. - * terminate - {Boolean} If true, no more listeners registered through an - * instance on the same event on the same element - * will receive this event. Extensions that call should set - * this to true. Default is false. */ - stop: function(event, allowDefault, terminate) { + stop: function(event, allowDefault) { - if (terminate) { - event._terminated = true; - } if (!allowDefault) { if (event.preventDefault) { event.preventDefault(); @@ -466,15 +459,21 @@ OpenLayers.Events = OpenLayers.Class({ * automatically instantiated when a listener is registered for an event * provided by an extension. * - * Extesions are created in the namespace using + * Extensions are created in the namespace using * , and named after the event they provide. - * The constructor recieves the target instance as - * argument. Extensions are expected to have an "observe" method, which is - * called to register its sequence events on the target's dom element, - * using . See - * for a reference implementation. + * The constructor receives the target instance as + * argument. Extensions should register their browser events using + * , with {extension: true} as 4th argument. See + * for a reference implementation. */ 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 @@ -504,6 +503,7 @@ OpenLayers.Events = OpenLayers.Class({ 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 @@ -527,9 +527,7 @@ OpenLayers.Events = OpenLayers.Class({ */ destroy: function () { for (var e in this.extensions) { - if (typeof this.extensions[e].destroy === "function") { - this.extensions[e].destroy(); - } + this.extensions[e].destroy(); } this.extensions = null; if (this.element) { @@ -563,17 +561,8 @@ OpenLayers.Events = OpenLayers.Class({ * * Parameters: * element - {HTMLDOMElement} a DOM element to attach browser events to - * options - {Object} Additional options for his method. - * - * Valid options: - * keepElement - {Boolean} If set to true, the instance will not stop - * observing events on an element it was previously attached to. */ - attachToElement: function (element, options) { - options = options || {}; - if(this.element && !options.keepElement) { - OpenLayers.Event.stopObservingElement(this.element); - } + attachToElement: function (element) { this.element = element; for (var i = 0, len = this.BROWSER_EVENTS.length; i < len; i++) { // register the event cross-browser @@ -585,33 +574,6 @@ OpenLayers.Events = OpenLayers.Class({ OpenLayers.Event.observe(element, "dragstart", OpenLayers.Event.stop); }, - /** - * Method: addExtension - * Adds an extension event to this instance. - * - * Parameters: - * type - {String} the name of the extension event type to add - */ - addExtension: function(type) { - if (this.element.attachEvent && !this.element.addEventListener) { - // old IE - last registered, first triggered. No need to - // re-register the events to get them in a working order - this.extensions[type] = new OpenLayers.Events[type](this); - } else { - // Other browsers - last registered, last triggered. We stop - // observing the element, let the extensions register their browser - // events, and then we attach this instance to the element again. - OpenLayers.Event.stopObservingElement(this.element); - for (var t in this.extensions) { - if (typeof this.extensions[t].observe === "function") { - this.extensions[t].observe(); - } - } - this.extensions[type] = new OpenLayers.Events[type](this); - this.attachToElement(this.element, {keepElement: true}); - } - }, - /** * APIMethod: on * Convenience method for registering listeners with a common scope. @@ -669,16 +631,20 @@ OpenLayers.Events = OpenLayers.Class({ * 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. + * 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} If true, adds the new listener to the *front* of - * the events queue instead of to the end. + * 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.addExtension(type); + this.extensions[type] = new OpenLayers.Events[type](this); } if (func != null) { if (obj == null) { @@ -688,11 +654,16 @@ OpenLayers.Events = OpenLayers.Class({ if (!listeners) { listeners = []; this.listeners[type] = listeners; + this.extensionCount[type] = 0; } + var listener = {obj: obj, func: func}; if (priority) { - listeners.unshift({obj: obj, func: func}); + listeners.splice(this.extensionCount[type], 0, listener); + if (typeof priority === "object" && priority.extension) { + this.extensionCount[type]++; + } } else { - listeners.push({obj: obj, func: func}); + listeners.push(listener); } } }, @@ -852,8 +823,8 @@ OpenLayers.Events = OpenLayers.Class({ */ handleBrowserEvent: function (evt) { var type = evt.type, listeners = this.listeners[type]; - if(!listeners || listeners.length == 0 || evt._terminated) { - // noone's listening or event was terminated through , bail out + if(!listeners || listeners.length == 0) { + // noone's listening, bail out return; } // add clientX & clientY to all events - corresponds to average x, y diff --git a/lib/OpenLayers/Events/buttonclick.js b/lib/OpenLayers/Events/buttonclick.js index 79b0403bdc..6a9a5442e6 100644 --- a/lib/OpenLayers/Events/buttonclick.js +++ b/lib/OpenLayers/Events/buttonclick.js @@ -77,39 +77,20 @@ OpenLayers.Events.buttonclick = OpenLayers.Class({ } OpenLayers.Util.extend(this, options); - this._buttonClick = OpenLayers.Function.bindAsEventListener( - this.buttonClick, this - ); - this.observe(); - }, - - /** - * Method: observe - */ - observe: function() { for (var i=this.events.length-1; i>=0; --i) { - OpenLayers.Event.observe( - this.target.element, this.events[i], this._buttonClick - ); - }; - }, - - /** - * Method: stopObserving - */ - stopObserving: function() { - for (var i=this.events.length-1; i>=0; --i) { - OpenLayers.Event.stopObserving( - this.target.element, this.events[i], this._buttonClick - ); + this.target.register(this.events[i], this, this.buttonClick, { + extension: true + }); } }, - + /** * Method: destroy */ destroy: function() { - this.stopObserving() + for (var i=this.events.length-1; i>=0; --i) { + this.target.unregister(this.events[i], this, this.buttonClick); + } }, /** @@ -120,8 +101,9 @@ OpenLayers.Events.buttonclick = OpenLayers.Class({ * evt - {Event} */ buttonClick: function(evt) { - if (OpenLayers.Event.isLeftClick(evt) || !~evt.type.indexOf("mouse")) { - var element = OpenLayers.Event.element(evt); + var propagate = true, + element = OpenLayers.Event.element(evt); + if (element && (OpenLayers.Event.isLeftClick(evt) || !~evt.type.indexOf("mouse"))) { if (OpenLayers.Element.hasClass(element, "olAlphaImg")) { element = element.parentNode; } @@ -135,16 +117,19 @@ OpenLayers.Events.buttonclick = OpenLayers.Class({ if (this.cancelRegEx.test(evt.type)) { delete this._buttonStarted; } - OpenLayers.Event.stop(evt, false, true); + OpenLayers.Event.stop(evt, false); + propagate = false; } if (this.startRegEx.test(evt.type)) { this._buttonStarted = true; - OpenLayers.Event.stop(evt, false, true); + OpenLayers.Event.stop(evt, false); + propagate = false; } } else { delete this._buttonStarted; } } + return propagate; } }); \ No newline at end of file diff --git a/tests/Events.html b/tests/Events.html index 485c53818f..cd3b04d42a 100644 --- a/tests/Events.html +++ b/tests/Events.html @@ -30,6 +30,10 @@ var ev = { 'object': {}, + 'extensionCount': { + 'listenerA': 0, + 'listenerB': 0 + }, 'listeners': { 'listenerA': { 'push': function(options){ diff --git a/tests/Events/buttonclick.html b/tests/Events/buttonclick.html index d03205e68f..ab0c0777d5 100644 --- a/tests/Events/buttonclick.html +++ b/tests/Events/buttonclick.html @@ -13,7 +13,6 @@ button: 1, target: button }); - buttonClick._buttonClick(evt); events.handleBrowserEvent(evt); } function logEvent(evt) { @@ -22,7 +21,7 @@ function test_ButtonClick(t) { t.plan(2); - events = new OpenLayers.Events({}, document.getElementById("map")); + events = new OpenLayers.Events({}, element); buttonClick = new OpenLayers.Events.buttonclick({target: events}); t.ok(buttonClick.target === events, "target set from options argument"); buttonClick = new OpenLayers.Events.buttonclick(events);