DraggingHandlesSpec.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. describe("Dragging handles tests", function() {
  2. var testSlider;
  3. var mouseEventArguments;
  4. var tickOffsets;
  5. // Create mouse events
  6. function mouseEvent(type, offset) {
  7. var ev = document.createEvent("MouseEvents");
  8. mouseEventArguments[0] = type;
  9. mouseEventArguments[7] = offset;
  10. ev.initMouseEvent.apply(ev, mouseEventArguments);
  11. return ev;
  12. }
  13. beforeEach(function() {
  14. // Create slider
  15. testSlider = new Slider(document.getElementById("testSlider1"), {
  16. ticks: [0, 1, 2, 3, 4, 5, 6],
  17. value: [4, 5],
  18. step: 1,
  19. range: true,
  20. });
  21. // Set up default set of mouse event arguments
  22. mouseEventArguments = [
  23. 'mousemove', // type
  24. true, // canBubble
  25. true, // cancelable
  26. document, // view,
  27. 0, // detail
  28. 0, // screenX
  29. 0, // screenY
  30. undefined, // clientX
  31. testSlider.sliderElem.offsetTop, // clientY,
  32. false, // ctrlKey
  33. false, // altKey
  34. false, // shiftKey
  35. false, // metaKey,
  36. 0, // button
  37. null // relatedTarget
  38. ];
  39. // Calculate and store the 'clientX' for each tick in the slider
  40. tickOffsets = testSlider.ticks.map(function (tick) {
  41. return tick.offsetLeft + testSlider.sliderElem.offsetLeft;
  42. });
  43. });
  44. afterEach(function() {
  45. if(testSlider) {
  46. if(testSlider instanceof Slider) { testSlider.destroy(); }
  47. testSlider = null;
  48. }
  49. });
  50. describe("Dragging handles over each other", function() {
  51. it("should swap reliably given imprecision", function() {
  52. // Create mouse event with position to the left of problem tick
  53. var mouseLeft = document.createEvent('MouseEvents');
  54. mouseEventArguments[7] = tickOffsets[4]; // clientX
  55. mouseLeft.initMouseEvent.apply(mouseLeft, mouseEventArguments);
  56. // Create mouse event with position on problem tick
  57. var mouseOverlap = document.createEvent('MouseEvents');
  58. mouseEventArguments[7] = tickOffsets[5]; // clientX
  59. mouseOverlap.initMouseEvent.apply(mouseOverlap, mouseEventArguments);
  60. // Create mouse event with position to the right of problem tick
  61. var mouseRight = document.createEvent('MouseEvents');
  62. mouseEventArguments[7] = tickOffsets[6]; // clientX
  63. mouseRight.initMouseEvent.apply(mouseRight, mouseEventArguments);
  64. // Same offset as 'mouseLeft'
  65. var mouseUp = document.createEvent('MouseEvents');
  66. mouseEventArguments[7] = testSlider.ticks[4].offsetLeft + testSlider.sliderElem.offsetLeft; // clientX
  67. mouseUp.initMouseEvent.apply(mouseUp, mouseEventArguments);
  68. // Simulate drag without swapping
  69. testSlider.mousedown(mouseLeft);
  70. expect(testSlider._state.dragged).toBe(0);
  71. expect(testSlider.getValue()).toEqual([4, 5]);
  72. // Simulate handle overlap
  73. testSlider.mousemove(mouseOverlap);
  74. expect(testSlider._state.dragged).toBe(0);
  75. expect(testSlider.getValue()).toEqual([5, 5]);
  76. // Simulate left over right drag with imprecision in reported percentage
  77. testSlider.mousemove(mouseRight);
  78. expect(testSlider._state.dragged).toBe(1);
  79. expect(testSlider.getValue()).toEqual([5, 6]);
  80. // Simulate handle overlap
  81. testSlider.mousemove(mouseOverlap);
  82. expect(testSlider._state.dragged).toBe(1);
  83. expect(testSlider.getValue()).toEqual([5, 5]);
  84. // Simulator handle overlap with click
  85. testSlider.mousemove(mouseOverlap);
  86. testSlider.mousedown(mouseLeft);
  87. expect(testSlider._state.dragged).toBe(0);
  88. expect(testSlider.getValue()).toEqual([4, 5]);
  89. // Simulate right over left drag with imprecision in reported percentage
  90. testSlider.mousemove(mouseLeft);
  91. expect(testSlider._state.dragged).toBe(0);
  92. expect(testSlider.getValue()).toEqual([4, 5]);
  93. // End with mouse up
  94. testSlider.mouseup(mouseUp);
  95. expect(testSlider._state.dragged).toBeNull();
  96. expect(testSlider.getValue()).toEqual([4, 5]);
  97. });
  98. });
  99. describe("Drag handles over each other and use keyboard to move handles over each other", function() {
  100. var keyboardEvent;
  101. function createMouseEvent(type, tickIdx) {
  102. var mouseEvent = document.createEvent('MouseEvent');
  103. mouseEventArguments[0] = type;
  104. mouseEventArguments[7] = tickOffsets[tickIdx];
  105. mouseEvent.initMouseEvent.apply(mouseEvent, mouseEventArguments);
  106. return mouseEvent;
  107. }
  108. beforeEach(function() {
  109. // Create keyboard event
  110. keyboardEvent = document.createEvent('Event');
  111. keyboardEvent.initEvent('keydown', true, true);
  112. });
  113. afterEach(function() {
  114. keyboardEvent = null;
  115. });
  116. it("should drag and keydown handles properly to the right then back to the left", function() {
  117. // Simulate drag without swapping
  118. testSlider.mousedown(createMouseEvent('mousedown', 4));
  119. expect(testSlider._state.dragged).toBe(0);
  120. expect(testSlider.getValue()).toEqual([4, 5]);
  121. // Simulate handle overlap
  122. testSlider.mousemove(createMouseEvent('mousemove', 5));
  123. expect(testSlider._state.dragged).toBe(0);
  124. expect(testSlider.getValue()).toEqual([5, 5]);
  125. // Simulate left over right drag
  126. testSlider.mousemove(createMouseEvent('mousemove', 6));
  127. expect(testSlider._state.dragged).toBe(1);
  128. expect(testSlider.getValue()).toEqual([5, 6]);
  129. // End with mouse up
  130. testSlider.mouseup(createMouseEvent('mouseup', 6));
  131. expect(testSlider._state.dragged).toBeNull();
  132. expect(testSlider.getValue()).toEqual([5, 6]);
  133. // Now move the handles past each other with the Left arrow key
  134. keyboardEvent.keyCode = keyboardEvent.which = 37;
  135. // Move handle2 to the left with keyboard
  136. testSlider.handle2Keydown(keyboardEvent);
  137. expect(testSlider._state.keyCtrl).toBeUndefined();
  138. expect(testSlider.getValue()).toEqual([5, 5]);
  139. // Move handle2 to the left again
  140. testSlider.handle2Keydown(keyboardEvent);
  141. expect(testSlider._state.keyCtrl).toBeUndefined();
  142. expect(testSlider.getValue()).toEqual([4, 5]);
  143. });
  144. it("should drag and keydown handles properly to the left then back to the right", function() {
  145. // Simulate drag without swapping
  146. testSlider.mousedown(createMouseEvent('mousedown', 5));
  147. expect(testSlider._state.dragged).toBe(1);
  148. expect(testSlider.getValue()).toEqual([4, 5]);
  149. // Simulate handle overlap
  150. testSlider.mousemove(createMouseEvent('mousemove', 4));
  151. expect(testSlider._state.dragged).toBe(1);
  152. expect(testSlider.getValue()).toEqual([4, 4]);
  153. // Simulate left over right drag
  154. testSlider.mousemove(createMouseEvent('mousemove', 3));
  155. expect(testSlider._state.dragged).toBe(0);
  156. expect(testSlider.getValue()).toEqual([3, 4]);
  157. // End with mouse up
  158. testSlider.mouseup(createMouseEvent('mouseup', 3));
  159. expect(testSlider._state.dragged).toBeNull();
  160. expect(testSlider.getValue()).toEqual([3, 4]);
  161. // Now move the handles past each other with the Right arrow key
  162. keyboardEvent.keyCode = keyboardEvent.which = 39;
  163. // Move handle1 to the right with keyboard
  164. testSlider.handle1Keydown(keyboardEvent);
  165. expect(testSlider._state.keyCtrl).toBeUndefined();
  166. expect(testSlider.getValue()).toEqual([4, 4]);
  167. // Move handle1 to the right again
  168. testSlider.handle1Keydown(keyboardEvent);
  169. expect(testSlider._state.keyCtrl).toBeUndefined();
  170. expect(testSlider.getValue()).toEqual([4, 5]);
  171. });
  172. });
  173. it("Should snap to a tick within tick bounds when using the mouse navigation", function() {
  174. testSlider.setAttribute('range', true);
  175. testSlider.setAttribute('ticks_snap_bounds', 0.45);
  176. testSlider.setAttribute('step', 0.1);
  177. testSlider.refresh();
  178. // Create mouse events
  179. var mouseDown = document.createEvent("MouseEvents");
  180. mouseEventArguments[7] = tickOffsets[1];
  181. mouseDown.initMouseEvent.apply(mouseDown, mouseEventArguments);
  182. var mouseRight = document.createEvent("MouseEvents");
  183. mouseEventArguments[7] = tickOffsets[2] - 2;
  184. mouseRight.initMouseEvent.apply(mouseRight, mouseEventArguments);
  185. testSlider.mousedown(mouseDown);
  186. expect(testSlider.getValue()).toEqual([0.7, 5]);
  187. testSlider.mousemove(mouseRight);
  188. expect(testSlider.getValue()).toEqual([2, 5]);
  189. // FIXME: Use 'mouseup' event type
  190. // End with mouse up
  191. testSlider.mouseup(mouseRight);
  192. expect(testSlider.getValue()).toEqual([2, 5]);
  193. });
  194. it("Should trigger change on mouseup", function(done) {
  195. var changes = 0;
  196. testSlider.on('slideStop', function(){
  197. expect(changes).toBe(1);
  198. expect(testSlider.getValue()).toEqual([2, 5]);
  199. done();
  200. });
  201. testSlider.mousedown(mouseEvent('mousedown', tickOffsets[1]));
  202. expect(testSlider.getValue()).toEqual([1, 5]);
  203. testSlider.on('change', function(){
  204. changes++;
  205. });
  206. testSlider.mouseup(mouseEvent('mouseup', tickOffsets[2]));
  207. });
  208. describe("Test 'mousemove' and 'mouseup' produces correct results", function() {
  209. var $mySlider;
  210. var $handle1;
  211. function arraysEqual(a, b) {
  212. if (a === b) { return true; }
  213. if (a == null || b == null) { return false; }
  214. if (a.length !== b.length) { return false; }
  215. for (var i = 0; i < a.length; ++i) {
  216. if (a[i] !== b[i]) { return false; }
  217. }
  218. return true;
  219. }
  220. it("Last value changed in 'change' event should equal 'mouseup' event value for slider", function(done) {
  221. // Change attributes for 'testSlider'
  222. testSlider.setAttribute('value', 3);
  223. testSlider.setAttribute('range', false);
  224. testSlider.refresh();
  225. $mySlider = $('#testSlider1');
  226. function createMouseEvent(type, tickIdx) {
  227. var mouseEvent = document.createEvent('MouseEvent');
  228. mouseEventArguments[0] = type;
  229. mouseEventArguments[7] = tickOffsets[tickIdx];
  230. mouseEvent.initMouseEvent.apply(mouseEvent, mouseEventArguments);
  231. return mouseEvent;
  232. }
  233. var lastValue = 99; // Dummy value
  234. $mySlider.on('change', function(eventData) {
  235. lastValue = eventData.value.newValue;
  236. });
  237. $mySlider.on('slideStop', function(eventData) {
  238. var value = eventData.value;
  239. var isEqual = Array.isArray(value) ? arraysEqual(lastValue, value) : value === lastValue;
  240. expect(isEqual).toBe(true);
  241. done();
  242. });
  243. // Simulate drag and release from tick[1] to tick[4]
  244. $handle1 = testSlider.$sliderElem.find('.slider-handle:first');
  245. $handle1[0].dispatchEvent(createMouseEvent('mousedown', 1));
  246. $handle1[0].dispatchEvent(createMouseEvent('mousemove', 4));
  247. $handle1[0].dispatchEvent(createMouseEvent('mouseup', 4));
  248. });
  249. });
  250. });