From 0b50073df6daef1fe2160da1608d2193ae1dc8e6 Mon Sep 17 00:00:00 2001 From: sporritt Date: Fri, 3 Jan 2014 15:23:01 +1100 Subject: [PATCH] improved event handler registration (dont use the functions toString method) for old ie --- html/index-dom.html | 2 +- index.html | 369 ++++++++++++++++++++++++++++++++++++++++++-- js/mottle-0.2.js | 29 ++-- 3 files changed, 377 insertions(+), 23 deletions(-) diff --git a/html/index-dom.html b/html/index-dom.html index 3bd64c9..d034ede 100644 --- a/html/index-dom.html +++ b/html/index-dom.html @@ -286,7 +286,7 @@

Event Triggering

Mottle.consume(e); } debug.innerHTML = msg; - if (typeof console != "undefined") console.log(e); + //if (typeof console != "undefined") console.log(e); fn && fn(e, msg, debug); }; }; diff --git a/index.html b/index.html index 3c148ed..caba2a1 100644 --- a/index.html +++ b/index.html @@ -1,17 +1,366 @@ - + + - +
+ <- back to index +

Mottle

+

+ Mottle is a lightweight browser event manager. It was originally written to support jsPlumb 1.6.0, but is independent of jsPlumb and may be useful for other + projects. Its main features are: +

+

+

+ Mottle has no external dependencies and works with all desktop browsers from IE6 up, as well as mobile browsers on Apple and Android devices. +

+
+

Basic Events

+

+ This element uses Mottle to register listeners for `mousedown`, `mouseup`, `click`, `dblclick`, `mousemove`, `mouseover`, `mouseout` and `contextmenu`. Note that you won't + see any `mouseup` events appearing in the debug pane when you left-click, as the `click` event is fired immediately thereafter. If you right-click, though, + you will first see a `contextmenu` event, followed by a `mouseup` event. +

+

Note also in this element if you press the mouse button, then move the mouse before releasing + the button, a `click` event is posted. This is the default behaviour of all browsers, but can be + suppressed using Mottle's "smartClick" functionality - see below. +

+

Click 'Unbind Events' to do what the name suggests.

+ + +
+
+ +
+
+
+var m = new Mottle();
+m.on("basicEvents", "mousedown", function() { ... });
+m.on("basicEvents", "mouseup", function() { ... });
+m.on("basicEvents", "click", function() { ... });
+m.on("basicEvents", "dblclick", function() { ... });
+m.on("basicEvents", "mousemove", function() { ... });
+m.on("basicEvents", "mouseover", function() { ... });
+m.on("basicEvents", "mouseout", function() { ... });
+m.on("basicEvents", "contextmenu", function() { ... });
+
+
+ +

Smart Clicks

+ In this demo, we are using the "smart click" functionality to suppress click events if the + user's mouse has moved between the `mousedown` and `mouseup` events. +
+
+ +
+
+
+var m = new Mottle({ smartClicks:true });
+m.on("smartClick", "click", function() { ... });
+
+
+ +

Event Delegation

+ As well as basic event handler binding, Mottle offers event delegation - the ability to bind a listener to some parent element and associate that listener with + a selector that identifies appropriate descendants of the element to which to respond. +

+ The element is configured to use Mottle's event delegation to bind the `click` and `contextmenu` events to the + element's children. +

+ +
+
1
+
2
+
3
+
4
+
5
+
+ +
+
+
+var m = new Mottle();
+m.on("eventDelegation", ".foo,.baz,.bar", "click", function() { ... });
+m.on("eventDelegation", ".foo,.baz,.bar", "contextmenu", function() { ... });
+
+
+ +

Mouseenter/mouseexit

+ Mouseenter and mousexit are proprietary Internet Explorer events that are kind of useful, and for that reason Mottle offers a wrapper for them in other + browsers. The basic concept is that the event only fires when the mouse enters or exits the exact element on which the listener was bound. This differs from + the mousemove/mouseout events, which are fired on some element regardless of whether the event occurred on that specific element or one of its descendants. +

A listener is bound to the mouseenter and mouseexit events on the element below. A single `mouseenter` event is fired when the mouse first + enters the event, and no more events are fired until the mouse exits the bounds of the event, at which time a `mouseexit` event is fired. +

