Use event handling of OpenLayers.Event, not the native one.

Also includes some of the fixes suggested by @bartvde.
This commit is contained in:
ahocevar
2012-01-20 14:17:56 +01:00
parent 05de2b5109
commit e70569b2bb
4 changed files with 55 additions and 96 deletions
+35 -64
View File
@@ -157,16 +157,9 @@ OpenLayers.Event = {
* allowDefault - {Boolean} If true, we stop the event chain but * allowDefault - {Boolean} If true, we stop the event chain but
* still allow the default browser behaviour (text selection, * still allow the default browser behaviour (text selection,
* radio-button clicking, etc). Default is false. * radio-button clicking, etc). Default is false.
* terminate - {Boolean} If true, no more listeners registered through an
* <OpenLayers.Events> instance on the same event on the same element
* will receive this event. Extensions that call <stop> 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 (!allowDefault) {
if (event.preventDefault) { if (event.preventDefault) {
event.preventDefault(); event.preventDefault();
@@ -466,15 +459,21 @@ OpenLayers.Events = OpenLayers.Class({
* automatically instantiated when a listener is registered for an event * automatically instantiated when a listener is registered for an event
* provided by an extension. * provided by an extension.
* *
* Extesions are created in the <OpenLayers.Events> namespace using * Extensions are created in the <OpenLayers.Events> namespace using
* <OpenLayers.Class>, and named after the event they provide. * <OpenLayers.Class>, and named after the event they provide.
* The constructor recieves the target <OpenLayers.Events> instance as * The constructor receives the target <OpenLayers.Events> instance as
* argument. Extensions are expected to have an "observe" method, which is * argument. Extensions should register their browser events using
* called to register its sequence events on the target's dom element, * <register>, with {extension: true} as 4th argument. See
* using <OpenLayers.Event.observe>. See <OpenLayers.Events.buttonclick> * <OpenLayers.Events.buttonclick> for a reference implementation.
* for a reference implementation.
*/ */
extensions: null, extensions: null,
/**
* Property: extensionCount
* {Object} Keys are event types (like in <listeners>), values are the
* number of extension listeners for each event type.
*/
extensionCount: null,
/** /**
* Method: clearMouseListener * Method: clearMouseListener
@@ -504,6 +503,7 @@ OpenLayers.Events = OpenLayers.Class({
this.fallThrough = fallThrough; this.fallThrough = fallThrough;
this.listeners = {}; this.listeners = {};
this.extensions = {}; this.extensions = {};
this.extensionCount = {};
// if a dom element is specified, add a listeners list // if a dom element is specified, add a listeners list
// for browser events on the element and register them // for browser events on the element and register them
@@ -527,9 +527,7 @@ OpenLayers.Events = OpenLayers.Class({
*/ */
destroy: function () { destroy: function () {
for (var e in this.extensions) { for (var e in this.extensions) {
if (typeof this.extensions[e].destroy === "function") { this.extensions[e].destroy();
this.extensions[e].destroy();
}
} }
this.extensions = null; this.extensions = null;
if (this.element) { if (this.element) {
@@ -563,17 +561,8 @@ OpenLayers.Events = OpenLayers.Class({
* *
* Parameters: * Parameters:
* element - {HTMLDOMElement} a DOM element to attach browser events to * 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) { attachToElement: function (element) {
options = options || {};
if(this.element && !options.keepElement) {
OpenLayers.Event.stopObservingElement(this.element);
}
this.element = element; this.element = element;
for (var i = 0, len = this.BROWSER_EVENTS.length; i < len; i++) { for (var i = 0, len = this.BROWSER_EVENTS.length; i < len; i++) {
// register the event cross-browser // register the event cross-browser
@@ -585,33 +574,6 @@ OpenLayers.Events = OpenLayers.Class({
OpenLayers.Event.observe(element, "dragstart", OpenLayers.Event.stop); 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 * APIMethod: on
* Convenience method for registering listeners with a common scope. * Convenience method for registering listeners with a common scope.
@@ -669,16 +631,20 @@ OpenLayers.Events = OpenLayers.Class({
* Parameters: * Parameters:
* type - {String} Name of the event to register * type - {String} Name of the event to register
* obj - {Object} The object to bind the context to for the callback#. * obj - {Object} The object to bind the context to for the callback#.
* If no object is specified, default is the Events's * If no object is specified, default is the Events's 'object' property.
* 'object' property.
* func - {Function} The callback function. If no callback is * func - {Function} The callback function. If no callback is
* specified, this function does nothing. * specified, this function does nothing.
* priority - {Boolean} If true, adds the new listener to the *front* of * priority - {Boolean|Object} If true, adds the new listener to the
* the events queue instead of to the end. * *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) { register: function (type, obj, func, priority) {
if (type in OpenLayers.Events && !this.extensions[type]) { if (type in OpenLayers.Events && !this.extensions[type]) {
this.addExtension(type); this.extensions[type] = new OpenLayers.Events[type](this);
} }
if (func != null) { if (func != null) {
if (obj == null) { if (obj == null) {
@@ -688,11 +654,16 @@ OpenLayers.Events = OpenLayers.Class({
if (!listeners) { if (!listeners) {
listeners = []; listeners = [];
this.listeners[type] = listeners; this.listeners[type] = listeners;
this.extensionCount[type] = 0;
} }
var listener = {obj: obj, func: func};
if (priority) { 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 { } else {
listeners.push({obj: obj, func: func}); listeners.push(listener);
} }
} }
}, },
@@ -852,8 +823,8 @@ OpenLayers.Events = OpenLayers.Class({
*/ */
handleBrowserEvent: function (evt) { handleBrowserEvent: function (evt) {
var type = evt.type, listeners = this.listeners[type]; var type = evt.type, listeners = this.listeners[type];
if(!listeners || listeners.length == 0 || evt._terminated) { if(!listeners || listeners.length == 0) {
// noone's listening or event was terminated through <stop>, bail out // noone's listening, bail out
return; return;
} }
// add clientX & clientY to all events - corresponds to average x, y // add clientX & clientY to all events - corresponds to average x, y
+15 -30
View File
@@ -77,39 +77,20 @@ OpenLayers.Events.buttonclick = OpenLayers.Class({
} }
OpenLayers.Util.extend(this, options); 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) { for (var i=this.events.length-1; i>=0; --i) {
OpenLayers.Event.observe( this.target.register(this.events[i], this, this.buttonClick, {
this.target.element, this.events[i], this._buttonClick extension: true
); });
};
},
/**
* 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
);
} }
}, },
/** /**
* Method: destroy * Method: destroy
*/ */
destroy: function() { 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} * evt - {Event}
*/ */
buttonClick: function(evt) { buttonClick: function(evt) {
if (OpenLayers.Event.isLeftClick(evt) || !~evt.type.indexOf("mouse")) { var propagate = true,
var element = OpenLayers.Event.element(evt); element = OpenLayers.Event.element(evt);
if (element && (OpenLayers.Event.isLeftClick(evt) || !~evt.type.indexOf("mouse"))) {
if (OpenLayers.Element.hasClass(element, "olAlphaImg")) { if (OpenLayers.Element.hasClass(element, "olAlphaImg")) {
element = element.parentNode; element = element.parentNode;
} }
@@ -135,16 +117,19 @@ OpenLayers.Events.buttonclick = OpenLayers.Class({
if (this.cancelRegEx.test(evt.type)) { if (this.cancelRegEx.test(evt.type)) {
delete this._buttonStarted; delete this._buttonStarted;
} }
OpenLayers.Event.stop(evt, false, true); OpenLayers.Event.stop(evt, false);
propagate = false;
} }
if (this.startRegEx.test(evt.type)) { if (this.startRegEx.test(evt.type)) {
this._buttonStarted = true; this._buttonStarted = true;
OpenLayers.Event.stop(evt, false, true); OpenLayers.Event.stop(evt, false);
propagate = false;
} }
} else { } else {
delete this._buttonStarted; delete this._buttonStarted;
} }
} }
return propagate;
} }
}); });
+4
View File
@@ -30,6 +30,10 @@
var ev = { var ev = {
'object': {}, 'object': {},
'extensionCount': {
'listenerA': 0,
'listenerB': 0
},
'listeners': { 'listeners': {
'listenerA': { 'listenerA': {
'push': function(options){ 'push': function(options){
+1 -2
View File
@@ -13,7 +13,6 @@
button: 1, button: 1,
target: button target: button
}); });
buttonClick._buttonClick(evt);
events.handleBrowserEvent(evt); events.handleBrowserEvent(evt);
} }
function logEvent(evt) { function logEvent(evt) {
@@ -22,7 +21,7 @@
function test_ButtonClick(t) { function test_ButtonClick(t) {
t.plan(2); t.plan(2);
events = new OpenLayers.Events({}, document.getElementById("map")); events = new OpenLayers.Events({}, element);
buttonClick = new OpenLayers.Events.buttonclick({target: events}); buttonClick = new OpenLayers.Events.buttonclick({target: events});
t.ok(buttonClick.target === events, "target set from options argument"); t.ok(buttonClick.target === events, "target set from options argument");
buttonClick = new OpenLayers.Events.buttonclick(events); buttonClick = new OpenLayers.Events.buttonclick(events);