Skip to content

Loading…

[event] Add `wheel` event #1556

Open
wants to merge 5 commits into from

2 participants

@juandopazo
YUI Library member

This PR modifies the mousewheel and adds a wheel event (basically mousewheel becomes an alias of wheel) that matches the W3C spec.

The wheel event has a deltaY payload that requires some math to get right across browsers. But simulating the event would require to do the math in the reverse order if I wanted to make an assertion over it. Does it make sense to do that or should I not test deltaY?

I'm sending the PR to get some early feedback. I still need to:

  • Figure out why tests fail in Phantomjs
  • Update the User Guide
  • Add manual test
  • Test in older browsers
@triptych

@juandopazo would this need to be updated/modified if @tilomitra adds Hammer.js ?

@juandopazo
YUI Library member

@triptych I don't think Hammer.js covers the wheel event.

@triptych

Yes, but since the api may change, would that mean you'll need to update this code to be compatible. @juandopazo

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Jan 9, 2014
  1. @juandopazo
Commits on Jan 13, 2014
  1. @juandopazo
Commits on Jan 14, 2014
  1. @juandopazo
  2. @juandopazo
Commits on Jan 15, 2014
  1. @juandopazo
View
96 src/event/js/mousewheel.js
@@ -4,42 +4,74 @@
* @submodule event-mousewheel
*/
var DOM_MOUSE_SCROLL = 'DOMMouseScroll',
- fixArgs = function(args) {
- var a = Y.Array(args, 0, true), target;
- if (Y.UA.gecko) {
- a[0] = DOM_MOUSE_SCROLL;
- target = Y.config.win;
- } else {
- target = Y.config.doc;
+ win = Y.config.win,
+ doc = Y.config.doc,
+ eventDef = {
+ detach: function (node, sub) {
+ sub._handle.detach();
+ },
+ _createFacade: function (domEvent, node, deltaY) {
+ var facade = new Y.DOMEventFacade(domEvent, node);
+ facade.type = 'wheel';
+ facade.deltaX = 0;
+ facade.deltaY = deltaY;
+ facade.deltaZ = 0;
+ facade.deltaMode = 1;
+ return facade;
}
+ };
- if (a.length < 3) {
- a[2] = target;
- } else {
- a.splice(2, 0, target);
- }
+function attach() {
+ return Y.Event._attach(arguments, {
+ facade: false
+ });
+}
- return a;
+if (win.WheelEvent) {
+ eventDef.on = function (node, sub, notifier) {
+ var self = this;
+ sub._handle = attach('wheel', function (domEvent) {
+ notifier.fire(self._createFacade(domEvent, node, domEvent.deltaY));
+ }, win);
+ };
+} else if ('onmousewheel' in doc) {
+ eventDef.on = function (node, sub, notifier) {
+ var self = this;
+ sub._handle = attach('mousewheel', function (domEvent) {
+ notifier.fire(self._createFacade(domEvent, node,
+ - 1/40 * ('wheelDeltaX' in domEvent ? domEvent.wheelDeltaX : domEvent.wheelDelta)));
+ }, doc);
+ };
+} else {
+ eventDef.on = function (node, sub, notifier) {
+ var self = this;
+ sub._handle = attach('MozMousePixelScroll', function (domEvent) {
+ notifier.fire(self._createFacade(domEvent, node, domEvent.detail));
+ }, win);
};
+}
/**
- * Mousewheel event. This listener is automatically attached to the
- * correct target, so one should not be supplied. Mouse wheel
- * direction and velocity is stored in the 'wheelDelta' field.
- * @event mousewheel
- * @param type {string} 'mousewheel'
- * @param fn {function} the callback to execute
- * @param context optional context object
- * @param args 0..n additional arguments to provide to the listener.
- * @return {EventHandle} the detach handle
- * @for YUI
- */
-Y.Env.evt.plugins.mousewheel = {
- on: function() {
- return Y.Event._attach(fixArgs(arguments));
- },
+Mousewheel event. Alias for the `wheel` event
+
+@event mousewheel
+@for YUI
+@see wheel
+@param {String} type Set to `'wheel'`.
+**/
+Y.Event.define('mousewheel', eventDef, true);
+
+/**
+The W3C `wheel` event. This listener is automatically attached to the correct
+target, so one should not be supplied/
- detach: function() {
- return Y.Event.detach.apply(Y.Event, fixArgs(arguments));
- }
-};
+@event wheel
+@for YUI
+@param {Number} deltaX Set to 0.
+@param {Number} deltaY Expected amount that the page will scroll along the
+ y-axis according to the deltaMode units.
+@param {Number} deltaZ Set to 0.
+@param {Number} deltaMode Set to 1. Unit indicator (pixels, lines, or pages) for
+ the deltaY attribute.
+**/
+Y.Event.define('wheel', eventDef, true);
View
2 src/event/meta/event.json
@@ -53,7 +53,7 @@
},
"event-mousewheel": {
"requires": [
- "node-base"
+ "event-synthetic"
]
},
"event-resize": {
View
23 src/event/tests/manual/wheel.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <title>Wheel Event Tests</title>
+ <link rel="stylesheet" type="text/css" href="../../../../build/cssnormalize/cssnormalize-min.css">
+</head>
+<body class="yui3-skin-sam">
+ <h1>Wheel Event Tests</h1>
+ <script type="text/javascript" src="../../../../build/yui/yui.js"></script>
+ <script type="text/javascript">
+YUI({
+ filter: 'raw'
+}).use('event', 'console', function (Y) {
+ new Y.Console().render();
+
+ Y.on('wheel', function (e) {
+ Y.log('wheel event - deltaY = ' + e.deltaY, 'info', 'event-mousewheel');
+ });
+});
+ </script>
+</body>
+</html>
View
2 src/event/tests/unit/assets/mousewheel-tests.js
@@ -13,6 +13,8 @@ YUI.add('mousewheel-tests', function(Y) {
}
}));
+ Y.MouseWheelSuite = suite;
+
Y.Test.Runner.add(suite);
});
View
147 src/event/tests/unit/assets/wheel-tests.js
@@ -0,0 +1,147 @@
+YUI.add('wheel-tests', function (Y) {
+
+ var win = Y.config.win,
+ doc = Y.config.doc,
+ Assert = Y.Assert,
+ node = Y.one('#tester'),
+ domNode = node.getDOMNode();
+
+ var createWheelEvent;
+
+ // Chrome
+ if ((function () {
+ try {
+ return !!doc.createEvent('WheelEvent').initWebKitWheelEvent;
+ } catch (e) {
+ return false;
+ }
+ }())) {
+ createWheelEvent = function (deltaY) {
+ var evt = doc.createEvent('WheelEvent');
+ evt.initWebKitWheelEvent(
+ 0, /* deltaX*/
+ -deltaY, /* deltaY */
+ window, /* view */
+ 0, /* screenX */
+ 0, /* screenY */
+ 0, /* clientX */
+ 0, /* clientY */
+ false, /* ctrlKey */
+ false, /* altKey */
+ false, /* shiftKey */
+ false /* metaKey */);
+ return evt;
+ };
+ // Modern IE
+ } else if ((function () {
+ try {
+ return !!doc.createEvent('WheelEvent').initWheelEvent;
+ } catch (e) {
+ return false;
+ }
+ }())) {
+ createWheelEvent = function (deltaY) {
+ var evt = doc.createEvent('WheelEvent');
+ evt.initWheelEvent('wheel', /* type */
+ true, /* bubbles */
+ true, /* cancelable */
+ window, /* view */
+ 0, /* detail */
+ 1, /* screenX */
+ 2, /* screenY */
+ 3, /* clientX */
+ 4, /* clientY */
+ 5, /* button */
+ null, /* relatedTarget */
+ "", /* modifiers */
+ 6, /* deltaX*/
+ 7, /* deltaY */
+ 8, /* deltaZ*/
+ 9 /* deltaMode */ );
+ return evt;
+ };
+ } else if (doc.createEventObject) {
+ createWheelEvent = function (deltaY) {
+ var evt = doc.createEventObject();
+ evt.type = 'wheelevent';
+ return evt;
+ };
+ } else {
+ createWheelEvent = function (deltaY) {
+ var evt = doc.createEvent('MouseScrollEvents');
+ evt.initMouseEvent('wheel', /* type */
+ true, /* bubbles */
+ true, /* cancelable */
+ window, /* view */
+ 0, /* detail */
+ 0, /* screenX */
+ 0, /* screenY */
+ 0, /* clientX */
+ 0, /* clientY */
+ false, /* ctrlKey */
+ false, /* altKey */
+ false, /* shiftKey */
+ false, /* metaKey */
+ 0, /* button */
+ null /* related target */
+ );
+ return evt;
+ };
+ }
+
+ Y.MouseWheelSuite.add(new Y.Test.Case({
+ name: 'W3C wheel event',
+
+ _should: {
+ ignore: {
+ 'test wheel implementation': !win.WheelEvent,
+ 'test mousewheel implementation': !!win.WheelEvent
+ }
+ },
+
+ // Modern IE
+ 'test wheel implementation': function () {
+ var deltaY = 50,
+ mouseEvent = createWheelEvent(deltaY),
+ test = this;
+
+ node.once('wheel', function (e) {
+ test.resume(function () {
+ Assert.areSame(0, e.deltaX, 'Wrong deltaX event payloed');
+ Assert.areSame(0, e.deltaZ, 'Wrong deltaZ event payloed');
+ Assert.areSame(1, e.deltaMode, 'Wrong deltaMode event payloed');
+ });
+ });
+
+ setTimeout(function () {
+ domNode.dispatchEvent(mouseEvent);
+ }, 0);
+
+ test.wait();
+ },
+
+ 'test mousewheel implementation': function () {
+ var mouseEvent = createWheelEvent(50),
+ test = this;
+
+ node.once('wheel', function (e) {
+ test.resume(function () {
+ Assert.areSame(0, e.deltaX, 'Wrong deltaX event payloed');
+ Assert.areSame(0, e.deltaZ, 'Wrong deltaZ event payloed');
+ Assert.areSame(1, e.deltaMode, 'Wrong deltaMode event payloed');
+ });
+ });
+
+ setTimeout(function () {
+ if (domNode.dispatchEvent) {
+ domNode.dispatchEvent(mouseEvent);
+ } else {
+ domNode.fireEvent('onmousewheel', mouseEvent);
+ }
+ }, 0);
+
+ test.wait();
+ }
+ }));
+
+});
View
6 src/event/tests/unit/event-mousewheel.html
@@ -18,9 +18,13 @@
'mousewheel-tests': {
fullpath: './assets/mousewheel-tests.js',
requires: [ 'event-mousewheel', 'test-console', 'test' ]
+ },
+ 'wheel-tests': {
+ fullpath: './assets/wheel-tests.js',
+ requires: ['mousewheel-tests']
}
}
-}).use('mousewheel-tests', function(Y) {
+}).use('wheel-tests', function(Y) {
(new Y.Test.Console()).render('#log');
Y.Test.Runner.setName('Event: Mousewheel');
Something went wrong with that request. Please try again.