textEditor.spec.js 29 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103
  1. describe('TextEditor', () => {
  2. var id = 'testContainer';
  3. beforeEach(function() {
  4. this.$container = $(`<div id="${id}" style="width: 300px; height: 200px; overflow: hidden;"></div>`).appendTo('body');
  5. });
  6. afterEach(function() {
  7. if (this.$container) {
  8. destroy();
  9. this.$container.remove();
  10. }
  11. });
  12. it('should begin editing when enterBeginsEditing equals true', () => {
  13. handsontable({
  14. enterBeginsEditing: true,
  15. editor: 'text'
  16. });
  17. selectCell(2, 2);
  18. keyDown('enter');
  19. var selection = getSelected();
  20. expect(selection).toEqual([2, 2, 2, 2]);
  21. expect(isEditorVisible()).toEqual(true);
  22. });
  23. it('should move down after editing', () => {
  24. handsontable({
  25. editor: 'text'
  26. });
  27. selectCell(2, 2);
  28. keyDown('enter');
  29. keyDown('enter');
  30. var selection = getSelected();
  31. expect(selection).toEqual([3, 2, 3, 2]);
  32. });
  33. it('should move down when enterBeginsEditing equals false', () => {
  34. handsontable({
  35. enterBeginsEditing: false
  36. });
  37. selectCell(2, 2);
  38. keyDown('enter');
  39. var selection = getSelected();
  40. expect(selection).toEqual([3, 2, 3, 2]);
  41. expect(isEditorVisible()).toEqual(false);
  42. });
  43. it('should render string in textarea', () => {
  44. handsontable();
  45. setDataAtCell(2, 2, 'string');
  46. selectCell(2, 2);
  47. keyDown('enter');
  48. expect(keyProxy().val()).toEqual('string');
  49. });
  50. it('should render textarea editor in specified size at cell 0, 0 without headers', (done) => {
  51. var hot = handsontable();
  52. selectCell(0, 0);
  53. keyDown('enter');
  54. setTimeout(() => {
  55. expect(hot.getActiveEditor().TEXTAREA.style.height).toBe('23px');
  56. expect(hot.getActiveEditor().TEXTAREA.style.width).toBe('40px');
  57. done();
  58. }, 200);
  59. });
  60. it('should render textarea editor in specified size at cell 1, 0 without headers', (done) => {
  61. var hot = handsontable();
  62. selectCell(1, 1);
  63. keyDown('enter');
  64. setTimeout(() => {
  65. expect(hot.getActiveEditor().TEXTAREA.style.height).toBe('23px');
  66. done();
  67. }, 200);
  68. });
  69. it('should render textarea editor in specified size at cell 0, 0 with headers', (done) => {
  70. const hot = handsontable({
  71. rowHeaders: true,
  72. colHeaders: true
  73. });
  74. selectCell(0, 0);
  75. keyDown('enter');
  76. setTimeout(() => {
  77. expect(hot.getActiveEditor().TEXTAREA.style.height).toBe('23px');
  78. expect(hot.getActiveEditor().TEXTAREA.style.width).toBe('40px');
  79. expect(hot.getActiveEditor().textareaParentStyle.top).toBe('26px');
  80. done();
  81. }, 200);
  82. });
  83. it('should render textarea editor in specified size at cell 0, 0 with headers defined in columns', (done) => {
  84. const hot = handsontable({
  85. data: Handsontable.helper.createSpreadsheetObjectData(10, 10),
  86. columns: [{
  87. data: 'prop0',
  88. title: 'Prop 0'
  89. }, {
  90. data: 'prop1',
  91. title: 'Prop 1'
  92. }, {
  93. data: 'prop2',
  94. title: 'Prop 2'
  95. }, {
  96. data: 'prop3',
  97. title: 'Prop 3'
  98. }],
  99. });
  100. selectCell(0, 0);
  101. keyDown('enter');
  102. setTimeout(() => {
  103. expect(hot.getActiveEditor().TEXTAREA.style.height).toBe('23px');
  104. expect(parseInt(hot.getActiveEditor().TEXTAREA.style.width, 10)).toBeAroundValue(50, 4);
  105. expect(hot.getActiveEditor().textareaParentStyle.top).toBe('26px');
  106. done();
  107. }, 200);
  108. });
  109. it('should hide whole editor when it is higher then header', (done) => {
  110. const hot = handsontable({
  111. data: Handsontable.helper.createSpreadsheetData(50, 50),
  112. rowHeaders: true,
  113. colHeaders: true
  114. });
  115. setDataAtCell(2, 2, 'string\nstring\nstring');
  116. selectCell(2, 2);
  117. keyDown('enter');
  118. keyUp('enter');
  119. var mainHolder = hot.view.wt.wtTable.holder;
  120. mainHolder.scrollTop = 150;
  121. mainHolder.scrollLeft = 150;
  122. setTimeout(() => {
  123. expect(parseInt(hot.getActiveEditor().textareaParentStyle.top, 10)).toBeAroundValue(-77);
  124. expect(parseInt(hot.getActiveEditor().textareaParentStyle.left, 10)).toBeAroundValue(-1);
  125. done();
  126. }, 200);
  127. });
  128. it('should hide editor when quick navigation by click scrollbar was triggered', (done) => {
  129. var hot = handsontable({
  130. data: Handsontable.helper.createSpreadsheetData(50, 50),
  131. rowHeaders: true,
  132. colHeaders: true
  133. });
  134. setDataAtCell(2, 2, 'string\nstring\nstring');
  135. selectCell(2, 2);
  136. keyDown('enter');
  137. keyUp('enter');
  138. hot.scrollViewportTo(49);
  139. setTimeout(() => {
  140. expect(hot.getActiveEditor().textareaParentStyle.display).toBe('none');
  141. done();
  142. }, 100);
  143. });
  144. it('should render textarea editor in specified height (single line)', (done) => {
  145. var hot = handsontable(),
  146. editorHeight;
  147. setDataAtCell(2, 2, 'first line');
  148. selectCell(2, 2);
  149. keyDown('enter');
  150. setTimeout(() => {
  151. expect(hot.getActiveEditor().TEXTAREA.style.height).toBe('23px');
  152. done();
  153. }, 200);
  154. });
  155. it('should render textarea editor in specified height (multi line)', (done) => {
  156. var hot = handsontable(),
  157. editorHeight;
  158. setDataAtCell(2, 2, 'first line\n second line\n third line...');
  159. selectCell(2, 2);
  160. keyDown('enter');
  161. setTimeout(() => {
  162. expect(hot.getActiveEditor().TEXTAREA.style.height).toBe('64px');
  163. done();
  164. }, 200);
  165. });
  166. it('should render number in textarea', () => {
  167. handsontable();
  168. setDataAtCell(2, 2, 13);
  169. selectCell(2, 2);
  170. keyDown('enter');
  171. expect(keyProxy().val()).toEqual('13');
  172. });
  173. it('should render boolean true in textarea', () => {
  174. handsontable();
  175. setDataAtCell(2, 2, true);
  176. selectCell(2, 2);
  177. keyDown('enter');
  178. expect(keyProxy().val()).toEqual('true');
  179. });
  180. it('should render boolean false in textarea', () => {
  181. handsontable();
  182. setDataAtCell(2, 2, false);
  183. selectCell(2, 2);
  184. keyDown('enter');
  185. expect(keyProxy().val()).toEqual('false');
  186. });
  187. it('should render null in textarea', () => {
  188. handsontable();
  189. setDataAtCell(2, 2, null);
  190. selectCell(2, 2);
  191. keyDown('enter');
  192. expect(keyProxy().val()).toEqual('');
  193. });
  194. it('should render undefined in textarea', () => {
  195. handsontable();
  196. setDataAtCell(2, 2, void 0);
  197. selectCell(2, 2);
  198. keyDown('enter');
  199. expect(keyProxy().val()).toEqual('');
  200. });
  201. it('should render nested object value in textarea', () => {
  202. handsontable({
  203. data: [{
  204. name: {
  205. first: 'Tom',
  206. last: 'Kowalski',
  207. obj: {}
  208. }
  209. }, {
  210. name: {
  211. first: 'John',
  212. last: 'Cage',
  213. obj: {
  214. foo: 'bar'
  215. }
  216. }
  217. }],
  218. columns: [{
  219. data: 'name.last'
  220. }, {
  221. data: 'name.obj.foo'
  222. }]
  223. });
  224. selectCell(0, 0);
  225. keyDown('enter');
  226. expect(keyProxy().val()).toEqual('Kowalski');
  227. selectCell(1, 1);
  228. keyDown('enter');
  229. expect(keyProxy().val()).toEqual('bar');
  230. });
  231. it('should render nested object value in textarea after change rows order', () => {
  232. var hot = handsontable({
  233. data: [{
  234. name: {
  235. first: 'Tom',
  236. last: 'Kowalski',
  237. obj: {}
  238. }
  239. }, {
  240. name: {
  241. first: 'John',
  242. last: 'Cage',
  243. obj: {
  244. foo: 'bar'
  245. }
  246. }
  247. }],
  248. columns: [{
  249. data: 'name.last'
  250. }, {
  251. data: 'name.obj.foo'
  252. }],
  253. manualRowMove: true
  254. });
  255. hot.getPlugin('manualRowMove').moveRow(1, 0);
  256. hot.render();
  257. selectCell(0, 0);
  258. keyDown('enter');
  259. expect(keyProxy().val()).toEqual('Cage');
  260. keyDown('enter');
  261. expect(hot.getDataAtCell(0, 0)).toEqual('Cage');
  262. selectCell(1, 1);
  263. keyDown('enter');
  264. expect(keyProxy().val()).toEqual('');
  265. keyDown('enter');
  266. expect(hot.getDataAtCell(1, 1)).toEqual('');
  267. });
  268. it('should render nested object value in textarea after change columns order', () => {
  269. var hot = handsontable({
  270. data: [{
  271. name: {
  272. first: 'Tom',
  273. last: 'Kowalski',
  274. obj: {}
  275. }
  276. }, {
  277. name: {
  278. first: 'John',
  279. last: 'Cage',
  280. obj: {
  281. foo: 'bar'
  282. }
  283. }
  284. }],
  285. columns: [{
  286. data: 'name.last'
  287. }, {
  288. data: 'name.obj.foo'
  289. }],
  290. manualColumnMove: true
  291. });
  292. hot.getPlugin('manualColumnMove').moveColumn(1, 0);
  293. hot.render();
  294. selectCell(0, 0);
  295. keyDown('enter');
  296. expect(keyProxy().val()).toEqual('');
  297. keyDown('enter');
  298. expect(hot.getDataAtCell(0, 0)).toEqual('');
  299. selectCell(1, 1);
  300. keyDown('enter');
  301. expect(keyProxy().val()).toEqual('Cage');
  302. keyDown('enter');
  303. expect(hot.getDataAtCell(1, 1)).toEqual('Cage');
  304. });
  305. it('should render array value defined by columns settings in textarea', () => {
  306. handsontable({
  307. data: [
  308. ['', 'Kia'],
  309. ['2012', 10],
  310. ['2013', 10],
  311. ],
  312. columns: [{
  313. data: '1'
  314. }, {
  315. data: '0'
  316. }],
  317. });
  318. selectCell(0, 0);
  319. keyDown('enter');
  320. expect(keyProxy().val()).toEqual('Kia');
  321. selectCell(1, 1);
  322. keyDown('enter');
  323. expect(keyProxy().val()).toEqual('2012');
  324. });
  325. it('should open editor after hitting F2', () => {
  326. handsontable();
  327. selectCell(2, 2);
  328. var editor = $('.handsontableInput');
  329. expect(isEditorVisible()).toEqual(false);
  330. keyDown('f2');
  331. expect(isEditorVisible()).toEqual(true);
  332. });
  333. it('should close editor after hitting ESC', () => {
  334. handsontable();
  335. selectCell(2, 2);
  336. var editor = $('.handsontableInput');
  337. expect(isEditorVisible()).toEqual(false);
  338. keyDown('f2');
  339. expect(isEditorVisible()).toEqual(true);
  340. keyDown('esc');
  341. expect(isEditorVisible()).toEqual(false);
  342. });
  343. it('should NOT open editor after hitting CapsLock', () => {
  344. handsontable();
  345. selectCell(2, 2);
  346. var editor = $('.handsontableInput');
  347. expect(isEditorVisible()).toEqual(false);
  348. keyDown(Handsontable.helper.KEY_CODES.CAPS_LOCK);
  349. expect(isEditorVisible()).toEqual(false);
  350. });
  351. it('should open editor after cancelling edit and beginning it again', () => {
  352. handsontable();
  353. selectCell(2, 2);
  354. expect(isEditorVisible()).toEqual(false);
  355. keyDown('f2');
  356. expect(isEditorVisible()).toEqual(true);
  357. keyDown('esc');
  358. expect(isEditorVisible()).toEqual(false);
  359. keyDown('f2');
  360. expect(isEditorVisible()).toEqual(true);
  361. });
  362. it('loadData should not destroy editor', () => {
  363. handsontable();
  364. selectCell(2, 2);
  365. keyDown('f2');
  366. loadData(getData());
  367. expect(isEditorVisible()).toEqual(true);
  368. });
  369. it('updateSettings should not destroy editor', () => {
  370. handsontable();
  371. selectCell(2, 2);
  372. keyDown('f2');
  373. updateSettings({
  374. data: getData()
  375. });
  376. expect(isEditorVisible()).toEqual(true);
  377. });
  378. it('textarea should have cell dimensions (after render)', () => {
  379. var data = [
  380. ['a', 'b'],
  381. ['c', 'd']
  382. ];
  383. var hot = handsontable({
  384. data,
  385. minRows: 4,
  386. minCols: 4,
  387. minSpareRows: 4,
  388. minSpareCols: 4,
  389. enterMoves: false
  390. });
  391. selectCell(1, 1);
  392. var $td = getHtCore().find('tbody tr:eq(1) td:eq(1)');
  393. var editor = hot.getActiveEditor();
  394. keyDownUp('enter');
  395. expect(keyProxy().width()).toEqual($td.width());
  396. keyDownUp('enter');
  397. data[1][1] = 'dddddddddddddddddddd';
  398. render();
  399. keyDownUp('enter');
  400. expect(keyProxy().width()).toEqual($td.width());
  401. });
  402. it('global shortcuts (like CTRL+A) should be blocked when cell is being edited', () => {
  403. handsontable();
  404. selectCell(2, 2);
  405. keyDownUp('enter');
  406. keyDown(65, {
  407. ctrlKey: true
  408. }); // CTRL+A should NOT select all table when cell is edited
  409. var selection = getSelected();
  410. expect(selection).toEqual([2, 2, 2, 2]);
  411. expect(isEditorVisible()).toEqual(true);
  412. });
  413. it('should open editor after double clicking on a cell', (done) => {
  414. var hot = handsontable({
  415. data: Handsontable.helper.createSpreadsheetData(5, 2)
  416. });
  417. var cell = $(getCell(0, 0));
  418. var clicks = 0;
  419. window.scrollTo(0, cell.offset().top);
  420. setTimeout(() => {
  421. mouseDown(cell);
  422. mouseUp(cell);
  423. clicks++;
  424. }, 0);
  425. setTimeout(() => {
  426. mouseDown(cell);
  427. mouseUp(cell);
  428. clicks++;
  429. }, 100);
  430. setTimeout(() => {
  431. var editor = hot.getActiveEditor();
  432. expect(clicks).toBe(2);
  433. expect(editor.isOpened()).toBe(true);
  434. expect(editor.isInFullEditMode()).toBe(true);
  435. done();
  436. }, 200);
  437. });
  438. it('should call editor focus() method after opening an editor', () => {
  439. var hot = handsontable();
  440. selectCell(2, 2);
  441. var editor = hot.getActiveEditor();
  442. spyOn(editor, 'focus');
  443. expect(editor.isOpened()).toEqual(false);
  444. expect(editor.focus).not.toHaveBeenCalled();
  445. keyDown('f2');
  446. expect(editor.isOpened()).toEqual(true);
  447. expect(editor.focus).toHaveBeenCalled();
  448. });
  449. it('editor size should not exceed the viewport after text edit', function() {
  450. handsontable({
  451. data: Handsontable.helper.createSpreadsheetData(10, 5),
  452. width: 200,
  453. height: 200
  454. });
  455. selectCell(2, 2);
  456. keyDown('enter');
  457. expect(isEditorVisible()).toEqual(true);
  458. document.activeElement.value = 'Very very very very very very very very very very very very very very very very very long text';
  459. keyDownUp(32); // space - trigger textarea resize
  460. var $textarea = $(document.activeElement);
  461. var $wtHider = this.$container.find('.wtHider');
  462. expect($textarea.offset().left + $textarea.outerWidth()).not.toBeGreaterThan($wtHider.offset().left + this.$container.outerWidth());
  463. expect($textarea.offset().top + $textarea.outerHeight()).not.toBeGreaterThan($wtHider.offset().top + $wtHider.outerHeight());
  464. });
  465. it('should open editor after selecting cell in another table and hitting enter', function() {
  466. this.$container2 = $(`<div id="${id}-2"></div>`).appendTo('body');
  467. var hot1 = handsontable();
  468. var hot2 = handsontable2.call(this);
  469. this.$container.find('tbody tr:eq(0) td:eq(0)').simulate('mousedown');
  470. this.$container.find('tbody tr:eq(0) td:eq(0)').simulate('mouseup');
  471. // Open editor in HOT1
  472. keyDown('enter');
  473. var editor = $('.handsontableInputHolder');
  474. expect(editor.is(':visible')).toBe(true);
  475. // Close editor in HOT1
  476. keyDown('enter');
  477. expect(editor.is(':visible')).toBe(false);
  478. this.$container2.find('tbody tr:eq(0) td:eq(0)').simulate('mousedown');
  479. this.$container2.find('tbody tr:eq(0) td:eq(0)').simulate('mouseup');
  480. expect(hot1.getSelected()).toBeUndefined();
  481. expect(hot2.getSelected()).toEqual([0, 0, 0, 0]);
  482. // Open editor in HOT2
  483. keyDown('enter');
  484. editor = $('.handsontableInputHolder');
  485. expect(editor.is(':visible')).toBe(true);
  486. this.$container2.handsontable('destroy');
  487. this.$container2.remove();
  488. function handsontable2(options) {
  489. var container = this.$container2;
  490. container.handsontable(options);
  491. container[0].focus(); // otherwise TextEditor tests do not pass in IE8
  492. return container.data('handsontable');
  493. }
  494. });
  495. it('should open editor after pressing a printable character', function() {
  496. var hot = handsontable({
  497. data: Handsontable.helper.createSpreadsheetData(3, 3)
  498. });
  499. selectCell(0, 0);
  500. var editorHolder = $('.handsontableInputHolder');
  501. // var editorInput = editorHolder.find('.handsontableInput');
  502. expect(editorHolder.is(':visible')).toBe(false);
  503. // var keyboardEvent = $.Event('keydown', {
  504. // keyCode: 'a'.charCodeAt(0)
  505. // });
  506. // this.$container.trigger(keyboardEvent);
  507. this.$container.simulate('keydown', {
  508. keyCode: 'a'.charCodeAt(0)
  509. });
  510. expect(editorHolder.is(':visible')).toBe(true);
  511. });
  512. it('should open editor after pressing a printable character with shift key', function() {
  513. var hot = handsontable({
  514. data: Handsontable.helper.createSpreadsheetData(3, 3)
  515. });
  516. selectCell(0, 0);
  517. var editorHolder = $('.handsontableInputHolder');
  518. expect(editorHolder.is(':visible')).toBe(false);
  519. /**
  520. * To reliably mimic SHIFT+SOME_KEY combination we have to trigger two events.
  521. * First we need to trigger keydown event with SHIFT keyCode (16)
  522. * and then trigger a keydown event with keyCode of SOME_KEY and shiftKey property set to true
  523. */
  524. // var shiftKeyboardEvent = $.Event('keydown', {
  525. // keyCode: 16, //shift
  526. // shiftKey: true
  527. // });
  528. //
  529. // var keyboardEvent = $.Event('keydown', {
  530. // keyCode: 'a'.charCodeAt(0),
  531. // shiftKey: true
  532. // });
  533. this.$container.simulate('keydown', {
  534. keyCode: 'a'.charCodeAt(0),
  535. shiftKey: true
  536. });
  537. // this.$container.trigger(shiftKeyboardEvent);
  538. // this.$container.trigger(keyboardEvent);
  539. expect(editorHolder.is(':visible')).toBe(true);
  540. });
  541. it('should be able to open editor after clearing cell data with DELETE', function() {
  542. var hot = handsontable({
  543. data: Handsontable.helper.createSpreadsheetData(3, 3)
  544. });
  545. selectCell(0, 0);
  546. var editorHolder = $('.handsontableInputHolder');
  547. expect(editorHolder.is(':visible')).toBe(false);
  548. this.$container.simulate('keydown', {
  549. keyCode: 46
  550. });
  551. this.$container.simulate('keydown', {
  552. keyCode: 'a'.charCodeAt(0)
  553. });
  554. expect(editorHolder.is(':visible')).toBe(true);
  555. });
  556. it('should be able to open editor after clearing cell data with BACKSPACE', function() {
  557. var hot = handsontable({
  558. data: Handsontable.helper.createSpreadsheetData(3, 3)
  559. });
  560. selectCell(0, 0);
  561. var editorHolder = $('.handsontableInputHolder');
  562. expect(editorHolder.is(':visible')).toBe(false);
  563. this.$container.simulate('keydown', {
  564. keyCode: 8 // backspace
  565. });
  566. this.$container.simulate('keydown', {
  567. keyCode: 'a'.charCodeAt(0)
  568. });
  569. expect(editorHolder.is(':visible')).toBe(true);
  570. });
  571. it('should scroll editor to a cell, if trying to edit cell that is outside of the viewport', () => {
  572. var hot = handsontable({
  573. data: Handsontable.helper.createSpreadsheetData(20, 20),
  574. width: 100,
  575. height: 50
  576. });
  577. selectCell(0, 0);
  578. expect(getCell(0, 0)).not.toBeNull();
  579. expect(getCell(19, 19)).toBeNull();
  580. hot.view.scrollViewport({row: 19, col: 19});
  581. hot.render();
  582. expect(getCell(0, 0)).toBeNull();
  583. expect(getCell(19, 19)).not.toBeNull();
  584. keyDown('enter');
  585. expect(getCell(0, 0)).not.toBeNull();
  586. expect(getCell(19, 19)).toBeNull();
  587. });
  588. it('should open empty editor after clearing cell value width BACKSPACE', () => {
  589. var hot = handsontable({
  590. data: Handsontable.helper.createSpreadsheetData(4, 4)
  591. });
  592. expect(getDataAtCell(0, 0)).toEqual('A1');
  593. selectCell(0, 0);
  594. keyDown(Handsontable.helper.KEY_CODES.BACKSPACE);
  595. expect(getDataAtCell(0, 0)).toEqual('');
  596. expect(hot.getActiveEditor().isOpened()).toBe(false);
  597. keyDown(Handsontable.helper.KEY_CODES.ENTER);
  598. expect(hot.getActiveEditor().isOpened()).toBe(true);
  599. expect(hot.getActiveEditor().getValue()).toEqual('');
  600. });
  601. it('should open empty editor after clearing cell value width DELETE', () => {
  602. var hot = handsontable({
  603. data: Handsontable.helper.createSpreadsheetData(4, 4)
  604. });
  605. expect(getDataAtCell(0, 0)).toEqual('A1');
  606. selectCell(0, 0);
  607. keyDown(Handsontable.helper.KEY_CODES.DELETE);
  608. expect(getDataAtCell(0, 0)).toEqual('');
  609. expect(hot.getActiveEditor().isOpened()).toBe(false);
  610. keyDown(Handsontable.helper.KEY_CODES.ENTER);
  611. expect(hot.getActiveEditor().isOpened()).toBe(true);
  612. expect(hot.getActiveEditor().getValue()).toEqual('');
  613. });
  614. it('should not open editor after hitting ALT (#1239)', () => {
  615. var hot = handsontable({
  616. data: Handsontable.helper.createSpreadsheetData(4, 4)
  617. });
  618. expect(getDataAtCell(0, 0)).toEqual('A1');
  619. selectCell(0, 0);
  620. keyDown(Handsontable.helper.KEY_CODES.ALT);
  621. expect(hot.getActiveEditor().isOpened()).toBe(false);
  622. });
  623. it('should open editor at the same coordinates as the edited cell', () => {
  624. var hot = handsontable({
  625. data: Handsontable.helper.createSpreadsheetData(16, 8),
  626. fixedColumnsLeft: 2,
  627. fixedRowsTop: 2
  628. });
  629. var mainHolder = hot.view.wt.wtTable.holder;
  630. // corner
  631. selectCell(1, 1);
  632. keyDown(Handsontable.helper.KEY_CODES.ENTER);
  633. var $inputHolder = $('.handsontableInputHolder');
  634. expect($(getCell(1, 1)).offset().left).toEqual($inputHolder.offset().left + 1);
  635. expect($(getCell(1, 1)).offset().top).toEqual($inputHolder.offset().top + 1);
  636. // top
  637. selectCell(1, 4);
  638. keyDown(Handsontable.helper.KEY_CODES.ENTER);
  639. expect($(getCell(1, 4)).offset().left).toEqual($inputHolder.offset().left + 1);
  640. expect($(getCell(1, 4)).offset().top).toEqual($inputHolder.offset().top + 1);
  641. // left
  642. selectCell(4, 1);
  643. keyDown(Handsontable.helper.KEY_CODES.ENTER);
  644. expect($(getCell(4, 1)).offset().left).toEqual($inputHolder.offset().left + 1);
  645. expect($(getCell(4, 1)).offset().top).toEqual($inputHolder.offset().top + 1);
  646. // non-fixed
  647. selectCell(4, 4);
  648. keyDown(Handsontable.helper.KEY_CODES.ENTER);
  649. expect($(getCell(4, 4)).offset().left).toEqual($inputHolder.offset().left + 1);
  650. expect($(getCell(4, 4)).offset().top).toEqual($inputHolder.offset().top + 1);
  651. $(mainHolder).scrollTop(1000);
  652. });
  653. it('should open editor at the same coordinates as the edited cell after the table had been scrolled (corner)', () => {
  654. var hot = handsontable({
  655. data: Handsontable.helper.createSpreadsheetData(16, 8),
  656. fixedColumnsLeft: 2,
  657. fixedRowsTop: 2
  658. });
  659. var $holder = $(hot.view.wt.wtTable.holder);
  660. $holder.scrollTop(100);
  661. $holder.scrollLeft(100);
  662. hot.render();
  663. // corner
  664. selectCell(1, 1);
  665. var currentCell = hot.getCell(1, 1, true);
  666. var left = $(currentCell).offset().left;
  667. var top = $(currentCell).offset().top;
  668. var $inputHolder = $('.handsontableInputHolder');
  669. keyDown(Handsontable.helper.KEY_CODES.ENTER);
  670. expect(left).toEqual($inputHolder.offset().left + 1);
  671. expect(top).toEqual($inputHolder.offset().top + 1);
  672. });
  673. it('should open editor at the same coordinates as the edited cell after the table had been scrolled (top)', (done) => {
  674. var hot = handsontable({
  675. data: Handsontable.helper.createSpreadsheetData(50, 50),
  676. fixedColumnsLeft: 2,
  677. fixedRowsTop: 2
  678. });
  679. var $holder = $(hot.view.wt.wtTable.holder);
  680. $holder[0].scrollTop = 500;
  681. setTimeout(() => {
  682. $holder[0].scrollLeft = 500;
  683. }, 100);
  684. setTimeout(() => {
  685. // top
  686. selectCell(1, 6);
  687. }, 200);
  688. setTimeout(() => {
  689. var currentCell = hot.getCell(1, 6, true);
  690. var left = $(currentCell).offset().left;
  691. var top = $(currentCell).offset().top;
  692. var $inputHolder = $('.handsontableInputHolder');
  693. keyDown(Handsontable.helper.KEY_CODES.ENTER);
  694. expect(left).toEqual($inputHolder.offset().left + 1);
  695. expect(top).toEqual($inputHolder.offset().top + 1);
  696. done();
  697. }, 300);
  698. });
  699. it('should open editor at the same coordinates as the edited cell after the table had been scrolled (left)', () => {
  700. var hot = handsontable({
  701. data: Handsontable.helper.createSpreadsheetData(50, 50),
  702. fixedColumnsLeft: 2,
  703. fixedRowsTop: 2
  704. });
  705. var $holder = $(hot.view.wt.wtTable.holder);
  706. $holder.scrollTop(500);
  707. $holder.scrollLeft(500);
  708. hot.render();
  709. // left
  710. selectCell(6, 1);
  711. var currentCell = hot.getCell(6, 1, true);
  712. var left = $(currentCell).offset().left;
  713. var top = $(currentCell).offset().top;
  714. var $inputHolder = $('.handsontableInputHolder');
  715. keyDown(Handsontable.helper.KEY_CODES.ENTER);
  716. expect(left).toEqual($inputHolder.offset().left + 1);
  717. expect(top).toEqual($inputHolder.offset().top + 1);
  718. });
  719. it('should open editor at the same coordinates as the edited cell after the table had been scrolled (non-fixed)', () => {
  720. var hot = handsontable({
  721. data: Handsontable.helper.createSpreadsheetData(50, 50),
  722. fixedColumnsLeft: 2,
  723. fixedRowsTop: 2
  724. });
  725. var $holder = $(hot.view.wt.wtTable.holder);
  726. $holder.scrollTop(500);
  727. $holder.scrollLeft(500);
  728. hot.render();
  729. // non-fixed
  730. selectCell(7, 7);
  731. var currentCell = hot.getCell(7, 7, true);
  732. var left = $(currentCell).offset().left;
  733. var top = $(currentCell).offset().top;
  734. var $inputHolder = $('.handsontableInputHolder');
  735. keyDown(Handsontable.helper.KEY_CODES.ENTER);
  736. expect(left).toEqual($inputHolder.offset().left + 1);
  737. expect(top).toEqual($inputHolder.offset().top + 1);
  738. });
  739. it('should display editor with the proper size, when the edited column is beyond the tables container', function() {
  740. this.$container.css('overflow', '');
  741. var hot = handsontable({
  742. data: Handsontable.helper.createSpreadsheetData(3, 9)
  743. });
  744. selectCell(0, 7);
  745. keyDown(Handsontable.helper.KEY_CODES.ENTER);
  746. expect(Handsontable.dom.outerWidth(hot.getActiveEditor().TEXTAREA)).toBeAroundValue(Handsontable.dom.outerWidth(hot.getCell(0, 7)));
  747. });
  748. it('should display editor with the proper size, when editing a last row after the table is scrolled to the bottom', () => {
  749. var hot = handsontable({
  750. data: Handsontable.helper.createSpreadsheetData(3, 8),
  751. minSpareRows: 1,
  752. height: 100
  753. });
  754. selectCell(0, 2);
  755. keyDown(Handsontable.helper.KEY_CODES.ENTER);
  756. var regularHeight = Handsontable.dom.outerHeight(hot.getActiveEditor().TEXTAREA);
  757. selectCell(3, 2);
  758. keyDown(Handsontable.helper.KEY_CODES.ENTER);
  759. keyDown(Handsontable.helper.KEY_CODES.ENTER);
  760. keyDown(Handsontable.helper.KEY_CODES.ENTER);
  761. // lame check, needs investigating why sometimes it leaves 2px error
  762. if (Handsontable.dom.outerHeight(hot.getActiveEditor().TEXTAREA) == regularHeight) {
  763. expect(Handsontable.dom.outerHeight(hot.getActiveEditor().TEXTAREA)).toEqual(regularHeight);
  764. } else {
  765. expect(Handsontable.dom.outerHeight(hot.getActiveEditor().TEXTAREA)).toEqual(regularHeight - 2);
  766. }
  767. });
  768. it('should render the text without trimming out the whitespace, if trimWhitespace is set to false', function() {
  769. this.$container.css('overflow', '');
  770. var hot = handsontable({
  771. data: Handsontable.helper.createSpreadsheetData(3, 9),
  772. trimWhitespace: false
  773. });
  774. selectCell(0, 2);
  775. keyDown(Handsontable.helper.KEY_CODES.ENTER);
  776. hot.getActiveEditor().TEXTAREA.value = ' test of whitespace ';
  777. keyDown(Handsontable.helper.KEY_CODES.ENTER);
  778. expect(getDataAtCell(0, 2).length).toEqual(37);
  779. });
  780. it('should insert new line on caret position when pressing ALT + ENTER', () => {
  781. var data = [
  782. ['Maserati', 'Mazda'],
  783. ['Honda', 'Mini']
  784. ];
  785. var hot = handsontable({
  786. data
  787. });
  788. selectCell(0, 0);
  789. keyDown(Handsontable.helper.KEY_CODES.ENTER);
  790. var $editorInput = $('.handsontableInput');
  791. Handsontable.dom.setCaretPosition($editorInput[0], 2);
  792. $editorInput.simulate('keydown', {
  793. altKey: true,
  794. keyCode: Handsontable.helper.KEY_CODES.ENTER
  795. });
  796. expect(hot.getActiveEditor().TEXTAREA.value).toEqual('Ma\nserati');
  797. });
  798. it('should be displayed and resized properly, so it doesn\'t exceed the viewport dimensions', () => {
  799. var data = [
  800. ['', '', '', '', ''],
  801. ['', 'The Dude abides. I don\'t know about you but I take comfort in that. It\'s good knowin\' he\'s out there. The ' +
  802. 'Dude. Takin\' \'er easy for all us sinners. Shoosh. I sure hope he makes the finals.', '', '', ''],
  803. ['', '', '', '', '']
  804. ];
  805. var hot = handsontable({
  806. data,
  807. colWidths: 40,
  808. width: 300,
  809. height: 200,
  810. minSpareRows: 20,
  811. minSpareCols: 20
  812. });
  813. selectCell(1, 1);
  814. keyDown(Handsontable.helper.KEY_CODES.ENTER);
  815. var $editorInput = $('.handsontableInput');
  816. var $editedCell = $(hot.getCell(1, 1));
  817. expect($editorInput.outerWidth()).toEqual(hot.view.wt.wtTable.holder.clientWidth - $editedCell.position().left + 1);
  818. hot.view.wt.scrollHorizontal(3);
  819. hot.render();
  820. expect($editorInput.width() + $editorInput.offset().left).toBeLessThan(hot.view.wt.wtTable.holder.clientWidth);
  821. });
  822. it('should resize editor to properly size after focus', (done) => {
  823. var data = [
  824. ['', '', '', '', '', '', '', '', '', '', ''],
  825. ['', '', '', '', '', '', '', '', '', '', ''],
  826. ['', '', '', '', '', '', '', '', '', '', ''],
  827. ['', '', '', '', '', '', '', '', '', '', ''],
  828. ['', '', '', '', '', '', '', '', '', '', 'sadiasdoadoajdoasjdoij doi ajdoiasjdasoidasoid'],
  829. ['', '', '', '', '', '', '', '', '', '', ''],
  830. ['', '', '', '', '', '', '', '', '', '', ''],
  831. ['', '', '', '', '', '', '', '', '', '', ''],
  832. ['', '', '', '', '', '', '', '', '', '', ''],
  833. ['', '', '', '', '', '', '', '', '', '', ''],
  834. ];
  835. var hot = handsontable({
  836. data,
  837. colWidths: 40,
  838. rowHeights: 25,
  839. width: 500,
  840. height: 220
  841. });
  842. selectCell(4, 10);
  843. keyDown(Handsontable.helper.KEY_CODES.ENTER);
  844. var $editorInput = $('.handsontableInput');
  845. setTimeout(() => {
  846. expect([105, 119]).toEqual(jasmine.arrayContaining([$editorInput.height()]));
  847. done();
  848. }, 150);
  849. });
  850. });