Thanks! I'll apply this patch shortly to the svn repository. It will be committed in parts, separating the actual mouse wheel stuff from code fixing other issues in signal(), etc.
One question though. I see that the Mozilla "event.details" value is considered equivalent to "-event.wheelDelta / 40". But where does this magic number 40 come from? I see from MSDN that wheelDelta is always returned in multiples of 120. Is this just assuming that a wheel event always scrolls 3 lines? Cheers, /Per On Tue, Jun 3, 2008 at 8:55 AM, [EMAIL PROTECTED] <[EMAIL PROTECTED]> wrote: > > Below is a patch for adding mousewheel handling to mochikit. It has > been made against SVN 1383. > > It contains changes to Signal.js and some demo pages that end up in > examples. > > My main need for this is to try and suppress the scrolling of a page > after the contents of a div have been fully scrolled. The example > manages to do this for FF but fails in IE if you scroll quickly > enough. If anybody has any ideas on how to make this work reliably in > IE I'd love to hear about it. > > This patch makes no attempt at making all of the signal handling late > bound (as mentioned in by Per in a previous message), it just > refactors Signal.connect a bit to create custom handlers for mouse > wheel events and for the existing mouseenter/leave stuff. > > - Sim > > > > diff -r 3354b0497e7a MochiKit/Signal.js > --- a/MochiKit/Signal.js Fri May 30 12:43:36 2008 +1000 > +++ b/MochiKit/Signal.js Tue Jun 03 16:45:16 2008 +1000 > @@ -63,7 +63,7 @@ > str += '}'; > } > } > - if (this.type() == 'mouseover' || this.type() == 'mouseout' > || > + if (this.type() == 'mouseover' || this.type() == 'mouseout' > || > this.type() == 'mouseenter' || this.type() == > 'mouseleave') { > str += ', relatedTarget(): ' + > repr(this.relatedTarget()); > } > @@ -94,6 +94,13 @@ > /** @id MochiKit.Signal.Event.prototype.target */ > target: function () { > return this._event.target || this._event.srcElement; > + }, > + > + wheelData: function() { > + if (! this._wheelData) { > + this._wheelData = this._event.detail ? this._event.detail * > -1 : this._event.wheelDelta / 40; > + } > + return this._wheelData; > }, > > _relatedTarget: null, > @@ -516,10 +523,10 @@ > if (sig === 'onload' || sig === 'onunload') { > return function (nativeEvent) { > obj[func].apply(obj, [new E(src, nativeEvent)]); > - > + > var ident = new MochiKit.Signal.Ident({ > source: src, signal: sig, objOrFunc: obj, > funcOrStr: func}); > - > + > MochiKit.Signal._disconnect(ident); > }; > } else { > @@ -531,10 +538,10 @@ > if (sig === 'onload' || sig === 'onunload') { > return function (nativeEvent) { > func.apply(obj, [new E(src, nativeEvent)]); > - > + > var ident = new MochiKit.Signal.Ident({ > source: src, signal: sig, objOrFunc: func}); > - > + > MochiKit.Signal._disconnect(ident); > }; > } else { > @@ -576,6 +583,69 @@ > }; > }, > > + _makeMouseEnterListener: function(self,src, sig, func, obj) { > + var listener = self._mouseEnterListener(src, sig.substr(2), > func, obj); > + self._addEventListener(src, > + (sig === "onmouseenter") ? > "onmouseover" : "onmouseout", > + listener ); > + return listener; > + }, > + > + _mouseWheelListener: function (src, sig, func, obj) { > + var E = MochiKit.Signal.Event; > + > + // return a closure that smooths over the differences between > browsers > + return function (nativeEvent) { > + var e = new E(src, nativeEvent); > + e.type = function () { return sig; }; > + > + // let the connected function deal with it > + if (typeof(func) == "string") { > + return obj[func].apply(obj, [e]); > + } else { > + return func.apply(obj, [e]); > + } > + }; > + }, > + > + _makeMouseWheelListener: function (self,src,sig,func,obj) { > + var listener = self._mouseWheelListener(src, sig.substr(2), > func, obj); > + > + // takes care of IE, Opera, etc > + self._addEventListener(src, "onmousewheel", listener ); > + > + // Mozilla has a totally different name > + if (src.addEventListener) { > + src.addEventListener("DOMMouseScroll", listener, false); > + } > + return listener; > + }, > + > + _addEventListener: function(src, sig, listener) { > + if (src.addEventListener) { > + src.addEventListener(sig.substr(2), listener, false); > + } else if (src.attachEvent) { > + src.attachEvent(sig, listener); // useCapture unsupported > + } > + }, > + > + _makeDOMListener: function(self, src, sig, func, obj) { > + // simulated mouse event for those browsers that need it > + if ((sig === "onmouseenter" || sig === "onmouseleave") > + && !self._browserAlreadyHasMouseEnterAndLeave()) { > + return self._makeMouseEnterListener(self,src,sig,func,obj); > + } > + // special mouse wheel handling > + else if (sig === "onmousewheel") { > + return self._makeMouseWheelListener(self,src,sig,func,obj); > + } > + > + // default dom listener > + var listener = self._listener(src, sig, func, obj, true); > + self._addEventListener(src, sig, listener ); > + return listener; > + }, > + > _getDestPair: function (objOrFunc, funcOrStr) { > var obj = null; > var func = null; > @@ -613,32 +683,17 @@ > obj = src; > } > > - var isDOM = !!(src.addEventListener || src.attachEvent); > - if (isDOM && (sig === "onmouseenter" || sig === > "onmouseleave") > - && !self._browserAlreadyHasMouseEnterAndLeave()) { > - var listener = self._mouseEnterListener(src, > sig.substr(2), func, obj); > - if (sig === "onmouseenter") { > - sig = "onmouseover"; > - } else { > - sig = "onmouseout"; > - } > - } else { > - var listener = self._listener(src, sig, func, obj, > isDOM); > - } > - > - if (src.addEventListener) { > - src.addEventListener(sig.substr(2), listener, false); > - } else if (src.attachEvent) { > - src.attachEvent(sig, listener); // useCapture unsupported > - } > + var isDOM = !!(sig.substr(0,2) === "on" && > (src.addEventListener || src.attachEvent)); > + var listener = isDOM ? self._makeDOMListener(self, src, sig, > func, obj) : > + self._listener(src, sig, func, obj, false); > > var ident = new MochiKit.Signal.Ident({ > - source: src, > - signal: sig, > - listener: listener, > - isDOM: isDOM, > - objOrFunc: objOrFunc, > - funcOrStr: funcOrStr, > + source: src, > + signal: sig, > + listener: listener, > + isDOM: isDOM, > + objOrFunc: objOrFunc, > + funcOrStr: funcOrStr, > connected: true > }); > self._observers.push(ident); > diff -r 3354b0497e7a examples/mousewheel_events/index.html > --- /dev/null Thu Jan 01 00:00:00 1970 +0000 > +++ b/examples/mousewheel_events/index.html Tue Jun 03 16:45:16 2008 > +1000 > @@ -0,0 +1,85 @@ > +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" > + "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> > +<html xmlns="http://www.w3.org/1999/xhtml"> > +<head> > + <title>Mouse Wheel Events with MochiKit</title> > + <link href="mousewheel_events.css" rel="stylesheet" type="text/ > css" /> > + <script type="text/javascript" src="../../MochiKit/MochiKit.js"></ > script> > + <script type="text/javascript" src="mousewheel_events.js"></ > script> > +</head> > +<body> > + <h1> > + Mouse Wheel Events with MochiKit > + </h1> > + <p> > + For a detailed description of what happens under the hood, > check out > + <a href="mousewheel_events.js" class="view- > source">mousewheel_events.js</a>. > + </p> > + > + <p> > + View Source: [ > + <a href="index.html" class="view-source">index.html</a> | > + <a href="mousewheel_events.js" class="view- > source">mousewheel_events.js</a> | > + <a href="mousewheel_events.css" class="view- > source">mousewheel_events.css</a> > + ] > + </p> > + > + <div id="show-wheeldata" class="scroll-box">Scroll In Me: <span > id="show-wheeldata-ouput">0</span> (-3 for down, 3 for up)</div> > + > + <div id="scroll-page" class="scroll-box" style="height : 100px; > overflow : scroll;"> > + Scroll Me and then the page scrolls! <br /> > + Scroll Me and then the page scrolls! <br /> > + Scroll Me and then the page scrolls! <br /> > + Scroll Me and then the page scrolls! <br /> > + Scroll Me and then the page scrolls! <br /> > + Scroll Me and then the page scrolls! <br /> > + Scroll Me and then the page scrolls! <br /> > + Scroll Me and then the page scrolls! <br /> > + Scroll Me and then the page scrolls! <br /> > + Scroll Me and then the page scrolls! <br /> > + Scroll Me and then the page scrolls! <br /> > + Scroll Me and then the page scrolls! <br /> > + Scroll Me and then the page scrolls! <br /> > + Scroll Me and then the page scrolls! <br /> > + Scroll Me and then the page scrolls! <br /> > + Scroll Me and then the page scrolls! <br /> > + Scroll Me and then the page scrolls! <br /> > + Scroll Me and then the page scrolls! <br /> > + Scroll Me and then the page scrolls! <br /> > + Scroll Me and then the page scrolls! <br /> > + </div> > + > + <div id="no-scroll-page" class="scroll-box" style="height : > 100px; overflow : scroll;"> > + Scroll Me and then the page does not scroll! <br /> > + Scroll Me and then the page does not scroll! <br /> > + Scroll Me and then the page does not scroll! <br /> > + Scroll Me and then the page does not scroll! <br /> > + Scroll Me and then the page does not scroll! <br /> > + Scroll Me and then the page does not scroll! <br /> > + Scroll Me and then the page does not scroll! <br /> > + Scroll Me and then the page does not scroll! <br /> > + Scroll Me and then the page does not scroll! <br /> > + Scroll Me and then the page does not scroll! <br /> > + Scroll Me and then the page does not scroll! <br /> > + Scroll Me and then the page does not scroll! <br /> > + Scroll Me and then the page does not scroll! <br /> > + Scroll Me and then the page does not scroll! <br /> > + Scroll Me and then the page does not scroll! <br /> > + Scroll Me and then the page does not scroll! <br /> > + Scroll Me and then the page does not scroll! <br /> > + Scroll Me and then the page does not scroll! <br /> > + Scroll Me and then the page does not scroll! <br /> > + Scroll Me and then the page does not scroll! <br /> > + </div> > + > + <div class="padding">Ignore me I just make the page big enough to > require scrollbars.</div> > + <div class="padding">Ignore me I just make the page big enough to > require scrollbars.</div> > + <div class="padding">Ignore me I just make the page big enough to > require scrollbars.</div> > + <div class="padding">Ignore me I just make the page big enough to > require scrollbars.</div> > + <div class="padding">Ignore me I just make the page big enough to > require scrollbars.</div> > + <div class="padding">Ignore me I just make the page big enough to > require scrollbars.</div> > + <div class="padding">Ignore me I just make the page big enough to > require scrollbars.</div> > + <div class="padding">Ignore me I just make the page big enough to > require scrollbars.</div> > + <div class="padding">Ignore me I just make the page big enough to > require scrollbars.</div> > +</body> > +</html> > diff -r 3354b0497e7a examples/mousewheel_events/mousewheel_events.css > --- /dev/null Thu Jan 01 00:00:00 1970 +0000 > +++ b/examples/mousewheel_events/mousewheel_events.css Tue Jun 03 > 16:45:16 2008 +1000 > @@ -0,0 +1,17 @@ > +h1 { > + font-size: 2em; > + color: #4B4545; > + text-align: center; > +} > + > +div.scroll-box { > + border : 2px solid blue; > + padding : 4ex 4em; > + margin : 4ex 4em; > +} > + > +div.padding { > + padding : 4ex 4em; > + margin : 4ex 4em; > + border : 1px solid silver; > +}; > \ No newline at end of file > diff -r 3354b0497e7a examples/mousewheel_events/mousewheel_events.js > --- /dev/null Thu Jan 01 00:00:00 1970 +0000 > +++ b/examples/mousewheel_events/mousewheel_events.js Tue Jun 03 > 16:45:16 2008 +1000 > @@ -0,0 +1,56 @@ > +/* > + > + Mouse Events: Simple Mouse Scrolling Handlers > + > +*/ > + > +function showWheelData( event ) { > + getElement("show-wheeldata-ouput").innerHTML = event.wheelData(); > + event.stop(); > +}; > + > +function stopPageFromScrolling( event ) { > + var src = event.src(); > + var scrollTop = src.scrollTop; > + > + // While trying to stop scrolling events for IE, found that it > + // jumped around a bit. The following fudgetFactor is NOT the way > + // to handle this but was the best I could do with the limited > time > + // I had. > + var fudgeFactor = /MSIE/.test(navigator.userAgent) ? 25 : 0; > + > + // scrolling up > + if (event.wheelData() > 0) { > + // Following test should probably be "if (scrollTop == 0)" which > + // works in FF but not IE. > + if (scrollTop <= fudgeFactor) { > + event.stop(); > + } > + } > + //..scrolling down > + else { > + // Following test should be "if (scrollTop == src.scrollHeight - > src.clientHeight)", > + // see comment above. > + if (src.scrollHeight <= (scrollTop + src.clientHeight + > fudgeFactor)) { > + event.stop(); > + } > + } > +}; > + > +function connectMouseWheelEvents(){ > + connect("show-wheeldata", "onmousewheel", showWheelData); > + connect("no-scroll-page", "onmousewheel", stopPageFromScrolling); > +}; > + > +connect(window, 'onload', > + function() { > + connectMouseWheelEvents(); > + var elems = getElementsByTagAndClassName("A", "view- > source"); > + var page = "mousewheel_events/"; > + for (var i = 0; i < elems.length; i++) { > + var elem = elems[i]; > + var href = elem.href.split(/\//).pop(); > + elem.target = "_blank"; > + elem.href = "../view-source/view-source.html#" + page + > href; > + } > + }); > diff -r 3354b0497e7a tests/test_MochiKit-Signal.html > --- a/tests/test_MochiKit-Signal.html Fri May 30 12:43:36 2008 +1000 > +++ b/tests/test_MochiKit-Signal.html Tue Jun 03 16:45:16 2008 +1000 > @@ -4,26 +4,27 @@ > <script type="text/javascript" src="../MochiKit/Iter.js"></ > script> > <script type="text/javascript" src="../MochiKit/DOM.js"></script> > <script type="text/javascript" src="../MochiKit/Style.js"></ > script> > - <script type="text/javascript" src="../MochiKit/Signal.js"></ > script> > - <script type="text/javascript" src="../MochiKit/Logging.js"></ > script> > - <script type="text/javascript" src="SimpleTest/SimpleTest.js"></ > script> > + <script type="text/javascript" src="../MochiKit/Signal.js"></ > script> > + <script type="text/javascript" src="../MochiKit/Logging.js"></ > script> > + <script type="text/javascript" src="SimpleTest/SimpleTest.js"></ > script> > <link rel="stylesheet" type="text/css" href="SimpleTest/ > test.css"> > > </head> > <body> > > Please ignore this button: <input type="submit" id="submit" /><br /> > +Please ignore this button: <input type="submit" id="test" /><br /> > > <pre id="test"> > <script type="text/javascript" src="test_Signal.js"></script> > <script type="text/javascript"> > try { > - > + > tests.test_Signal({ok:ok, is:is}); > ok(true, "test suite finished!"); > - > + > } catch (err) { > - > + > var s = "test suite failure!\n"; > var o = {}; > var k = null; > > > > --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "MochiKit" group. To post to this group, send email to mochikit@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/mochikit?hl=en -~----------~----~----~----~------~----~------~--~---