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 [email protected]
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
-~----------~----~----~----~------~----~------~--~---

Reply via email to