edit-mode.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459
  1. describe('keyboard operation - edit mode', function () {
  2. let input;
  3. beforeEach(function () {
  4. input = document.createElement('input');
  5. testContainer.appendChild(input);
  6. });
  7. afterEach(function () {
  8. testContainer.removeChild(input);
  9. });
  10. it('turns on when Datepicker.enterEditMode() is called', function () {
  11. const dp = new Datepicker(input);
  12. input.focus();
  13. dp.enterEditMode();
  14. expect(dp.editMode, 'to be true');
  15. expect(input.classList.contains('in-edit'), 'to be true');
  16. dp.destroy();
  17. input.classList.remove('in-edit');
  18. });
  19. it('turns on when a printable letter, backspace or delete key is pressed without ctrl/meta', function () {
  20. const dp = new Datepicker(input);
  21. input.focus();
  22. simulant.fire(input, 'keydown', {key: '1'});
  23. expect(dp.editMode, 'to be true');
  24. delete dp.editMode;
  25. input.classList.remove('in-edit');
  26. simulant.fire(input, 'keydown', {key: 'J'});
  27. expect(dp.editMode, 'to be true');
  28. delete dp.editMode;
  29. input.classList.remove('in-edit');
  30. simulant.fire(input, 'keydown', {key: '/'});
  31. expect(dp.editMode, 'to be true');
  32. delete dp.editMode;
  33. input.classList.remove('in-edit');
  34. simulant.fire(input, 'keydown', {key: ' '});
  35. expect(dp.editMode, 'to be true');
  36. delete dp.editMode;
  37. input.classList.remove('in-edit');
  38. simulant.fire(input, 'keydown', {key: 'Backspace'});
  39. expect(dp.editMode, 'to be true');
  40. delete dp.editMode;
  41. input.classList.remove('in-edit');
  42. simulant.fire(input, 'keydown', {key: 'Delete'});
  43. expect(dp.editMode, 'to be true');
  44. delete dp.editMode;
  45. input.classList.remove('in-edit');
  46. // with modifier key
  47. simulant.fire(input, 'keydown', {key: '1', shiftKey: true});
  48. expect(dp.editMode, 'to be true');
  49. delete dp.editMode;
  50. input.classList.remove('in-edit');
  51. simulant.fire(input, 'keydown', {key: '1', altKey: true});
  52. expect(dp.editMode, 'to be true');
  53. delete dp.editMode;
  54. input.classList.remove('in-edit');
  55. simulant.fire(input, 'keydown', {key: '1', ctrlKey: true});
  56. expect(dp.editMode, 'to be undefined');
  57. expect(input.classList.contains('in-edit'), 'to be false');
  58. simulant.fire(input, 'keydown', {key: '1', metaKey: true});
  59. expect(dp.editMode, 'to be undefined');
  60. expect(input.classList.contains('in-edit'), 'to be false');
  61. // non-pritable-letter key
  62. simulant.fire(input, 'keydown', {key: 'PageDown'});
  63. expect(dp.editMode, 'to be undefined');
  64. expect(input.classList.contains('in-edit'), 'to be false');
  65. simulant.fire(input, 'keydown', {key: 'Escape', ctrlKey: true});
  66. expect(dp.editMode, 'to be undefined');
  67. dp.destroy();
  68. });
  69. it('turns on when shift + either of arrow keys is pressed without ctrl/meta', function () {
  70. const dp = new Datepicker(input);
  71. input.focus();
  72. // shift + arrow
  73. simulant.fire(input, 'keydown', {key: 'ArrowLeft', shiftKey: true});
  74. expect(dp.editMode, 'to be true');
  75. delete dp.editMode;
  76. input.classList.remove('in-edit');
  77. simulant.fire(input, 'keydown', {key: 'ArrowRight', shiftKey: true});
  78. expect(dp.editMode, 'to be true');
  79. delete dp.editMode;
  80. input.classList.remove('in-edit');
  81. simulant.fire(input, 'keydown', {key: 'ArrowUp', shiftKey: true});
  82. expect(dp.editMode, 'to be true');
  83. delete dp.editMode;
  84. input.classList.remove('in-edit');
  85. simulant.fire(input, 'keydown', {key: 'ArrowDown', shiftKey: true});
  86. expect(dp.editMode, 'to be true');
  87. delete dp.editMode;
  88. input.classList.remove('in-edit');
  89. // arrow + other modifire key
  90. // arrow-left
  91. simulant.fire(input, 'keydown', {key: 'ArrowLeft', altKey: true});
  92. expect(dp.editMode, 'to be undefined');
  93. simulant.fire(input, 'keydown', {key: 'ArrowLeft', ctrlKey: true});
  94. expect(dp.editMode, 'to be undefined');
  95. simulant.fire(input, 'keydown', {key: 'ArrowLeft', metaKey: true});
  96. expect(dp.editMode, 'to be undefined');
  97. // arrow-right
  98. simulant.fire(input, 'keydown', {key: 'ArrowRight', altKey: true});
  99. expect(dp.editMode, 'to be undefined');
  100. simulant.fire(input, 'keydown', {key: 'ArrowRight', ctrlKey: true});
  101. expect(dp.editMode, 'to be undefined');
  102. simulant.fire(input, 'keydown', {key: 'ArrowRight', metaKey: true});
  103. expect(dp.editMode, 'to be undefined');
  104. // arrow-up
  105. simulant.fire(input, 'keydown', {key: 'ArrowUp', altKey: true});
  106. expect(dp.editMode, 'to be undefined');
  107. simulant.fire(input, 'keydown', {key: 'ArrowUp', ctrlKey: true});
  108. expect(dp.editMode, 'to be undefined');
  109. simulant.fire(input, 'keydown', {key: 'ArrowUp', metaKey: true});
  110. expect(dp.editMode, 'to be undefined');
  111. // arrow-down
  112. simulant.fire(input, 'keydown', {key: 'ArrowDown', altKey: true});
  113. expect(dp.editMode, 'to be undefined');
  114. simulant.fire(input, 'keydown', {key: 'ArrowDown', ctrlKey: true});
  115. expect(dp.editMode, 'to be undefined');
  116. simulant.fire(input, 'keydown', {key: 'ArrowDown', metaKey: true});
  117. expect(dp.editMode, 'to be undefined');
  118. // shift + arrow with other modifier key
  119. // arrow-left
  120. simulant.fire(input, 'keydown', {key: 'ArrowLeft', shiftKey: true, altKey: true});
  121. expect(dp.editMode, 'to be true');
  122. delete dp.editMode;
  123. input.classList.remove('in-edit');
  124. simulant.fire(input, 'keydown', {key: 'ArrowLeft', shiftKey: true, ctrlKey: true});
  125. expect(dp.editMode, 'to be undefined');
  126. simulant.fire(input, 'keydown', {key: 'ArrowLeft', shiftKey: true, metaKey: true});
  127. expect(dp.editMode, 'to be undefined');
  128. // arrow-right
  129. simulant.fire(input, 'keydown', {key: 'ArrowRight', shiftKey: true, altKey: true});
  130. expect(dp.editMode, 'to be true');
  131. delete dp.editMode;
  132. input.classList.remove('in-edit');
  133. simulant.fire(input, 'keydown', {key: 'ArrowRight', shiftKey: true, ctrlKey: true});
  134. expect(dp.editMode, 'to be undefined');
  135. simulant.fire(input, 'keydown', {key: 'ArrowRight', shiftKey: true, metaKey: true});
  136. expect(dp.editMode, 'to be undefined');
  137. // arrow-up
  138. simulant.fire(input, 'keydown', {key: 'ArrowUp', shiftKey: true, altKey: true});
  139. expect(dp.editMode, 'to be true');
  140. delete dp.editMode;
  141. input.classList.remove('in-edit');
  142. simulant.fire(input, 'keydown', {key: 'ArrowUp', shiftKey: true, ctrlKey: true});
  143. expect(dp.editMode, 'to be undefined');
  144. simulant.fire(input, 'keydown', {key: 'ArrowUp', shiftKey: true, metaKey: true});
  145. expect(dp.editMode, 'to be undefined');
  146. // arrow-down
  147. simulant.fire(input, 'keydown', {key: 'ArrowDown', shiftKey: true, altKey: true});
  148. expect(dp.editMode, 'to be true');
  149. delete dp.editMode;
  150. input.classList.remove('in-edit');
  151. simulant.fire(input, 'keydown', {key: 'ArrowDown', shiftKey: true, ctrlKey: true});
  152. expect(dp.editMode, 'to be undefined');
  153. simulant.fire(input, 'keydown', {key: 'ArrowDown', shiftKey: true, metaKey: true});
  154. expect(dp.editMode, 'to be undefined');
  155. dp.destroy();
  156. });
  157. it('turns on when input is clicked', function () {
  158. const dp = new Datepicker(input);
  159. input.focus();
  160. simulant.fire(input, 'mousedown');
  161. input.click();
  162. expect(dp.editMode, 'to be true');
  163. expect(input.classList.contains('in-edit'), 'to be true');
  164. dp.destroy();
  165. input.classList.remove('in-edit');
  166. });
  167. it('does not turn on when the picker is hidden', function () {
  168. const dp = new Datepicker(input);
  169. dp.enterEditMode();
  170. expect(dp.editMode, 'to be undefined');
  171. expect(input.classList.contains('in-edit'), 'to be false');
  172. simulant.fire(input, 'keydown', {key: '1'});
  173. expect(dp.editMode, 'to be undefined');
  174. simulant.fire(input, 'keydown', {key: 'J'});
  175. expect(dp.editMode, 'to be undefined');
  176. simulant.fire(input, 'mousedown');
  177. input.click();
  178. expect(dp.editMode, 'to be undefined');
  179. dp.destroy();
  180. });
  181. it('disables the arrow-key operation of the picker', function () {
  182. const clock = sinon.useFakeTimers({now: new Date(2020, 1, 14)});
  183. const {dp, picker} = createDP(input);
  184. const viewSwitch = getViewSwitch(picker);
  185. input.focus();
  186. dp.enterEditMode();
  187. simulant.fire(input, 'keydown', {key: 'ArrowLeft'});
  188. expect(viewSwitch.textContent, 'to be', 'February 2020');
  189. let cells = getCells(picker);
  190. expect(filterCells(cells, '.focused'), 'to equal', [cells[19]]);
  191. expect(cells[19].textContent, 'to be', '14');
  192. simulant.fire(input, 'keydown', {key: 'ArrowRight'});
  193. expect(viewSwitch.textContent, 'to be', 'February 2020');
  194. cells = getCells(picker);
  195. expect(filterCells(cells, '.focused'), 'to equal', [cells[19]]);
  196. simulant.fire(input, 'keydown', {key: 'ArrowUp'});
  197. expect(viewSwitch.textContent, 'to be', 'February 2020');
  198. cells = getCells(picker);
  199. expect(filterCells(cells, '.focused'), 'to equal', [cells[19]]);
  200. simulant.fire(input, 'keydown', {key: 'ArrowDownt'});
  201. expect(viewSwitch.textContent, 'to be', 'February 2020');
  202. cells = getCells(picker);
  203. expect(filterCells(cells, '.focused'), 'to equal', [cells[19]]);
  204. viewSwitch.click();
  205. simulant.fire(input, 'keydown', {key: 'ArrowLeft'});
  206. expect(viewSwitch.textContent, 'to be', '2020');
  207. cells = getCells(picker);
  208. expect(filterCells(cells, '.focused'), 'to equal', [cells[1]]);
  209. viewSwitch.click();
  210. simulant.fire(input, 'keydown', {key: 'ArrowRight'});
  211. expect(viewSwitch.textContent, 'to be', '2020-2029');
  212. cells = getCells(picker);
  213. expect(filterCells(cells, '.focused'), 'to equal', [cells[1]]);
  214. viewSwitch.click();
  215. simulant.fire(input, 'keydown', {key: 'ArrowDown'});
  216. expect(viewSwitch.textContent, 'to be', '2000-2090');
  217. cells = getCells(picker);
  218. expect(filterCells(cells, '.focused'), 'to equal', [cells[3]]);
  219. dp.destroy();
  220. clock.restore();
  221. });
  222. it('turns off when Datepicker.exitEditMode() is called', function () {
  223. const dp = new Datepicker(input);
  224. input.focus();
  225. dp.enterEditMode();
  226. dp.exitEditMode();
  227. expect(dp.editMode, 'to be undefined');
  228. expect(input.classList.contains('in-edit'), 'to be false');
  229. dp.destroy();
  230. });
  231. it('turns off when the picker hides', function () {
  232. const {dp, picker} = createDP(input);
  233. input.focus();
  234. dp.enterEditMode();
  235. dp.hide();
  236. expect(dp.editMode, 'to be undefined');
  237. expect(input.classList.contains('in-edit'), 'to be false');
  238. dp.destroy();
  239. });
  240. it('turns off when escape key is pressed', function () {
  241. const dp = new Datepicker(input);
  242. input.focus();
  243. dp.enterEditMode();
  244. simulant.fire(input, 'keydown', {key: 'Escape'});
  245. expect(dp.editMode, 'to be undefined');
  246. expect(input.classList.contains('in-edit'), 'to be false');
  247. dp.destroy();
  248. });
  249. it('leaves the edit on the input as-is by default when turning off', function () {
  250. const dp = new Datepicker(input);
  251. const date = dateValue(2020, 1, 14);
  252. dp.setDate(date);
  253. input.focus();
  254. dp.enterEditMode();
  255. input.value = '4/22/2020';
  256. dp.exitEditMode();
  257. expect(input.value, 'to be', '4/22/2020');
  258. expect(dp.dates, 'to equal', [date]);
  259. dp.show();
  260. dp.enterEditMode();
  261. input.value = '3/8/2020';
  262. dp.hide();
  263. expect(input.value, 'to be', '3/8/2020');
  264. expect(dp.dates, 'to equal', [date]);
  265. dp.show();
  266. dp.enterEditMode();
  267. input.value = '02/14/2020';
  268. simulant.fire(input, 'keydown', {key: 'Escape'});
  269. expect(input.value, 'to be', '02/14/2020');
  270. expect(dp.dates, 'to equal', [date]);
  271. dp.destroy();
  272. });
  273. it('hides the picker when turning off by escape key press', function () {
  274. const {dp, picker} = createDP(input);
  275. input.focus();
  276. dp.enterEditMode();
  277. simulant.fire(input, 'keydown', {key: 'Escape'});
  278. expect(isVisible(picker), 'to be false');
  279. dp.show();
  280. dp.enterEditMode();
  281. dp.exitEditMode();
  282. expect(isVisible(picker), 'to be true');
  283. dp.destroy();
  284. });
  285. it('updates the selection with the input when turning off by exitEditMode() call with update: true option', function () {
  286. const dp = new Datepicker(input);
  287. const date = dateValue(2020, 3, 22);
  288. dp.setDate('02/14/2020');
  289. input.focus();
  290. dp.enterEditMode();
  291. input.value = '4/22/2020';
  292. dp.exitEditMode({update: true});
  293. expect(dp.editMode, 'to be undefined');
  294. expect(input.classList.contains('in-edit'), 'to be false');
  295. expect(input.value, 'to be', '04/22/2020');
  296. expect(dp.dates, 'to equal', [date]);
  297. dp.destroy();
  298. });
  299. it('updates the selection with the input when turning off by enter key press', function () {
  300. const dp = new Datepicker(input);
  301. const date = dateValue(2020, 3, 22);
  302. dp.setDate('02/14/2020');
  303. input.focus();
  304. dp.enterEditMode();
  305. input.value = '4/22/2020';
  306. simulant.fire(input, 'keydown', {key: 'Enter'});
  307. expect(dp.editMode, 'to be undefined');
  308. expect(input.classList.contains('in-edit'), 'to be false');
  309. expect(input.value, 'to be', '04/22/2020');
  310. expect(dp.dates, 'to equal', [date]);
  311. dp.destroy();
  312. });
  313. it('updates the selection with the input when turning off being induced by unfocusing input element', function () {
  314. const outsider = document.createElement('p');
  315. testContainer.appendChild(outsider);
  316. const dp = new Datepicker(input);
  317. const date = dateValue(2020, 3, 22);
  318. // by tab key-press
  319. dp.setDate('02/14/2020');
  320. input.focus();
  321. dp.enterEditMode();
  322. input.value = '4/22/2020';
  323. simulant.fire(input, 'keydown', {key: 'Tab'});
  324. expect(dp.editMode, 'to be undefined');
  325. expect(input.classList.contains('in-edit'), 'to be false');
  326. expect(input.value, 'to be', '04/22/2020');
  327. expect(dp.dates, 'to equal', [date]);
  328. //by clicking outside
  329. dp.setDate('02/14/2020');
  330. dp.show();
  331. dp.enterEditMode();
  332. input.value = '4/22/2020';
  333. simulant.fire(outsider, 'mousedown');
  334. expect(dp.editMode, 'to be undefined');
  335. expect(input.classList.contains('in-edit'), 'to be false');
  336. expect(input.value, 'to be', '04/22/2020');
  337. expect(dp.dates, 'to equal', [date]);
  338. dp.destroy();
  339. testContainer.removeChild(outsider);
  340. });
  341. });