+

Note: this doesn't do anything on touch devices - there is no related concept.

+
+
INNER
+
+ +
+
+
+var m = new Mottle();
+m.on("mouseEnterExit", "mouseenter", function() { ... });
+m.on("mouseEnterExit", "mouseexit", function() { ... });
+
+
+ +

Event Delegation + Mouseenter/mouseexit

+ Here we are mixing the `mouseenter` and `mouseexit` event wrappers with event delegation: the element + is registered as the delegate for the `mouseenter` and `mouseexit` events from the child elements inside. +

Note: this doesn't do anything on touch devices - there is no related concept.

+
+
1
+
2
+
3
+
4
+
5
+
+ +
+
+
+var m = new Mottle();
+m.on("mouseEnterExitDelegation", ".foo,.bar,.baz", "mouseenter", function() { ... });
+m.on("mouseEnterExitDelegation", ".foo,.bar,.baz", "mouseexit", function() { ... });
+
+
+ +

Event Delegation + Smart Clicks

+ Here we are mixing the smart click functionality with event delegation: the element + is registered as the delegate for the `click` and `contextmenu` events from the child + elements inside. +
+
1
+
2
+
3
+
4
+
5
+
+ +
+
+
+var m = new Mottle({smartClicks:true});
+m.on("smartClickDelegation", ".foo,.bar,.baz", "click", function() { ... });
+m.on("smartClickDelegation", ".foo,.bar,.baz", "contextmenu", function() { ... });
+
+
+ +

Event Triggering

+ We register a `dblclick` listener on the main element. When you press the Trigger button, a `dblclick` event is triggered. Click + on the element itself to clear the message. +
+
+ + +
+
+
+var m = new Mottle();
+m.on("triggering", "dblclick", function() { ...write the message... });
+m.on("triggering", "click", function() { ...clear the message... });
+m.on("triggering", "button.trigger", "click", function(e) {
+	m.trigger("triggering", "dblclick", e);
+});
+
+
+ + +
+ + + + + \ No newline at end of file diff --git a/js/mottle-0.2.js b/js/mottle-0.2.js index c18bc80..e59dfe6 100644 --- a/js/mottle-0.2.js +++ b/js/mottle-0.2.js @@ -203,9 +203,6 @@ var isTouchDevice = "ontouchstart" in document.documentElement, isMouseDevice = "onmousedown" in document.documentElement, - downEvent = isTouchDevice ? "touchstart" : "mousedown", - upEvent = isTouchDevice ? "touchend" : "mouseup", - moveEvent = isTouchDevice ? "touchmove" : "mousemove", touchMap = { "mousedown":"touchstart", "mouseup":"touchend", "mousemove":"touchmove" }, click="click", dblclick="dblclick",contextmenu="contextmenu", touchstart="touchstart",touchend="touchend",touchmove="touchmove", @@ -248,19 +245,27 @@ if (obj.addEventListener) obj.addEventListener( type, fn, false ); else if (obj.attachEvent) { - obj["e"+type+fn] = fn; - obj[type+fn] = function() { obj["e"+type+fn]( window.event ); } - obj.attachEvent( "on"+type, obj[type+fn] ); + + var key = type + fn.__tauid; + obj["e" + key] = fn; + // TODO look at replacing with .call(..) + obj[key] = function() { obj["e"+key]( window.event ); } + obj.attachEvent( "on"+type, obj[key] ); } }, _unbind = function( obj, type, fn) { + // it has been bound if there is a tauid. otherwise it was not bound and we + // can ignore it. _unstore(obj, type, fn); - if (obj.removeEventListener) - obj.removeEventListener( type, fn, false ); - else if (obj.detachEvent) { - obj.detachEvent( "on"+type, obj[type+fn] ); - obj[type+fn] = null; - obj["e"+type+fn] = null; + if (fn.__tauid != null) { + if (obj.removeEventListener) + obj.removeEventListener( type, fn, false ); + else if (obj.detachEvent) { + var key = type + fn.__tauid; + obj[key] && obj.detachEvent( "on"+type, obj[key] ); + obj[key] = null; + obj["e"+key] = null; + } } }, _devNull = function() {};