mousewheelhandler_test.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. // Copyright 2009 The Closure Library Authors. All Rights Reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS-IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. goog.provide('goog.events.MouseWheelHandlerTest');
  15. goog.setTestOnly('goog.events.MouseWheelHandlerTest');
  16. goog.require('goog.dom');
  17. goog.require('goog.events');
  18. goog.require('goog.events.BrowserEvent');
  19. goog.require('goog.events.MouseWheelEvent');
  20. goog.require('goog.events.MouseWheelHandler');
  21. goog.require('goog.functions');
  22. goog.require('goog.string');
  23. goog.require('goog.testing.PropertyReplacer');
  24. goog.require('goog.testing.events');
  25. goog.require('goog.testing.jsunit');
  26. goog.require('goog.userAgent');
  27. var log;
  28. var stubs = new goog.testing.PropertyReplacer();
  29. var DEFAULT_TYPE = 'mousewheel';
  30. var GECKO_TYPE = 'DOMMouseScroll';
  31. var HORIZONTAL = 'h';
  32. var VERTICAL = 'v';
  33. var mouseWheelEvent;
  34. var mouseWheelEventRtl;
  35. var mouseWheelHandler;
  36. var mouseWheelHandlerRtl;
  37. function setUpPage() {
  38. log = goog.dom.getElement('log');
  39. }
  40. function setUp() {
  41. stubs.remove(goog, 'userAgent');
  42. }
  43. function tearDown() {
  44. stubs.reset();
  45. goog.dispose(mouseWheelHandler);
  46. goog.dispose(mouseWheelHandlerRtl);
  47. mouseWheelHandlerRtl = null;
  48. mouseWheelHandler = null;
  49. mouseWheelEvent = null;
  50. mouseWheelEventRtl = null;
  51. }
  52. function tearDownPage() {
  53. // Create interactive demo.
  54. mouseWheelHandler = new goog.events.MouseWheelHandler(document.body);
  55. goog.events.listen(
  56. mouseWheelHandler, goog.events.MouseWheelHandler.EventType.MOUSEWHEEL,
  57. function(e) {
  58. log.innerHTML += goog.string.subs(
  59. '<br />(deltaX, deltaY): (%s, %s)', e.deltaX, e.deltaY);
  60. });
  61. }
  62. function testIeStyleMouseWheel() {
  63. goog.userAgent =
  64. {OPERA: false, EDGE_OR_IE: true, GECKO: false, WEBKIT: false};
  65. createHandlerAndListen();
  66. // Non-gecko, non-webkit events get wheelDelta divided by -40 to get detail.
  67. handleEvent(createFakeMouseWheelEvent(DEFAULT_TYPE, 120));
  68. assertMouseWheelEvent(-3, 0, -3);
  69. handleEvent(createFakeMouseWheelEvent(DEFAULT_TYPE, -120));
  70. assertMouseWheelEvent(3, 0, 3);
  71. handleEvent(createFakeMouseWheelEvent(DEFAULT_TYPE, 1200));
  72. assertMouseWheelEvent(-30, 0, -30);
  73. }
  74. function testNullBody() {
  75. goog.userAgent = {OPERA: false, IE: true, GECKO: false, WEBKIT: false};
  76. var documentObjectWithNoBody = {};
  77. goog.testing.events.mixinListenable(documentObjectWithNoBody);
  78. mouseWheelHandler =
  79. new goog.events.MouseWheelHandler(documentObjectWithNoBody);
  80. }
  81. function testGeckoStyleMouseWheel() {
  82. goog.userAgent = {OPERA: false, IE: false, GECKO: true, WEBKIT: false};
  83. createHandlerAndListen();
  84. handleEvent(createFakeMouseWheelEvent(GECKO_TYPE, null, 3));
  85. assertMouseWheelEvent(3, 0, 3);
  86. handleEvent(createFakeMouseWheelEvent(GECKO_TYPE, null, -12));
  87. assertMouseWheelEvent(-12, 0, -12);
  88. // Really big values should get truncated to +-3.
  89. handleEvent(createFakeMouseWheelEvent(GECKO_TYPE, null, 1200));
  90. assertMouseWheelEvent(3, 0, 3);
  91. handleEvent(createFakeMouseWheelEvent(GECKO_TYPE, null, -1200));
  92. assertMouseWheelEvent(-3, 0, -3);
  93. // Test scrolling with the additional axis property.
  94. handleEvent(createFakeMouseWheelEvent(GECKO_TYPE, null, 3, VERTICAL));
  95. assertMouseWheelEvent(3, 0, 3);
  96. handleEvent(createFakeMouseWheelEvent(GECKO_TYPE, null, 3, HORIZONTAL));
  97. assertMouseWheelEvent(3, 3, 0);
  98. handleEvent(createFakeMouseWheelEvent(GECKO_TYPE, null, -3, HORIZONTAL));
  99. assertMouseWheelEvent(-3, -3, 0);
  100. }
  101. function testWebkitStyleMouseWheel_ieStyle() {
  102. goog.userAgent =
  103. {OPERA: false, IE: false, GECKO: false, WEBKIT: true, WINDOWS: true};
  104. createHandlerAndListen();
  105. // IE-style Webkit events get wheelDelta divided by -40 to get detail.
  106. handleEvent(createFakeWebkitMouseWheelEvent(-40, 0));
  107. assertMouseWheelEvent(1, 1, 0);
  108. handleEvent(createFakeWebkitMouseWheelEvent(120, 0));
  109. assertMouseWheelEvent(-3, -3, 0);
  110. handleEvent(createFakeWebkitMouseWheelEvent(0, 120));
  111. assertMouseWheelEvent(-3, 0, -3);
  112. handleEvent(createFakeWebkitMouseWheelEvent(0, -40));
  113. assertMouseWheelEvent(1, 0, 1);
  114. handleEvent(createFakeWebkitMouseWheelEvent(80, -40));
  115. assertMouseWheelEvent(-2, -2, 1);
  116. }
  117. function testWebkitStyleMouseWheel_ieStyleOnLinux() {
  118. goog.userAgent = {
  119. OPERA: false,
  120. IE: false,
  121. GECKO: false,
  122. WEBKIT: true,
  123. WINDOWS: false,
  124. LINUX: true
  125. };
  126. runWebKitContinuousAndDiscreteEventsTest();
  127. }
  128. function testWebkitStyleMouseWheel_ieStyleOnMac() {
  129. goog.userAgent = {
  130. OPERA: false,
  131. IE: false,
  132. GECKO: false,
  133. WEBKIT: true,
  134. WINDOWS: false,
  135. MAC: true
  136. };
  137. runWebKitContinuousAndDiscreteEventsTest();
  138. }
  139. function runWebKitContinuousAndDiscreteEventsTest() {
  140. goog.userAgent.isVersionOrHigher = goog.functions.TRUE;
  141. createHandlerAndListen();
  142. // IE-style wheel events.
  143. handleEvent(createFakeWebkitMouseWheelEvent(0, -40));
  144. assertMouseWheelEvent(1, 0, 1);
  145. handleEvent(createFakeWebkitMouseWheelEvent(80, -40));
  146. assertMouseWheelEvent(-2, -2, 1);
  147. // Even in Webkit versions that usually behave in IE style, sometimes wheel
  148. // events don't behave; this has been observed for instance with Macbook
  149. // and Chrome OS touchpads in Webkit 534.10+.
  150. handleEvent(createFakeWebkitMouseWheelEvent(-3, 5));
  151. assertMouseWheelEvent(-5, 3, -5);
  152. handleEvent(createFakeWebkitMouseWheelEvent(4, -7));
  153. assertMouseWheelEvent(7, -4, 7);
  154. }
  155. function testWebkitStyleMouseWheel_nonIeStyle() {
  156. goog.userAgent =
  157. {OPERA: false, IE: false, GECKO: false, WEBKIT: true, WINDOWS: false};
  158. goog.userAgent.isVersionOrHigher = goog.functions.FALSE;
  159. createHandlerAndListen();
  160. // non-IE-style Webkit events do not get wheelDelta scaled
  161. handleEvent(createFakeWebkitMouseWheelEvent(-40, 0));
  162. assertMouseWheelEvent(1, 1, 0);
  163. handleEvent(createFakeWebkitMouseWheelEvent(120, 0));
  164. assertMouseWheelEvent(-3, -3, 0);
  165. handleEvent(createFakeWebkitMouseWheelEvent(0, 120));
  166. assertMouseWheelEvent(-3, 0, -3);
  167. handleEvent(createFakeWebkitMouseWheelEvent(0, -40));
  168. assertMouseWheelEvent(1, 0, 1);
  169. handleEvent(createFakeWebkitMouseWheelEvent(80, -40));
  170. assertMouseWheelEvent(-2, -2, 1);
  171. }
  172. function testMaxDeltaX() {
  173. goog.userAgent =
  174. {OPERA: false, IE: false, GECKO: false, WEBKIT: true, WINDOWS: true};
  175. createHandlerAndListen();
  176. // IE-style Webkit events get wheelDelta divided by -40 to get detail.
  177. handleEvent(createFakeWebkitMouseWheelEvent(-120, 0));
  178. assertMouseWheelEvent(3, 3, 0);
  179. mouseWheelHandler.setMaxDeltaX(3);
  180. mouseWheelHandlerRtl.setMaxDeltaX(3);
  181. handleEvent(createFakeWebkitMouseWheelEvent(-120, 0));
  182. assertMouseWheelEvent(3, 3, 0);
  183. mouseWheelHandler.setMaxDeltaX(2);
  184. mouseWheelHandlerRtl.setMaxDeltaX(2);
  185. handleEvent(createFakeWebkitMouseWheelEvent(-120, 0));
  186. assertMouseWheelEvent(3, 2, 0);
  187. handleEvent(createFakeWebkitMouseWheelEvent(0, -120));
  188. assertMouseWheelEvent(3, 0, 3);
  189. }
  190. function testMaxDeltaY() {
  191. goog.userAgent =
  192. {OPERA: false, IE: false, GECKO: false, WEBKIT: true, WINDOWS: true};
  193. createHandlerAndListen();
  194. // IE-style Webkit events get wheelDelta divided by -40 to get detail.
  195. handleEvent(createFakeWebkitMouseWheelEvent(0, -120));
  196. assertMouseWheelEvent(3, 0, 3);
  197. mouseWheelHandler.setMaxDeltaY(3);
  198. mouseWheelHandlerRtl.setMaxDeltaY(3);
  199. handleEvent(createFakeWebkitMouseWheelEvent(0, -120));
  200. assertMouseWheelEvent(3, 0, 3);
  201. mouseWheelHandler.setMaxDeltaY(2);
  202. mouseWheelHandlerRtl.setMaxDeltaY(2);
  203. handleEvent(createFakeWebkitMouseWheelEvent(0, -120));
  204. assertMouseWheelEvent(3, 0, 2);
  205. handleEvent(createFakeWebkitMouseWheelEvent(-120, 0));
  206. assertMouseWheelEvent(3, 3, 0);
  207. }
  208. // Be sure to call this after setting up goog.userAgent mock and not before.
  209. function createHandlerAndListen() {
  210. mouseWheelHandler =
  211. new goog.events.MouseWheelHandler(goog.dom.getElement('foo'));
  212. goog.events.listen(
  213. mouseWheelHandler, goog.events.MouseWheelHandler.EventType.MOUSEWHEEL,
  214. function(e) { mouseWheelEvent = e; });
  215. mouseWheelHandlerRtl =
  216. new goog.events.MouseWheelHandler(goog.dom.getElement('fooRtl'));
  217. goog.events.listen(
  218. mouseWheelHandlerRtl, goog.events.MouseWheelHandler.EventType.MOUSEWHEEL,
  219. function(e) { mouseWheelEventRtl = e; });
  220. }
  221. function handleEvent(event) {
  222. mouseWheelHandler.handleEvent(event);
  223. mouseWheelHandlerRtl.handleEvent(event);
  224. }
  225. function assertMouseWheelEvent(expectedDetail, expectedDeltaX, expectedDeltaY) {
  226. assertTrue('event should be non-null', !!mouseWheelEvent);
  227. assertTrue(
  228. 'event should have correct JS type',
  229. mouseWheelEvent instanceof goog.events.MouseWheelEvent);
  230. assertEquals(
  231. 'event should have correct detail property', expectedDetail,
  232. mouseWheelEvent.detail);
  233. assertEquals(
  234. 'event should have correct deltaX property', expectedDeltaX,
  235. mouseWheelEvent.deltaX);
  236. assertEquals(
  237. 'event should have correct deltaY property', expectedDeltaY,
  238. mouseWheelEvent.deltaY);
  239. // RTL
  240. assertTrue('event should be non-null', !!mouseWheelEventRtl);
  241. assertTrue(
  242. 'event should have correct JS type',
  243. mouseWheelEventRtl instanceof goog.events.MouseWheelEvent);
  244. assertEquals(
  245. 'event should have correct detail property', expectedDetail,
  246. mouseWheelEventRtl.detail);
  247. assertEquals(
  248. 'event should have correct deltaX property', -expectedDeltaX,
  249. mouseWheelEventRtl.deltaX);
  250. assertEquals(
  251. 'event should have correct deltaY property', expectedDeltaY,
  252. mouseWheelEventRtl.deltaY);
  253. }
  254. function createFakeMouseWheelEvent(
  255. type, opt_wheelDelta, opt_detail, opt_axis, opt_wheelDeltaX,
  256. opt_wheelDeltaY) {
  257. var event = {
  258. type: type,
  259. wheelDelta: goog.isDef(opt_wheelDelta) ? opt_wheelDelta : undefined,
  260. detail: goog.isDef(opt_detail) ? opt_detail : undefined,
  261. axis: opt_axis || undefined,
  262. wheelDeltaX: goog.isDef(opt_wheelDeltaX) ? opt_wheelDeltaX : undefined,
  263. wheelDeltaY: goog.isDef(opt_wheelDeltaY) ? opt_wheelDeltaY : undefined,
  264. // These two are constants defined on the event in FF3.1 and later.
  265. // It doesn't matter exactly what they are, and it doesn't affect
  266. // our simulations of other browsers.
  267. HORIZONTAL_AXIS: HORIZONTAL,
  268. VERTICAL_AXIS: VERTICAL
  269. };
  270. return new goog.events.BrowserEvent(event);
  271. }
  272. function createFakeWebkitMouseWheelEvent(wheelDeltaX, wheelDeltaY) {
  273. return createFakeMouseWheelEvent(
  274. DEFAULT_TYPE,
  275. Math.abs(wheelDeltaX) > Math.abs(wheelDeltaY) ? wheelDeltaX : wheelDeltaY,
  276. undefined, undefined, wheelDeltaX, wheelDeltaY);
  277. }