ec64dd614f96526756cc2fe03fe5841b2fd1409e99ba146a19aca9cd688f11650b05465e6ce16021b8a363e12ab5b68ece901143fb12c2908f58595b4b9e27 72 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394
  1. describe('ColumnSorting', () => {
  2. var id = 'testContainer';
  3. beforeEach(function() {
  4. this.$container = $(`<div id="${id}" style="overflow: auto; width: 300px; height: 200px;"></div>`).appendTo('body');
  5. this.sortByColumn = function(columnIndex) {
  6. var element = this.$container.find(`th span.columnSorting:eq(${columnIndex})`);
  7. element.simulate('mousedown');
  8. element.simulate('mouseup');
  9. };
  10. });
  11. afterEach(function() {
  12. if (this.$container) {
  13. destroy();
  14. this.$container.remove();
  15. }
  16. });
  17. var arrayOfObjects = function() {
  18. return [
  19. {id: 1, name: 'Ted', lastName: 'Right'},
  20. {id: 2, name: 'Frank', lastName: 'Honest'},
  21. {id: 3, name: 'Joan', lastName: 'Well'},
  22. {id: 4, name: 'Sid', lastName: 'Strong'},
  23. {id: 5, name: 'Jane', lastName: 'Neat'},
  24. {id: 6, name: 'Chuck', lastName: 'Jackson'},
  25. {id: 7, name: 'Meg', lastName: 'Jansen'},
  26. {id: 8, name: 'Rob', lastName: 'Norris'},
  27. {id: 9, name: 'Sean', lastName: 'O\'Hara'},
  28. {id: 10, name: 'Eve', lastName: 'Branson'}
  29. ];
  30. };
  31. it('should sort table by first visible column', function() {
  32. var hot = handsontable({
  33. data: [
  34. [1, 9, 3, 4, 5, 6, 7, 8, 9],
  35. [9, 8, 7, 6, 5, 4, 3, 2, 1],
  36. [8, 7, 6, 5, 4, 3, 3, 1, 9],
  37. [0, 3, 0, 5, 6, 7, 8, 9, 1]
  38. ],
  39. colHeaders: true,
  40. columnSorting: true
  41. });
  42. var htCore = getHtCore();
  43. expect(htCore.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('1');
  44. expect(htCore.find('tbody tr:eq(0) td:eq(1)').text()).toEqual('9');
  45. expect(htCore.find('tbody tr:eq(0) td:eq(2)').text()).toEqual('3');
  46. expect(htCore.find('tbody tr:eq(0) td:eq(3)').text()).toEqual('4');
  47. this.sortByColumn(0);
  48. expect(htCore.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('0');
  49. expect(htCore.find('tbody tr:eq(0) td:eq(1)').text()).toEqual('3');
  50. expect(htCore.find('tbody tr:eq(0) td:eq(2)').text()).toEqual('0');
  51. expect(htCore.find('tbody tr:eq(0) td:eq(3)').text()).toEqual('5');
  52. });
  53. it('should apply stable sort function #3606', () => {
  54. var hot = handsontable({
  55. data: [
  56. ['mercedes1', 'Mercedes', 'A 160', '01/14/2007'],
  57. ['citroen1', 'Citroen', 'C4 Coupe', '12/01/2007'],
  58. ['opel1', 'Opel', 'Astra', '02/02/2006'],
  59. ['bmw1', 'BMW', '320i Coupe', '07/24/2009'],
  60. ['citroen2', 'Citroen', 'C4 Coupe', '12/01/2012'],
  61. ['opel2', 'Opel', 'Astra', '02/02/2004'],
  62. ['mercedes2', 'Mercedes', 'A 160', '01/14/2008'],
  63. ['citroen3', 'Citroen', 'C4 Coupe', '12/01/2007'],
  64. ['mercedes3', 'Mercedes', 'A 160', '01/14/2009'],
  65. ['opel3', 'Opel', 'Astra', '02/02/2006'],
  66. ['bmw2', 'BMW', '320i Coupe', '07/24/2013'],
  67. ['bmw3', 'BMW', '320i Coupe', '07/24/2012'],
  68. ],
  69. columns: [
  70. {},
  71. {},
  72. {
  73. type: 'date',
  74. dateFormat: 'mm/dd/yy'
  75. },
  76. {
  77. type: 'numeric'
  78. }
  79. ],
  80. columnSorting: true
  81. });
  82. hot.sort(1, true); // ASC
  83. expect(hot.getDataAtCol(0)).toEqual([
  84. 'bmw1', 'bmw2', 'bmw3',
  85. 'citroen1', 'citroen2', 'citroen3',
  86. 'mercedes1', 'mercedes2', 'mercedes3',
  87. 'opel1', 'opel2', 'opel3'
  88. ]);
  89. hot.sort(1, false); // DESC
  90. expect(hot.getDataAtCol(0)).toEqual([
  91. 'opel1', 'opel2', 'opel3',
  92. 'mercedes1', 'mercedes2', 'mercedes3',
  93. 'citroen1', 'citroen2', 'citroen3',
  94. 'bmw1', 'bmw2', 'bmw3'
  95. ]);
  96. });
  97. it('should not throw error when trying run handsontable with columnSorting and autoRowSize in the same time.', () => {
  98. var errors = 0;
  99. try {
  100. handsontable({
  101. data: arrayOfObjects(),
  102. autoRowSize: true,
  103. columnSorting: true
  104. });
  105. } catch (e) {
  106. errors++;
  107. }
  108. expect(errors).toBe(0);
  109. });
  110. it('should sort numbers descending after 2 clicks on table header', function() {
  111. handsontable({
  112. data: arrayOfObjects(),
  113. colHeaders: true,
  114. columnSorting: true
  115. });
  116. this.sortByColumn(0);
  117. this.sortByColumn(0);
  118. expect(this.$container.find('tr td').first().html()).toEqual('10');
  119. });
  120. it('should remove specified row from sorted table and NOT sort the table again', function() {
  121. var hot = handsontable({
  122. data: [
  123. [1, 'B'],
  124. [3, 'D'],
  125. [2, 'A'],
  126. [0, 'C']
  127. ],
  128. colHeaders: true,
  129. columnSorting: true
  130. });
  131. this.sortByColumn(0);
  132. var htCore = getHtCore();
  133. expect(htCore.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('0');
  134. expect(htCore.find('tbody tr:eq(1) td:eq(0)').text()).toEqual('1');
  135. expect(htCore.find('tbody tr:eq(2) td:eq(0)').text()).toEqual('2');
  136. expect(htCore.find('tbody tr:eq(3) td:eq(0)').text()).toEqual('3');
  137. expect(htCore.find('tbody tr').length).toEqual(4);
  138. // Now if sort is launched, sorting ordered will be reversed
  139. hot.sortOrder = false;
  140. hot.alter('remove_row', 0);
  141. expect(htCore.find('tbody tr').length).toEqual(3);
  142. expect(htCore.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('1');
  143. expect(htCore.find('tbody tr:eq(1) td:eq(0)').text()).toEqual('2');
  144. expect(htCore.find('tbody tr:eq(2) td:eq(0)').text()).toEqual('3');
  145. });
  146. it('should add an empty row to sorted table', function() {
  147. var hot = handsontable({
  148. data: [
  149. [1, 'B'],
  150. [0, 'A'],
  151. [3, 'D'],
  152. [2, 'C']
  153. ],
  154. colHeaders: true,
  155. columnSorting: true
  156. });
  157. this.sortByColumn(0);
  158. var htCore = getHtCore();
  159. expect(htCore.find('tbody tr').length).toEqual(4);
  160. expect(htCore.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('0');
  161. expect(htCore.find('tbody tr:eq(1) td:eq(0)').text()).toEqual('1');
  162. expect(htCore.find('tbody tr:eq(2) td:eq(0)').text()).toEqual('2');
  163. expect(htCore.find('tbody tr:eq(3) td:eq(0)').text()).toEqual('3');
  164. hot.alter('insert_row', 1, 2);
  165. expect(htCore.find('tbody tr').length).toEqual(6);
  166. expect(htCore.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('0');
  167. expect(htCore.find('tbody tr:eq(1) td:eq(0)').text()).toEqual('');
  168. expect(htCore.find('tbody tr:eq(2) td:eq(0)').text()).toEqual('');
  169. expect(htCore.find('tbody tr:eq(3) td:eq(0)').text()).toEqual('1');
  170. expect(htCore.find('tbody tr:eq(4) td:eq(0)').text()).toEqual('2');
  171. expect(htCore.find('tbody tr:eq(5) td:eq(0)').text()).toEqual('3');
  172. });
  173. it('should add an empty row to sorted table at a given index', function() {
  174. var hot = handsontable({
  175. data: [
  176. [1, 'B'],
  177. [0, 'A'],
  178. [3, 'D'],
  179. [2, 'C']
  180. ],
  181. colHeaders: true,
  182. columnSorting: true
  183. });
  184. var htCore = getHtCore();
  185. this.sortByColumn(0);
  186. expect(htCore.find('tbody tr:eq(3) td:eq(0)').text()).toEqual('3');
  187. expect(htCore.find('tbody tr:eq(4) td:eq(0)').text()).toEqual('');
  188. hot.alter('insert_row', 2);
  189. expect(htCore.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('0');
  190. expect(htCore.find('tbody tr:eq(1) td:eq(0)').text()).toEqual('1');
  191. expect(htCore.find('tbody tr:eq(2) td:eq(0)').text()).toEqual('');
  192. expect(htCore.find('tbody tr:eq(2) td:eq(0)').text()).toEqual('');
  193. expect(htCore.find('tbody tr:eq(2) td:eq(0)').text()).toEqual('');
  194. expect(htCore.find('tbody tr:eq(3) td:eq(0)').text()).toEqual('2');
  195. });
  196. it('should NOT sort the table after value update in sorted column', function() {
  197. var hot = handsontable({
  198. data: [
  199. [1, 'B'],
  200. [0, 'A'],
  201. [3, 'D'],
  202. [2, 'C']
  203. ],
  204. colHeaders: true,
  205. columnSorting: true
  206. });
  207. var htCore = getHtCore();
  208. expect(htCore.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('1');
  209. this.sortByColumn(0);
  210. this.sortByColumn(0);
  211. expect(htCore.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('3');
  212. expect(htCore.find('tbody tr:eq(1) td:eq(0)').text()).toEqual('2');
  213. hot.setDataAtCell(1, 0, 20);
  214. render();
  215. expect(htCore.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('3');
  216. expect(htCore.find('tbody tr:eq(1) td:eq(0)').text()).toEqual('20');
  217. });
  218. it('defaultSort comparing function shouldn\'t change order when comparing empty string, null and undefined', () => {
  219. var hot = handsontable({});
  220. var defaultSort = hot.getPlugin('columnSorting').defaultSort;
  221. expect(defaultSort(false, {})(['key1', null], ['key2', null])).toEqual(0);
  222. expect(defaultSort(false, {})(['key1', ''], ['key2', ''])).toEqual(0);
  223. expect(defaultSort(false, {})(['key1', undefined], ['key2', undefined])).toEqual(0);
  224. expect(defaultSort(false, {})(['key1', ''], ['key2', null])).toEqual(0);
  225. expect(defaultSort(false, {})(['key1', null], ['key2', ''])).toEqual(0);
  226. expect(defaultSort(false, {})(['key1', ''], ['key2', undefined])).toEqual(0);
  227. expect(defaultSort(false, {})(['key1', undefined], ['key2', ''])).toEqual(0);
  228. expect(defaultSort(false, {})(['key1', null], ['key2', undefined])).toEqual(0);
  229. expect(defaultSort(false, {})(['key1', undefined], ['key2', null])).toEqual(0);
  230. });
  231. it('should place empty strings, null and undefined values at proper position (stability of default comparing function)', () => {
  232. var hot = handsontable({
  233. data: [
  234. [null, 'Ted Right'],
  235. [undefined, 'Jane Neat'],
  236. [null, 'Meg Jansen'],
  237. ['', 'Sean Hara'],
  238. ['', 'Eve Branson'],
  239. [6, 'Frank Honest'],
  240. [7, 'Joan Well'],
  241. [8, 'Sid Strong'],
  242. [9, 'Chuck Jackson'],
  243. [10, 'Rob Norris'],
  244. [11, 'Eve Well']
  245. ],
  246. columnSorting: true
  247. });
  248. hot.sort(0, true); // ASC
  249. expect(hot.getDataAtCol(1)).toEqual([
  250. 'Frank Honest',
  251. 'Joan Well',
  252. 'Sid Strong',
  253. 'Chuck Jackson',
  254. 'Rob Norris',
  255. 'Eve Well',
  256. // empty cells below
  257. 'Ted Right',
  258. 'Jane Neat',
  259. 'Meg Jansen',
  260. 'Sean Hara',
  261. 'Eve Branson',
  262. ]);
  263. hot.sort(0, false); // DESC
  264. expect(hot.getDataAtCol(1)).toEqual([
  265. 'Eve Well',
  266. 'Rob Norris',
  267. 'Chuck Jackson',
  268. 'Sid Strong',
  269. 'Joan Well',
  270. 'Frank Honest',
  271. // empty cells below
  272. 'Ted Right',
  273. 'Jane Neat',
  274. 'Meg Jansen',
  275. 'Sean Hara',
  276. 'Eve Branson',
  277. ]);
  278. });
  279. it('should place empty strings, null and undefined values at proper position when `sortEmptyCells` option is enabled ' +
  280. '(API call, data type: default)', () => {
  281. var hot = handsontable({
  282. data: [
  283. [6, 'Frank Honest'],
  284. [null, 'Ted Right'],
  285. [7, 'Joan Well'],
  286. [8, 'Sid Strong'],
  287. [undefined, 'Jane Neat'],
  288. [9, 'Chuck Jackson'],
  289. [null, 'Meg Jansen'],
  290. [10, 'Rob Norris'],
  291. ['', 'Sean Hara'],
  292. ['', 'Eve Branson']
  293. ],
  294. columnSorting: {
  295. sortEmptyCells: true
  296. }
  297. });
  298. hot.sort(0, true); // ASC
  299. expect(hot.getDataAtCol(1)).toEqual([
  300. 'Ted Right',
  301. 'Jane Neat',
  302. 'Meg Jansen',
  303. 'Sean Hara',
  304. 'Eve Branson',
  305. // empty cells above
  306. 'Frank Honest',
  307. 'Joan Well',
  308. 'Sid Strong',
  309. 'Chuck Jackson',
  310. 'Rob Norris'
  311. ]);
  312. hot.sort(0, false); // DESC
  313. expect(hot.getDataAtCol(1)).toEqual([
  314. 'Rob Norris',
  315. 'Chuck Jackson',
  316. 'Sid Strong',
  317. 'Joan Well',
  318. 'Frank Honest',
  319. // empty cells below
  320. 'Ted Right',
  321. 'Jane Neat',
  322. 'Meg Jansen',
  323. 'Sean Hara',
  324. 'Eve Branson',
  325. ]);
  326. });
  327. it('should place empty strings, null and undefined values at proper position when `sortEmptyCells` ' +
  328. 'option is enabled and `column` property of `columnSorting` option is set (data type: default)', function() {
  329. var hot = handsontable({
  330. data: [
  331. [6, 'Frank Honest'],
  332. [null, 'Ted Right'],
  333. [7, 'Joan Well'],
  334. [8, 'Sid Strong'],
  335. [undefined, 'Jane Neat'],
  336. [9, 'Chuck Jackson'],
  337. [null, 'Meg Jansen'],
  338. [10, 'Rob Norris'],
  339. ['', 'Sean Hara'],
  340. ['', 'Eve Branson']
  341. ],
  342. columnSorting: {
  343. sortEmptyCells: true,
  344. sortOrder: true,
  345. column: 0
  346. }
  347. });
  348. // ASC
  349. expect(hot.getDataAtCol(1)).toEqual([
  350. 'Ted Right',
  351. 'Jane Neat',
  352. 'Meg Jansen',
  353. 'Sean Hara',
  354. 'Eve Branson',
  355. // empty cells above
  356. 'Frank Honest',
  357. 'Joan Well',
  358. 'Sid Strong',
  359. 'Chuck Jackson',
  360. 'Rob Norris'
  361. ]);
  362. if (this.$container) {
  363. destroy();
  364. this.$container.remove();
  365. }
  366. hot = handsontable({
  367. data: [
  368. [6, 'Frank Honest'],
  369. [null, 'Ted Right'],
  370. [7, 'Joan Well'],
  371. [8, 'Sid Strong'],
  372. [undefined, 'Jane Neat'],
  373. [9, 'Chuck Jackson'],
  374. [null, 'Meg Jansen'],
  375. [10, 'Rob Norris'],
  376. ['', 'Sean Hara'],
  377. ['', 'Eve Branson']
  378. ],
  379. columnSorting: {
  380. sortEmptyCells: true,
  381. sortOrder: false,
  382. column: 0
  383. }
  384. });
  385. // DESC
  386. expect(hot.getDataAtCol(1)).toEqual([
  387. 'Rob Norris',
  388. 'Chuck Jackson',
  389. 'Sid Strong',
  390. 'Joan Well',
  391. 'Frank Honest',
  392. // empty cells below
  393. 'Ted Right',
  394. 'Jane Neat',
  395. 'Meg Jansen',
  396. 'Sean Hara',
  397. 'Eve Branson',
  398. ]);
  399. });
  400. it('should place empty strings, null and undefined values at proper position when `sortEmptyCells` ' +
  401. 'option is enabled and `column` property of `columnSorting` option is set (data type: numeric)', function() {
  402. var hot = handsontable({
  403. data: [
  404. [6, 'Frank Honest'],
  405. [null, 'Ted Right'],
  406. [7, 'Joan Well'],
  407. [8, 'Sid Strong'],
  408. [undefined, 'Jane Neat'],
  409. [9, 'Chuck Jackson'],
  410. [null, 'Meg Jansen'],
  411. [10, 'Rob Norris'],
  412. ['', 'Sean Hara'],
  413. ['', 'Eve Branson']
  414. ],
  415. columns: [
  416. {
  417. type: 'numeric'
  418. },
  419. {}
  420. ],
  421. columnSorting: {
  422. sortEmptyCells: true,
  423. sortOrder: true,
  424. column: 0
  425. }
  426. });
  427. // ASC
  428. expect(hot.getDataAtCol(1)).toEqual([
  429. 'Ted Right',
  430. 'Jane Neat',
  431. 'Meg Jansen',
  432. 'Sean Hara',
  433. 'Eve Branson',
  434. // empty cells above
  435. 'Frank Honest',
  436. 'Joan Well',
  437. 'Sid Strong',
  438. 'Chuck Jackson',
  439. 'Rob Norris'
  440. ]);
  441. if (this.$container) {
  442. destroy();
  443. this.$container.remove();
  444. }
  445. hot = handsontable({
  446. data: [
  447. [6, 'Frank Honest'],
  448. [null, 'Ted Right'],
  449. [7, 'Joan Well'],
  450. [8, 'Sid Strong'],
  451. [undefined, 'Jane Neat'],
  452. [9, 'Chuck Jackson'],
  453. [null, 'Meg Jansen'],
  454. [10, 'Rob Norris'],
  455. ['', 'Sean Hara'],
  456. ['', 'Eve Branson']
  457. ],
  458. columnSorting: {
  459. sortEmptyCells: true,
  460. sortOrder: false,
  461. column: 0
  462. }
  463. });
  464. // DESC
  465. expect(hot.getDataAtCol(1)).toEqual([
  466. 'Rob Norris',
  467. 'Chuck Jackson',
  468. 'Sid Strong',
  469. 'Joan Well',
  470. 'Frank Honest',
  471. // empty cells below
  472. 'Ted Right',
  473. 'Jane Neat',
  474. 'Meg Jansen',
  475. 'Sean Hara',
  476. 'Eve Branson',
  477. ]);
  478. });
  479. describe('data type: date', () => {
  480. it('dateSort comparing function shouldn\'t change order when comparing empty string, null and undefined', () => {
  481. var hot = handsontable({});
  482. var dateSort = hot.getPlugin('columnSorting').dateSort;
  483. expect(dateSort(false, {})(['key1', null], ['key2', null])).toEqual(0);
  484. expect(dateSort(false, {})(['key1', ''], ['key2', ''])).toEqual(0);
  485. expect(dateSort(false, {})(['key1', undefined], ['key2', undefined])).toEqual(0);
  486. expect(dateSort(false, {})(['key1', ''], ['key2', null])).toEqual(0);
  487. expect(dateSort(false, {})(['key1', null], ['key2', ''])).toEqual(0);
  488. expect(dateSort(false, {})(['key1', ''], ['key2', undefined])).toEqual(0);
  489. expect(dateSort(false, {})(['key1', undefined], ['key2', ''])).toEqual(0);
  490. expect(dateSort(false, {})(['key1', null], ['key2', undefined])).toEqual(0);
  491. expect(dateSort(false, {})(['key1', undefined], ['key2', null])).toEqual(0);
  492. });
  493. it('should place empty strings, null and undefined values at proper position when `sortEmptyCells` ' +
  494. 'option is enabled and `column` property of `columnSorting` option is set', function() {
  495. var hot = handsontable({
  496. data: [
  497. ['Citroen1', 'C4 Coupe', null],
  498. ['Mercedes1', 'A 160', '12/01/2008'],
  499. ['Mercedes2', 'A 160', '01/14/2006'],
  500. ['Citroen2', 'C4 Coupe', undefined],
  501. ['Audi1', 'A4 Avant', '11/19/2011'],
  502. ['Opel1', 'Astra', '02/02/2004'],
  503. ['Citroen3', 'C4 Coupe', null],
  504. ['BMW1', '320i Coupe', '07/24/2011'],
  505. ['Citroen4', 'C4 Coupe', ''],
  506. ['Citroen5', 'C4 Coupe', ''],
  507. ],
  508. columns: [
  509. {},
  510. {},
  511. {
  512. type: 'date',
  513. dateFormat: 'MM/DD/YYYY'
  514. }
  515. ],
  516. columnSorting: {
  517. sortEmptyCells: true,
  518. sortOrder: true,
  519. column: 2
  520. }
  521. });
  522. // ASC
  523. expect(hot.getDataAtCol(0)).toEqual([
  524. 'Citroen1',
  525. 'Citroen2',
  526. 'Citroen3',
  527. 'Citroen4',
  528. 'Citroen5',
  529. // empty cells above
  530. 'Opel1',
  531. 'Mercedes2',
  532. 'Mercedes1',
  533. 'BMW1',
  534. 'Audi1'
  535. ]);
  536. if (this.$container) {
  537. destroy();
  538. this.$container.remove();
  539. }
  540. hot = handsontable({
  541. data: [
  542. ['Citroen1', 'C4 Coupe', null],
  543. ['Mercedes1', 'A 160', '12/01/2008'],
  544. ['Mercedes2', 'A 160', '01/14/2006'],
  545. ['Citroen2', 'C4 Coupe', undefined],
  546. ['Audi1', 'A4 Avant', '11/19/2011'],
  547. ['Opel1', 'Astra', '02/02/2004'],
  548. ['Citroen3', 'C4 Coupe', null],
  549. ['BMW1', '320i Coupe', '07/24/2011'],
  550. ['Citroen4', 'C4 Coupe', ''],
  551. ['Citroen5', 'C4 Coupe', ''],
  552. ],
  553. columns: [
  554. {},
  555. {},
  556. {
  557. type: 'date',
  558. dateFormat: 'MM/DD/YYYY'
  559. }
  560. ],
  561. columnSorting: {
  562. sortEmptyCells: true,
  563. sortOrder: false,
  564. column: 2
  565. }
  566. });
  567. // DESC
  568. expect(hot.getDataAtCol(0)).toEqual([
  569. 'Audi1',
  570. 'BMW1',
  571. 'Mercedes1',
  572. 'Mercedes2',
  573. 'Opel1',
  574. // empty cells below
  575. 'Citroen1',
  576. 'Citroen2',
  577. 'Citroen3',
  578. 'Citroen4',
  579. 'Citroen5'
  580. ]);
  581. });
  582. it('should sort date columns (MM/DD/YYYY)', () => {
  583. var hot = handsontable({
  584. data: [
  585. ['Mercedes', 'A 160', '01/14/2006', 6999.9999],
  586. ['Citroen', 'C4 Coupe', '12/01/2008', 8330],
  587. ['Audi', 'A4 Avant', '11/19/2011', 33900],
  588. ['Opel', 'Astra', '02/02/2004', 7000],
  589. ['BMW', '320i Coupe', '07/24/2011', 30500]
  590. ],
  591. columns: [
  592. {},
  593. {},
  594. {
  595. type: 'date',
  596. dateFormat: 'MM/DD/YYYY'
  597. },
  598. {
  599. type: 'numeric'
  600. }
  601. ],
  602. colHeaders: true,
  603. columnSorting: true
  604. });
  605. hot.sort(2, true); // ASC
  606. expect(hot.getDataAtRow(0)).toEqual(['Opel', 'Astra', '02/02/2004', 7000]);
  607. expect(hot.getDataAtRow(1)).toEqual(['Mercedes', 'A 160', '01/14/2006', 6999.9999]);
  608. expect(hot.getDataAtRow(2)).toEqual(['Citroen', 'C4 Coupe', '12/01/2008', 8330]);
  609. expect(hot.getDataAtRow(3)).toEqual(['BMW', '320i Coupe', '07/24/2011', 30500]);
  610. expect(hot.getDataAtRow(4)).toEqual(['Audi', 'A4 Avant', '11/19/2011', 33900]);
  611. hot.sort(2, false); // DESC
  612. expect(hot.getDataAtRow(0)).toEqual(['Audi', 'A4 Avant', '11/19/2011', 33900]);
  613. expect(hot.getDataAtRow(1)).toEqual(['BMW', '320i Coupe', '07/24/2011', 30500]);
  614. expect(hot.getDataAtRow(2)).toEqual(['Citroen', 'C4 Coupe', '12/01/2008', 8330]);
  615. expect(hot.getDataAtRow(3)).toEqual(['Mercedes', 'A 160', '01/14/2006', 6999.9999]);
  616. expect(hot.getDataAtRow(4)).toEqual(['Opel', 'Astra', '02/02/2004', 7000]);
  617. });
  618. it('should sort date columns (DD/MM/YYYY)', () => {
  619. var hot = handsontable({
  620. data: [
  621. ['Mercedes', 'A 160', '01/12/2012', 6999.9999],
  622. ['Citroen', 'C4 Coupe', '12/01/2013', 8330],
  623. ['Audi', 'A4 Avant', '11/10/2014', 33900],
  624. ['Opel', 'Astra', '02/02/2015', 7000],
  625. ['BMW', '320i Coupe', '07/02/2013', 30500]
  626. ],
  627. columns: [
  628. {},
  629. {},
  630. {
  631. type: 'date',
  632. dateFormat: 'DD/MM/YYYY'
  633. },
  634. {
  635. type: 'numeric'
  636. }
  637. ],
  638. colHeaders: true,
  639. columnSorting: true
  640. });
  641. hot.sort(2, true); // ASC
  642. expect(hot.getDataAtRow(0)).toEqual(['Mercedes', 'A 160', '01/12/2012', 6999.9999]);
  643. expect(hot.getDataAtRow(1)).toEqual(['Citroen', 'C4 Coupe', '12/01/2013', 8330]);
  644. expect(hot.getDataAtRow(2)).toEqual(['BMW', '320i Coupe', '07/02/2013', 30500]);
  645. expect(hot.getDataAtRow(3)).toEqual(['Audi', 'A4 Avant', '11/10/2014', 33900]);
  646. expect(hot.getDataAtRow(4)).toEqual(['Opel', 'Astra', '02/02/2015', 7000]);
  647. hot.sort(2, false); // DESC
  648. expect(hot.getDataAtRow(0)).toEqual(['Opel', 'Astra', '02/02/2015', 7000]);
  649. expect(hot.getDataAtRow(1)).toEqual(['Audi', 'A4 Avant', '11/10/2014', 33900]);
  650. expect(hot.getDataAtRow(2)).toEqual(['BMW', '320i Coupe', '07/02/2013', 30500]);
  651. expect(hot.getDataAtRow(3)).toEqual(['Citroen', 'C4 Coupe', '12/01/2013', 8330]);
  652. expect(hot.getDataAtRow(4)).toEqual(['Mercedes', 'A 160', '01/12/2012', 6999.9999]);
  653. });
  654. it('should sort date columns (MMMM Do YYYY)', () => {
  655. var hot = handsontable({
  656. data: [
  657. ['Mercedes', 'A 160', 'October 28th 2016', 6999.9999],
  658. ['Citroen', 'C4 Coupe', 'October 27th 2001', 8330],
  659. ['Audi', 'A4 Avant', 'July 8th 1999', 33900],
  660. ['Opel', 'Astra', 'June 1st 2001', 7000],
  661. ['BMW', '320i Coupe', 'August 3rd 2001', 30500]
  662. ],
  663. columns: [
  664. {},
  665. {},
  666. {
  667. type: 'date',
  668. dateFormat: 'MMMM Do YYYY'
  669. },
  670. {
  671. type: 'numeric'
  672. }
  673. ],
  674. colHeaders: true,
  675. columnSorting: true
  676. });
  677. hot.sort(2, true); // ASC
  678. expect(hot.getDataAtRow(0)).toEqual(['Audi', 'A4 Avant', 'July 8th 1999', 33900]);
  679. expect(hot.getDataAtRow(1)).toEqual(['Opel', 'Astra', 'June 1st 2001', 7000]);
  680. expect(hot.getDataAtRow(2)).toEqual(['BMW', '320i Coupe', 'August 3rd 2001', 30500]);
  681. expect(hot.getDataAtRow(3)).toEqual(['Citroen', 'C4 Coupe', 'October 27th 2001', 8330]);
  682. expect(hot.getDataAtRow(4)).toEqual(['Mercedes', 'A 160', 'October 28th 2016', 6999.9999]);
  683. hot.sort(2, false); // DESC
  684. expect(hot.getDataAtRow(0)).toEqual(['Mercedes', 'A 160', 'October 28th 2016', 6999.9999]);
  685. expect(hot.getDataAtRow(1)).toEqual(['Citroen', 'C4 Coupe', 'October 27th 2001', 8330]);
  686. expect(hot.getDataAtRow(2)).toEqual(['BMW', '320i Coupe', 'August 3rd 2001', 30500]);
  687. expect(hot.getDataAtRow(3)).toEqual(['Opel', 'Astra', 'June 1st 2001', 7000]);
  688. expect(hot.getDataAtRow(4)).toEqual(['Audi', 'A4 Avant', 'July 8th 1999', 33900]);
  689. });
  690. it('should sort date columns along with empty and null values', () => {
  691. var hot = handsontable({
  692. data: [
  693. ['Mercedes', 'A 160', '01/14/2006', 6999.9999],
  694. ['Citroen', 'C4 Coupe', '12/01/2008', 8330],
  695. ['Citroen', 'C4 Coupe null', null, 8330],
  696. ['Citroen', 'C4 Coupe empty', '', 8330],
  697. ['Audi', 'A4 Avant', '11/19/2011', 33900],
  698. ['Opel', 'Astra', '02/02/2004', 7000],
  699. ['BMW', '320i Coupe', '07/24/2011', 30500]
  700. ],
  701. columns: [
  702. {},
  703. {},
  704. {
  705. type: 'date',
  706. dateFormat: 'mm/dd/yy'
  707. },
  708. {
  709. type: 'numeric'
  710. }
  711. ],
  712. colHeaders: true,
  713. columnSorting: true
  714. });
  715. hot.sort(2, true); // ASC
  716. expect(hot.getDataAtRow(0)).toEqual(['Mercedes', 'A 160', '01/14/2006', 6999.9999]);
  717. expect(hot.getDataAtRow(1)).toEqual(['Opel', 'Astra', '02/02/2004', 7000]);
  718. expect(hot.getDataAtRow(2)).toEqual(['BMW', '320i Coupe', '07/24/2011', 30500]);
  719. expect(hot.getDataAtRow(3)).toEqual(['Audi', 'A4 Avant', '11/19/2011', 33900]);
  720. expect(hot.getDataAtRow(4)).toEqual(['Citroen', 'C4 Coupe', '12/01/2008', 8330]);
  721. hot.sort(2, false); // DESC
  722. expect(hot.getDataAtRow(0)).toEqual(['Citroen', 'C4 Coupe', '12/01/2008', 8330]);
  723. expect(hot.getDataAtRow(1)).toEqual(['Audi', 'A4 Avant', '11/19/2011', 33900]);
  724. expect(hot.getDataAtRow(2)).toEqual(['BMW', '320i Coupe', '07/24/2011', 30500]);
  725. expect(hot.getDataAtRow(3)).toEqual(['Opel', 'Astra', '02/02/2004', 7000]);
  726. expect(hot.getDataAtRow(4)).toEqual(['Mercedes', 'A 160', '01/14/2006', 6999.9999]);
  727. });
  728. });
  729. describe('data type: time', () => {
  730. it('should properly rewrite time into correct format after sort', (done) => {
  731. var hot = handsontable({
  732. data: [
  733. ['0:00:01 am'],
  734. ['5:30:14 pm'],
  735. ['8:00:00 pm'],
  736. ['11:15:05 am'],
  737. ['4:07:48 am']
  738. ],
  739. columns: [
  740. {
  741. type: 'time',
  742. dateFormat: 'h:mm:ss a',
  743. correctFormat: true
  744. }
  745. ],
  746. colHeaders: true,
  747. columnSorting: {
  748. column: 0,
  749. sortOrder: false
  750. }
  751. });
  752. hot.setDataAtCell(0, 0, '19:55', 'edit');
  753. setTimeout(() => {
  754. expect(hot.getDataAtCell(0, 0)).toEqual('7:55:00 pm');
  755. done();
  756. }, 250);
  757. });
  758. });
  759. it('should properly sort numeric data', function() {
  760. var hot = handsontable({
  761. data: [
  762. ['Mercedes', 'A 160', '01/14/2006', '6999.9999'],
  763. ['Citroen', 'C4 Coupe', '12/01/2008', 8330],
  764. ['Citroen', 'C4 Coupe null', null, '8330'],
  765. ['Citroen', 'C4 Coupe empty', '', 8333],
  766. ['Audi', 'A4 Avant', '11/19/2011', '33900'],
  767. ['Opel', 'Astra', '02/02/2004', '7000'],
  768. ['BMW', '320i Coupe', '07/24/2011', 30500]
  769. ],
  770. columns: [
  771. {},
  772. {},
  773. {},
  774. {
  775. type: 'numeric'
  776. }
  777. ],
  778. colHeaders: true,
  779. columnSorting: true
  780. });
  781. var htCore = getHtCore();
  782. this.sortByColumn(3);
  783. expect(hot.getDataAtCol(3)).toEqual(['6999.9999', '7000', 8330, '8330', 8333, 30500, '33900']);
  784. this.sortByColumn(3);
  785. expect(hot.getDataAtCol(3)).toEqual(['33900', 30500, 8333, 8330, '8330', '7000', '6999.9999']);
  786. this.sortByColumn(3);
  787. expect(hot.getDataAtCol(3)).toEqual(['6999.9999', 8330, '8330', 8333, '33900', '7000', 30500]);
  788. });
  789. it('numericSort comparing function shouldn\'t change order when comparing empty string, null and undefined', () => {
  790. var hot = handsontable({});
  791. var numericSort = hot.getPlugin('columnSorting').numericSort;
  792. expect(numericSort(false, {})(['key1', null], ['key2', null])).toEqual(0);
  793. expect(numericSort(false, {})(['key1', ''], ['key2', ''])).toEqual(0);
  794. expect(numericSort(false, {})(['key1', undefined], ['key2', undefined])).toEqual(0);
  795. expect(numericSort(false, {})(['key1', ''], ['key2', null])).toEqual(0);
  796. expect(numericSort(false, {})(['key1', null], ['key2', ''])).toEqual(0);
  797. expect(numericSort(false, {})(['key1', ''], ['key2', undefined])).toEqual(0);
  798. expect(numericSort(false, {})(['key1', undefined], ['key2', ''])).toEqual(0);
  799. expect(numericSort(false, {})(['key1', null], ['key2', undefined])).toEqual(0);
  800. expect(numericSort(false, {})(['key1', undefined], ['key2', null])).toEqual(0);
  801. });
  802. it('should sort table with multiple row headers', function() {
  803. var hot = handsontable({
  804. data: [
  805. [1, 'B'],
  806. [0, 'D'],
  807. [3, 'A'],
  808. [2, 'C']
  809. ],
  810. columns: [
  811. {},
  812. {},
  813. {
  814. type: 'date',
  815. dateFormat: 'mm/dd/yy'
  816. },
  817. {
  818. type: 'numeric'
  819. }
  820. ],
  821. colHeaders: true,
  822. columnSorting: true,
  823. removeRowPlugin: true // this plugin ads an extra row header, so now we have 2 instead of 1
  824. });
  825. expect(this.$container.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('1');
  826. this.sortByColumn(0); // sort by first column
  827. expect(this.$container.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('0');
  828. expect(this.$container.find('tbody tr:eq(0) td:eq(1)').text()).toEqual('D');
  829. this.sortByColumn(1); // sort by second column
  830. expect(this.$container.find('tbody tr:eq(0) td:eq(1)').text()).toEqual('A');
  831. });
  832. it('should allow to define sorting column and order during initialization', function() {
  833. var hot = handsontable({
  834. data: [
  835. [1, 'B'],
  836. [0, 'D'],
  837. [3, 'A'],
  838. [2, 'C']
  839. ],
  840. colHeaders: true,
  841. columnSorting: {
  842. column: 0,
  843. sortOrder: true
  844. }
  845. });
  846. expect(this.$container.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('0');
  847. expect(this.$container.find('tbody tr:eq(0) td:eq(1)').text()).toEqual('D');
  848. });
  849. it('should allow to change sorting column with updateSettings', function() {
  850. var hot = handsontable({
  851. data: [
  852. [1, 'B'],
  853. [0, 'D'],
  854. [3, 'A'],
  855. [2, 'C']
  856. ],
  857. colHeaders: true,
  858. columnSorting: {
  859. column: 0,
  860. sortOrder: true
  861. }
  862. });
  863. expect(this.$container.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('0');
  864. expect(this.$container.find('tbody tr:eq(0) td:eq(1)').text()).toEqual('D');
  865. updateSettings({
  866. columnSorting: {
  867. column: 1,
  868. sortOrder: true
  869. }
  870. });
  871. expect(this.$container.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('3');
  872. expect(this.$container.find('tbody tr:eq(0) td:eq(1)').text()).toEqual('A');
  873. });
  874. it('should allow to change sorting order with updateSettings', function() {
  875. var hot = handsontable({
  876. data: [
  877. [1, 'B'],
  878. [0, 'D'],
  879. [3, 'A'],
  880. [2, 'C']
  881. ],
  882. colHeaders: true,
  883. columnSorting: {
  884. column: 0,
  885. sortOrder: true
  886. }
  887. });
  888. expect(this.$container.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('0');
  889. updateSettings({
  890. columnSorting: {
  891. column: 0,
  892. sortOrder: false
  893. }
  894. });
  895. expect(this.$container.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('3');
  896. });
  897. it('should allow to change if sorting empty cells with updateSettings', () => {
  898. var hot = handsontable({
  899. data: [
  900. [1, 'B'],
  901. [2, ''],
  902. [3, 'A'],
  903. [4, ''],
  904. [6, 'E'],
  905. [7, ''],
  906. [8, 'F'],
  907. ],
  908. colHeaders: true,
  909. columnSorting: {
  910. column: 1,
  911. sortOrder: false,
  912. sortEmptyCells: false
  913. }
  914. });
  915. updateSettings({
  916. columnSorting: {
  917. column: 1,
  918. sortOrder: true,
  919. sortEmptyCells: true
  920. }
  921. });
  922. // ASC with empty cells sorting
  923. expect(hot.getDataAtCol(0)).toEqual([2, 4, 7, 3, 1, 6, 8]);
  924. updateSettings({
  925. columnSorting: {
  926. column: 1,
  927. sortOrder: true,
  928. sortEmptyCells: false
  929. }
  930. });
  931. // ASC without empty cells sorting
  932. expect(hot.getDataAtCol(0)).toEqual([3, 1, 6, 8, 2, 4, 7]);
  933. });
  934. it('should NOT sort spare rows', () => {
  935. var myData = [
  936. {a: 'aaa', b: 2, c: 3},
  937. {a: 'z', b: 11, c: -4},
  938. {a: 'dddd', b: 13, c: 13},
  939. {a: 'bbbb', b: 10, c: 11}
  940. ];
  941. function customIsEmptyRow(row) {
  942. var data = this.getSourceData();
  943. return data[row].isNew;
  944. }
  945. handsontable({
  946. data: myData,
  947. rowHeaders: true,
  948. colHeaders: ['A', 'B', 'C'],
  949. columns: [
  950. {data: 'a', type: 'text'},
  951. {data: 'b', type: 'text'},
  952. {data: 'c', type: 'text'}
  953. ],
  954. dataSchema: {isNew: true, a: false}, // default for a to avoid #bad value#
  955. columnSorting: true,
  956. minSpareRows: 3,
  957. isEmptyRow: customIsEmptyRow
  958. });
  959. // ASC
  960. updateSettings({
  961. columnSorting: {
  962. column: 0,
  963. sortOrder: true
  964. }
  965. });
  966. expect(getData()).toEqual([
  967. ['aaa', 2, 3],
  968. ['bbbb', 10, 11],
  969. ['dddd', 13, 13],
  970. ['z', 11, -4],
  971. [false, null, null],
  972. [false, null, null],
  973. [false, null, null]
  974. ]);
  975. updateSettings({
  976. columnSorting: {
  977. column: 0,
  978. sortOrder: false
  979. }
  980. });
  981. expect(getData()).toEqual([
  982. ['z', 11, -4],
  983. ['dddd', 13, 13],
  984. ['bbbb', 10, 11],
  985. ['aaa', 2, 3],
  986. [false, null, null],
  987. [false, null, null],
  988. [false, null, null]
  989. ]);
  990. });
  991. it('should reset column sorting with updateSettings', function() {
  992. var hot = handsontable({
  993. data: [
  994. [1, 'B'],
  995. [0, 'D'],
  996. [3, 'A'],
  997. [2, 'C']
  998. ],
  999. colHeaders: true,
  1000. columnSorting: {
  1001. column: 0,
  1002. sortOrder: true
  1003. }
  1004. });
  1005. expect(this.$container.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('0');
  1006. updateSettings({
  1007. columnSorting: void 0
  1008. });
  1009. expect(this.$container.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('1');
  1010. });
  1011. it('should expose sort method when columnSorting is enabled', () => {
  1012. var hot = handsontable();
  1013. expect(hot.getSettings().columnSorting).toBeFalsy();
  1014. expect(hot.sort).toBeUndefined();
  1015. updateSettings({
  1016. columnSorting: true
  1017. });
  1018. expect(hot.getSettings().columnSorting).toBe(true);
  1019. expect(hot.sort).toBeDefined();
  1020. expect(typeof hot.sort).toBe('function');
  1021. updateSettings({
  1022. columnSorting: false
  1023. });
  1024. expect(hot.getSettings().columnSorting).toBeFalsy();
  1025. expect(hot.sort).toBeUndefined();
  1026. });
  1027. it('should sort table using HOT.sort method', function() {
  1028. var hot = handsontable({
  1029. data: [
  1030. [1, 'B'],
  1031. [0, 'D'],
  1032. [3, 'A'],
  1033. [2, 'C']
  1034. ],
  1035. columnSorting: true
  1036. });
  1037. expect(this.$container.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('1');
  1038. expect(this.$container.find('tbody tr:eq(1) td:eq(0)').text()).toEqual('0');
  1039. expect(this.$container.find('tbody tr:eq(2) td:eq(0)').text()).toEqual('3');
  1040. expect(this.$container.find('tbody tr:eq(3) td:eq(0)').text()).toEqual('2');
  1041. hot.sort(0, true);
  1042. expect(this.$container.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('0');
  1043. expect(this.$container.find('tbody tr:eq(1) td:eq(0)').text()).toEqual('1');
  1044. expect(this.$container.find('tbody tr:eq(2) td:eq(0)').text()).toEqual('2');
  1045. expect(this.$container.find('tbody tr:eq(3) td:eq(0)').text()).toEqual('3');
  1046. });
  1047. it('should reset column sorting with updateSettings', function() {
  1048. var hot = handsontable({
  1049. data: [
  1050. [1, 'B'],
  1051. [0, 'D'],
  1052. [3, 'A'],
  1053. [2, 'C']
  1054. ],
  1055. colHeaders: true,
  1056. columnSorting: {
  1057. column: 0,
  1058. sortOrder: true
  1059. }
  1060. });
  1061. expect(this.$container.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('0');
  1062. updateSettings({
  1063. columnSorting: void 0
  1064. });
  1065. expect(this.$container.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('1');
  1066. });
  1067. it('should fire beforeColumnSort event before sorting data', function() {
  1068. var hot = handsontable({
  1069. data: [
  1070. [2],
  1071. [4],
  1072. [1],
  1073. [3]
  1074. ],
  1075. columnSorting: true
  1076. });
  1077. this.beforeColumnSortHandler = function() {
  1078. expect(this.$container.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('2');
  1079. expect(this.$container.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('4');
  1080. expect(this.$container.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('1');
  1081. expect(this.$container.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('3');
  1082. };
  1083. spyOn(this, 'beforeColumnSortHandler');
  1084. hot.addHook('beforeColumnSort', this.beforeColumnSortHandler);
  1085. var sortColumn = 0;
  1086. var sortOrder = true;
  1087. hot.sort(sortColumn, sortOrder);
  1088. expect(this.beforeColumnSortHandler.calls.count()).toEqual(1);
  1089. expect(this.beforeColumnSortHandler).toHaveBeenCalledWith(sortColumn, sortOrder, void 0, void 0, void 0, void 0);
  1090. });
  1091. it('should not sorting column when beforeColumnSort returns false', (done) => {
  1092. var hot = handsontable({
  1093. data: [
  1094. [2],
  1095. [4],
  1096. [1],
  1097. [3]
  1098. ],
  1099. columnSorting: true,
  1100. beforeColumnSort() {
  1101. return false;
  1102. }
  1103. });
  1104. hot.sort(0, true);
  1105. setTimeout(() => {
  1106. expect(spec().$container.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('2');
  1107. expect(spec().$container.find('tbody tr:eq(1) td:eq(0)').text()).toEqual('4');
  1108. expect(spec().$container.find('tbody tr:eq(2) td:eq(0)').text()).toEqual('1');
  1109. expect(spec().$container.find('tbody tr:eq(3) td:eq(0)').text()).toEqual('3');
  1110. done();
  1111. }, 200);
  1112. });
  1113. it('should add beforeColumnSort event listener in constructor', () => {
  1114. var beforeColumnSortCallback = jasmine.createSpy('beforeColumnSortHandler');
  1115. var hot = handsontable({
  1116. data: [[2], [4], [1], [3]],
  1117. columnSorting: true,
  1118. beforeColumnSort: beforeColumnSortCallback
  1119. });
  1120. var sortColumn = 0;
  1121. var sortOrder = true;
  1122. hot.sort(sortColumn, sortOrder);
  1123. expect(beforeColumnSortCallback.calls.count()).toEqual(1);
  1124. expect(beforeColumnSortCallback).toHaveBeenCalledWith(sortColumn, sortOrder, void 0, void 0, void 0, void 0);
  1125. });
  1126. it('should fire afterColumnSort event before data has been sorted but before table render', () => {
  1127. var hot = handsontable({
  1128. data: [
  1129. [2],
  1130. [4],
  1131. [1],
  1132. [3]
  1133. ],
  1134. columnSorting: true
  1135. });
  1136. var rendered = false;
  1137. var afterColumnSortHandler = jasmine.createSpy('afterColumnSortHandler');
  1138. var afterRenderSpy = jasmine.createSpy('afterRender');
  1139. hot.addHook('afterColumnSort', function() {
  1140. expect(rendered).toBe(false);
  1141. afterColumnSortHandler.apply(afterColumnSortHandler, arguments);
  1142. });
  1143. hot.addHook('afterRender', function() {
  1144. rendered = true;
  1145. afterRenderSpy.apply(afterRenderSpy, arguments);
  1146. });
  1147. var sortColumn = 0;
  1148. var sortOrder = true;
  1149. afterRenderSpy.calls.reset();
  1150. hot.sort(sortColumn, sortOrder);
  1151. expect(afterColumnSortHandler.calls.count()).toBe(1);
  1152. expect(afterColumnSortHandler).toHaveBeenCalledWith(sortColumn, sortOrder, void 0, void 0, void 0, void 0);
  1153. expect(afterRenderSpy.calls.count()).toBe(1);
  1154. });
  1155. it('should add afterColumnSort event listener in constructor', () => {
  1156. var afterColumnSortCallback = jasmine.createSpy('afterColumnSortHandler');
  1157. var hot = handsontable({
  1158. data: [[2], [4], [1], [3]],
  1159. columnSorting: true,
  1160. afterColumnSort: afterColumnSortCallback
  1161. });
  1162. var sortColumn = 0;
  1163. var sortOrder = true;
  1164. hot.sort(sortColumn, sortOrder);
  1165. expect(afterColumnSortCallback.calls.count()).toEqual(1);
  1166. expect(afterColumnSortCallback).toHaveBeenCalledWith(sortColumn, sortOrder, void 0, void 0, void 0, void 0);
  1167. });
  1168. it('should insert row when plugin is enabled, but table hasn\'t been sorted', () => {
  1169. var hot = handsontable({
  1170. data: [
  1171. [1, 'B'],
  1172. [0, 'D'],
  1173. [3, 'A'],
  1174. [2, 'C']
  1175. ],
  1176. columnSorting: true
  1177. });
  1178. expect(countRows()).toEqual(4);
  1179. expect(hot.sortColumn).toBeUndefined();
  1180. alter('insert_row');
  1181. expect(countRows()).toEqual(5);
  1182. });
  1183. it('should remove row when plugin is enabled, but table hasn\'t been sorted', () => {
  1184. var hot = handsontable({
  1185. data: [
  1186. [1, 'B'],
  1187. [0, 'D'],
  1188. [3, 'A'],
  1189. [2, 'C']
  1190. ],
  1191. columnSorting: true
  1192. });
  1193. expect(countRows()).toEqual(4);
  1194. expect(hot.sortColumn).toBeUndefined();
  1195. alter('remove_row');
  1196. expect(countRows()).toEqual(3);
  1197. });
  1198. it('should display new row added directly to dataSource, when observeChanges plugin is enabled', function(done) {
  1199. var data = [
  1200. [1, 'B'],
  1201. [0, 'A'],
  1202. [3, 'D'],
  1203. [2, 'C']
  1204. ];
  1205. var hot = handsontable({
  1206. data,
  1207. colHeaders: true,
  1208. columnSorting: true,
  1209. observeChanges: true
  1210. });
  1211. var htCore = getHtCore();
  1212. expect(htCore.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('1');
  1213. expect(htCore.find('tbody tr:eq(1) td:eq(0)').text()).toEqual('0');
  1214. expect(htCore.find('tbody tr:eq(2) td:eq(0)').text()).toEqual('3');
  1215. expect(htCore.find('tbody tr:eq(3) td:eq(0)').text()).toEqual('2');
  1216. this.sortByColumn(0);
  1217. expect(htCore.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('0');
  1218. expect(htCore.find('tbody tr:eq(1) td:eq(0)').text()).toEqual('1');
  1219. expect(htCore.find('tbody tr:eq(2) td:eq(0)').text()).toEqual('2');
  1220. expect(htCore.find('tbody tr:eq(3) td:eq(0)').text()).toEqual('3');
  1221. expect(htCore.find('tbody tr').length).toEqual(4);
  1222. var afterChangesObservedCallback = jasmine.createSpy('afterChangesObservedCallback');
  1223. hot.addHook('afterChangesObserved', afterChangesObservedCallback);
  1224. data.push([5, 'E']);
  1225. setTimeout(() => {
  1226. expect(countRows()).toEqual(5);
  1227. expect(spec().$container.find('tbody tr:eq(4) td:eq(0)').text()).toEqual('5');
  1228. expect(spec().$container.find('tbody tr:eq(4) td:eq(1)').text()).toEqual('E');
  1229. done();
  1230. }, 200);
  1231. });
  1232. it('should not display new row added directly to dataSource, when observeChanges plugin is explicitly disabled', function(done) {
  1233. var data = [
  1234. [1, 'B'],
  1235. [0, 'A'],
  1236. [3, 'D'],
  1237. [2, 'C']
  1238. ];
  1239. var hot = handsontable({
  1240. data,
  1241. colHeaders: true,
  1242. columnSorting: true,
  1243. observeChanges: false
  1244. });
  1245. var afterChangesObservedCallback = jasmine.createSpy('afterChangesObservedCallback');
  1246. hot.addHook('afterChangesObserved', afterChangesObservedCallback);
  1247. var htCore = getHtCore();
  1248. expect(htCore.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('1');
  1249. expect(htCore.find('tbody tr:eq(1) td:eq(0)').text()).toEqual('0');
  1250. expect(htCore.find('tbody tr:eq(2) td:eq(0)').text()).toEqual('3');
  1251. expect(htCore.find('tbody tr:eq(3) td:eq(0)').text()).toEqual('2');
  1252. this.sortByColumn(0);
  1253. expect(htCore.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('0');
  1254. expect(htCore.find('tbody tr:eq(1) td:eq(0)').text()).toEqual('1');
  1255. expect(htCore.find('tbody tr:eq(2) td:eq(0)').text()).toEqual('2');
  1256. expect(htCore.find('tbody tr:eq(3) td:eq(0)').text()).toEqual('3');
  1257. expect(htCore.find('tbody tr').length).toEqual(4);
  1258. data.push([5, 'E']);
  1259. setTimeout(() => {
  1260. expect(htCore.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('0');
  1261. expect(htCore.find('tbody tr:eq(1) td:eq(0)').text()).toEqual('1');
  1262. expect(htCore.find('tbody tr:eq(2) td:eq(0)').text()).toEqual('2');
  1263. expect(htCore.find('tbody tr:eq(3) td:eq(0)').text()).toEqual('3');
  1264. expect(htCore.find('tbody tr').length).toEqual(4);
  1265. expect(afterChangesObservedCallback).not.toHaveBeenCalled();
  1266. done();
  1267. }, 100);
  1268. });
  1269. it('should display new row added directly to dataSource, when observeChanges plugin status is undefined', (done) => {
  1270. var data = [
  1271. [1, 'B'],
  1272. [0, 'A'],
  1273. [3, 'D'],
  1274. [2, 'C']
  1275. ];
  1276. var onUpdateSettings = jasmine.createSpy('onUpdateSettings');
  1277. var hot = handsontable({
  1278. data,
  1279. colHeaders: true,
  1280. columnSorting: true,
  1281. afterUpdateSettings: onUpdateSettings
  1282. });
  1283. var afterChangesObservedCallback = jasmine.createSpy('afterChangesObservedCallback');
  1284. hot.addHook('afterChangesObserved', afterChangesObservedCallback);
  1285. var htCore = getHtCore();
  1286. // columnSorting enables observeChanges plugin by asynchronously invoking updateSettings
  1287. setTimeout(() => {
  1288. expect(htCore.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('1');
  1289. expect(htCore.find('tbody tr:eq(1) td:eq(0)').text()).toEqual('0');
  1290. expect(htCore.find('tbody tr:eq(2) td:eq(0)').text()).toEqual('3');
  1291. expect(htCore.find('tbody tr:eq(3) td:eq(0)').text()).toEqual('2');
  1292. spec().sortByColumn(0);
  1293. expect(htCore.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('0');
  1294. expect(htCore.find('tbody tr:eq(1) td:eq(0)').text()).toEqual('1');
  1295. expect(htCore.find('tbody tr:eq(2) td:eq(0)').text()).toEqual('2');
  1296. expect(htCore.find('tbody tr:eq(3) td:eq(0)').text()).toEqual('3');
  1297. expect(htCore.find('tbody tr').length).toEqual(4);
  1298. data.push([5, 'E']);
  1299. }, 100);
  1300. setTimeout(() => {
  1301. expect(countRows()).toEqual(5);
  1302. expect(htCore.find('tbody tr:eq(4) td:eq(0)').text()).toEqual('5');
  1303. expect(htCore.find('tbody tr:eq(4) td:eq(1)').text()).toEqual('E');
  1304. done();
  1305. }, 2000); // 2s delayed needs for safari env
  1306. });
  1307. it('should apply sorting when there are two tables and only one has sorting enabled and has been already sorted (#1020)', function() {
  1308. var hot = handsontable({
  1309. data: [
  1310. [1, 'B'],
  1311. [0, 'D'],
  1312. [3, 'A'],
  1313. [2, 'C']
  1314. ],
  1315. columnSorting: {
  1316. column: 1
  1317. }
  1318. });
  1319. this.$container2 = $(`<div id="${id}-2"></div>`).appendTo('body');
  1320. this.$container2.handsontable();
  1321. var hot2 = this.$container2.handsontable('getInstance');
  1322. selectCell(0, 1);
  1323. keyDown('enter');
  1324. expect($('.handsontableInput').val()).toEqual('A');
  1325. this.$container2.handsontable('destroy');
  1326. this.$container2.remove();
  1327. });
  1328. it('should reset sorting after loading new data', function() {
  1329. var hot = handsontable({
  1330. data: [
  1331. [1, 'B'],
  1332. [0, 'D'],
  1333. [3, 'A'],
  1334. [2, 'C']
  1335. ],
  1336. columnSorting: true
  1337. });
  1338. expect(this.$container.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('1');
  1339. expect(this.$container.find('tbody tr:eq(1) td:eq(0)').text()).toEqual('0');
  1340. expect(this.$container.find('tbody tr:eq(2) td:eq(0)').text()).toEqual('3');
  1341. expect(this.$container.find('tbody tr:eq(3) td:eq(0)').text()).toEqual('2');
  1342. hot.sort(0, true);
  1343. expect(this.$container.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('0');
  1344. expect(this.$container.find('tbody tr:eq(1) td:eq(0)').text()).toEqual('1');
  1345. expect(this.$container.find('tbody tr:eq(2) td:eq(0)').text()).toEqual('2');
  1346. expect(this.$container.find('tbody tr:eq(3) td:eq(0)').text()).toEqual('3');
  1347. loadData([
  1348. [50, 'E'],
  1349. [10, 'G'],
  1350. [30, 'F'],
  1351. [60, 'I'],
  1352. [40, 'J'],
  1353. [20, 'H']
  1354. ]);
  1355. expect(this.$container.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('50');
  1356. expect(this.$container.find('tbody tr:eq(1) td:eq(0)').text()).toEqual('10');
  1357. expect(this.$container.find('tbody tr:eq(2) td:eq(0)').text()).toEqual('30');
  1358. expect(this.$container.find('tbody tr:eq(3) td:eq(0)').text()).toEqual('60');
  1359. expect(this.$container.find('tbody tr:eq(4) td:eq(0)').text()).toEqual('40');
  1360. expect(this.$container.find('tbody tr:eq(5) td:eq(0)').text()).toEqual('20');
  1361. });
  1362. it('should reset sorting after loading new data (default sorting column and order set)', function() {
  1363. var hot = handsontable({
  1364. data: [
  1365. [1, 'B'],
  1366. [0, 'D'],
  1367. [3, 'A'],
  1368. [2, 'C']
  1369. ],
  1370. columnSorting: {
  1371. column: 1,
  1372. sortOrder: true
  1373. }
  1374. });
  1375. expect(this.$container.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('3');
  1376. expect(this.$container.find('tbody tr:eq(1) td:eq(0)').text()).toEqual('1');
  1377. expect(this.$container.find('tbody tr:eq(2) td:eq(0)').text()).toEqual('2');
  1378. expect(this.$container.find('tbody tr:eq(3) td:eq(0)').text()).toEqual('0');
  1379. expect(this.$container.find('tbody tr:eq(0) td:eq(1)').text()).toEqual('A');
  1380. expect(this.$container.find('tbody tr:eq(1) td:eq(1)').text()).toEqual('B');
  1381. expect(this.$container.find('tbody tr:eq(2) td:eq(1)').text()).toEqual('C');
  1382. expect(this.$container.find('tbody tr:eq(3) td:eq(1)').text()).toEqual('D');
  1383. hot.sort(0, true);
  1384. expect(this.$container.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('0');
  1385. expect(this.$container.find('tbody tr:eq(1) td:eq(0)').text()).toEqual('1');
  1386. expect(this.$container.find('tbody tr:eq(2) td:eq(0)').text()).toEqual('2');
  1387. expect(this.$container.find('tbody tr:eq(3) td:eq(0)').text()).toEqual('3');
  1388. loadData([
  1389. [50, 'E'],
  1390. [10, 'G'],
  1391. [30, 'F'],
  1392. [60, 'I'],
  1393. [40, 'J'],
  1394. [20, 'H']
  1395. ]);
  1396. expect(this.$container.find('tbody tr:eq(0) td:eq(0)').text()).toEqual('50');
  1397. expect(this.$container.find('tbody tr:eq(1) td:eq(0)').text()).toEqual('30');
  1398. expect(this.$container.find('tbody tr:eq(2) td:eq(0)').text()).toEqual('10');
  1399. expect(this.$container.find('tbody tr:eq(3) td:eq(0)').text()).toEqual('20');
  1400. expect(this.$container.find('tbody tr:eq(4) td:eq(0)').text()).toEqual('60');
  1401. expect(this.$container.find('tbody tr:eq(5) td:eq(0)').text()).toEqual('40');
  1402. expect(this.$container.find('tbody tr:eq(0) td:eq(1)').text()).toEqual('E');
  1403. expect(this.$container.find('tbody tr:eq(1) td:eq(1)').text()).toEqual('F');
  1404. expect(this.$container.find('tbody tr:eq(2) td:eq(1)').text()).toEqual('G');
  1405. expect(this.$container.find('tbody tr:eq(3) td:eq(1)').text()).toEqual('H');
  1406. expect(this.$container.find('tbody tr:eq(4) td:eq(1)').text()).toEqual('I');
  1407. expect(this.$container.find('tbody tr:eq(5) td:eq(1)').text()).toEqual('J');
  1408. });
  1409. it('should return updated data at specyfied row after sorted', function() {
  1410. var hot = handsontable({
  1411. data: [
  1412. [1, 'Ted', 'Right'],
  1413. [2, 'Frank', 'Honest'],
  1414. [3, 'Joan', 'Well'],
  1415. [4, 'Sid', 'Strong'],
  1416. [5, 'Jane', 'Neat']
  1417. ],
  1418. colHeaders: true,
  1419. rowHeaders: true,
  1420. columnSorting: true
  1421. });
  1422. this.sortByColumn(0);
  1423. expect(getDataAtRow(0)).toEqual([1, 'Ted', 'Right']);
  1424. expect(getDataAtRow(4)).toEqual([5, 'Jane', 'Neat']);
  1425. this.sortByColumn(0);
  1426. expect(getDataAtRow(0)).toEqual([5, 'Jane', 'Neat']);
  1427. expect(getDataAtRow(4)).toEqual([1, 'Ted', 'Right']);
  1428. this.sortByColumn(0);
  1429. expect(getDataAtRow(0)).toEqual([1, 'Ted', 'Right']);
  1430. expect(getDataAtRow(4)).toEqual([5, 'Jane', 'Neat']);
  1431. });
  1432. it('should return updated data at specyfied col after sorted', function() {
  1433. var hot = handsontable({
  1434. data: [
  1435. [1, 'Ted', 'Right'],
  1436. [2, 'Frank', 'Honest'],
  1437. [3, 'Joan', 'Well'],
  1438. [4, 'Sid', 'Strong'],
  1439. [5, 'Jane', 'Neat']
  1440. ],
  1441. colHeaders: true,
  1442. rowHeaders: true,
  1443. columnSorting: true
  1444. });
  1445. this.sortByColumn(0);
  1446. expect(getDataAtCol(0)).toEqual([1, 2, 3, 4, 5]);
  1447. expect(getDataAtCol(1)).toEqual(['Ted', 'Frank', 'Joan', 'Sid', 'Jane']);
  1448. this.sortByColumn(0);
  1449. expect(getDataAtCol(0)).toEqual([5, 4, 3, 2, 1]);
  1450. expect(getDataAtCol(1)).toEqual(['Jane', 'Sid', 'Joan', 'Frank', 'Ted']);
  1451. this.sortByColumn(0);
  1452. expect(getDataAtCol(0)).toEqual([1, 2, 3, 4, 5]);
  1453. expect(getDataAtCol(1)).toEqual(['Ted', 'Frank', 'Joan', 'Sid', 'Jane']);
  1454. });
  1455. it('should return original data source at specified row after sorted', function() {
  1456. var hot = handsontable({
  1457. data: [
  1458. [1, 'Ted', 'Right'],
  1459. [2, 'Frank', 'Honest'],
  1460. [3, 'Joan', 'Well'],
  1461. [4, 'Sid', 'Strong'],
  1462. [5, 'Jane', 'Neat']
  1463. ],
  1464. colHeaders: true,
  1465. rowHeaders: true,
  1466. columnSorting: true
  1467. });
  1468. this.sortByColumn(0);
  1469. expect(getDataAtRow(0)).toEqual([1, 'Ted', 'Right']);
  1470. expect(getDataAtRow(4)).toEqual([5, 'Jane', 'Neat']);
  1471. expect(getSourceDataAtRow(0)).toEqual([1, 'Ted', 'Right']);
  1472. expect(getSourceDataAtRow(4)).toEqual([5, 'Jane', 'Neat']);
  1473. this.sortByColumn(0);
  1474. expect(getDataAtRow(0)).toEqual([5, 'Jane', 'Neat']);
  1475. expect(getDataAtRow(4)).toEqual([1, 'Ted', 'Right']);
  1476. expect(getSourceDataAtRow(0)).toEqual([1, 'Ted', 'Right']);
  1477. expect(getSourceDataAtRow(4)).toEqual([5, 'Jane', 'Neat']);
  1478. });
  1479. it('should return original data source at specified col after sorted', function() {
  1480. var hot = handsontable({
  1481. data: [
  1482. [1, 'Ted', 'Right'],
  1483. [2, 'Frank', 'Honest'],
  1484. [3, 'Joan', 'Well'],
  1485. [4, 'Sid', 'Strong'],
  1486. [5, 'Jane', 'Neat']
  1487. ],
  1488. colHeaders: true,
  1489. rowHeaders: true,
  1490. columnSorting: true
  1491. });
  1492. this.sortByColumn(0);
  1493. expect(getDataAtCol(0)).toEqual([1, 2, 3, 4, 5]);
  1494. expect(getDataAtCol(1)).toEqual(['Ted', 'Frank', 'Joan', 'Sid', 'Jane']);
  1495. expect(getSourceDataAtCol(0)).toEqual([1, 2, 3, 4, 5]);
  1496. expect(getSourceDataAtCol(1)).toEqual(['Ted', 'Frank', 'Joan', 'Sid', 'Jane']);
  1497. this.sortByColumn(0);
  1498. expect(getDataAtCol(0)).toEqual([5, 4, 3, 2, 1]);
  1499. expect(getDataAtCol(1)).toEqual(['Jane', 'Sid', 'Joan', 'Frank', 'Ted']);
  1500. expect(getSourceDataAtCol(0)).toEqual([1, 2, 3, 4, 5]);
  1501. expect(getSourceDataAtCol(1)).toEqual(['Ted', 'Frank', 'Joan', 'Sid', 'Jane']);
  1502. this.sortByColumn(0);
  1503. expect(getDataAtCol(0)).toEqual([1, 2, 3, 4, 5]);
  1504. expect(getDataAtCol(1)).toEqual(['Ted', 'Frank', 'Joan', 'Sid', 'Jane']);
  1505. expect(getSourceDataAtCol(0)).toEqual([1, 2, 3, 4, 5]);
  1506. expect(getSourceDataAtCol(1)).toEqual(['Ted', 'Frank', 'Joan', 'Sid', 'Jane']);
  1507. });
  1508. it('should ignore case when sorting', function() {
  1509. var hot = handsontable({
  1510. data: [
  1511. [1, 'albuquerque'],
  1512. [2, 'Alabama'],
  1513. [3, 'Missouri']
  1514. ],
  1515. colHeaders: true,
  1516. columnSorting: true
  1517. });
  1518. this.sortByColumn(1);
  1519. expect(getDataAtCol(0)).toEqual([2, 1, 3]);
  1520. expect(getDataAtCol(1)).toEqual(['Alabama', 'albuquerque', 'Missouri']);
  1521. this.sortByColumn(1);
  1522. expect(getDataAtCol(0)).toEqual([3, 1, 2]);
  1523. expect(getDataAtCol(1)).toEqual(['Missouri', 'albuquerque', 'Alabama']);
  1524. });
  1525. it('should push empty cells to the end of sorted column', function() {
  1526. var hot = handsontable({
  1527. data: [
  1528. [1, 'Ted', 'Right'],
  1529. [2, '', 'Honest'],
  1530. [3, '', 'Well'],
  1531. [4, 'Sid', 'Strong'],
  1532. [5, 'Jane', 'Neat'],
  1533. ],
  1534. colHeaders: true,
  1535. rowHeaders: true,
  1536. columnSorting: true,
  1537. minSpareRows: 1
  1538. });
  1539. this.sortByColumn(1);
  1540. expect(getDataAtCol(0)).toEqual([5, 4, 1, 2, 3, null]);
  1541. expect(getDataAtCol(1)).toEqual(['Jane', 'Sid', 'Ted', '', '', null]);
  1542. this.sortByColumn(1);
  1543. expect(getDataAtCol(0)).toEqual([1, 4, 5, 2, 3, null]);
  1544. expect(getDataAtCol(1)).toEqual(['Ted', 'Sid', 'Jane', '', '', null]);
  1545. });
  1546. it('should push numeric values before non-numeric values, when sorting ascending using the default sorting function', function() {
  1547. var hot = handsontable({
  1548. data: [
  1549. [1, 'Ted', 123],
  1550. [2, '', 'Some'],
  1551. [3, '', 321],
  1552. [4, 'Sid', 'String'],
  1553. [5, 'Jane', 46]
  1554. ],
  1555. colHeaders: true,
  1556. columnSorting: true
  1557. });
  1558. this.sortByColumn(2);
  1559. expect(getDataAtCol(2)).toEqual([46, 123, 321, 'Some', 'String']);
  1560. this.sortByColumn(2);
  1561. expect(getDataAtCol(2)).toEqual(['String', 'Some', 321, 123, 46]);
  1562. });
  1563. it('should add a sorting indicator to the column header after it\'s been sorted, only if sortIndicator property is set to true', function() {
  1564. var hot = handsontable({
  1565. data: [
  1566. [1, 'Ted', 'Right'],
  1567. [2, '', 'Honest'],
  1568. [3, '', 'Well'],
  1569. [4, 'Sid', 'Strong'],
  1570. [5, 'Jane', 'Neat'],
  1571. ],
  1572. colHeaders: true,
  1573. columnSorting: true
  1574. });
  1575. this.sortByColumn(1);
  1576. var sortedColumn = this.$container.find('th span.columnSorting')[1],
  1577. afterValue = window.getComputedStyle(sortedColumn, ':after').getPropertyValue('content');
  1578. expect(afterValue === '' || afterValue === 'none').toBe(true);
  1579. // ---------------------------------
  1580. // INDICATOR SET FOR THE WHOLE TABLE
  1581. // ---------------------------------
  1582. hot.updateSettings({
  1583. sortIndicator: true
  1584. });
  1585. this.sortByColumn(1);
  1586. // descending (updateSettings doesn't reset sorting stack)
  1587. sortedColumn = this.$container.find('th span.columnSorting')[1];
  1588. afterValue = window.getComputedStyle(sortedColumn, ':after').getPropertyValue('content');
  1589. expect(afterValue.indexOf(String.fromCharCode(9660))).toBeGreaterThan(-1);
  1590. this.sortByColumn(1);
  1591. sortedColumn = this.$container.find('th span.columnSorting')[1];
  1592. afterValue = window.getComputedStyle(sortedColumn, ':after').getPropertyValue('content');
  1593. expect(afterValue === '' || afterValue === 'none').toBe(true);
  1594. this.sortByColumn(1);
  1595. // ascending
  1596. sortedColumn = this.$container.find('th span.columnSorting')[1];
  1597. afterValue = window.getComputedStyle(sortedColumn, ':after').getPropertyValue('content');
  1598. expect(afterValue.indexOf(String.fromCharCode(9650))).toBeGreaterThan(-1);
  1599. // ---------------------------------
  1600. // INDICATOR SET FOR A SINGLE COLUMN
  1601. // ---------------------------------
  1602. hot.updateSettings({
  1603. sortIndicator: void 0,
  1604. columns: [
  1605. {},
  1606. {},
  1607. {sortIndicator: true}
  1608. ]
  1609. });
  1610. this.sortByColumn(0);
  1611. sortedColumn = this.$container.find('th span.columnSorting')[0];
  1612. afterValue = window.getComputedStyle(sortedColumn, ':after').getPropertyValue('content');
  1613. expect(afterValue === '' || afterValue === 'none').toBe(true);
  1614. this.sortByColumn(1);
  1615. // descending
  1616. sortedColumn = this.$container.find('th span.columnSorting')[1];
  1617. afterValue = window.getComputedStyle(sortedColumn, ':after').getPropertyValue('content');
  1618. expect(afterValue === '' || afterValue === 'none').toBe(true);
  1619. this.sortByColumn(2);
  1620. sortedColumn = this.$container.find('th span.columnSorting')[2];
  1621. afterValue = window.getComputedStyle(sortedColumn, ':after').getPropertyValue('content');
  1622. expect(afterValue.indexOf(String.fromCharCode(9650))).toBeGreaterThan(-1);
  1623. });
  1624. it('should change sorting indicator state on every `hot.sort()` method call (continuously for the same column)', function() {
  1625. var hot = handsontable({
  1626. data: [
  1627. [1, 'Ted', 'Right'],
  1628. [2, '', 'Honest'],
  1629. [3, '', 'Well'],
  1630. [4, 'Sid', 'Strong'],
  1631. [5, 'Jane', 'Neat'],
  1632. ],
  1633. colHeaders: true,
  1634. columnSorting: true,
  1635. sortIndicator: true,
  1636. });
  1637. hot.sort(1);
  1638. // ascending
  1639. var sortedColumn = this.$container.find('th span.columnSorting')[1];
  1640. var afterValue = window.getComputedStyle(sortedColumn, ':after').getPropertyValue('content');
  1641. expect(afterValue.indexOf(String.fromCharCode(9650))).toBeGreaterThan(-1);
  1642. hot.sort(1);
  1643. // descending
  1644. sortedColumn = this.$container.find('th span.columnSorting')[1];
  1645. afterValue = window.getComputedStyle(sortedColumn, ':after').getPropertyValue('content');
  1646. expect(afterValue.indexOf(String.fromCharCode(9660))).toBeGreaterThan(-1);
  1647. hot.sort(1);
  1648. sortedColumn = this.$container.find('th span.columnSorting')[1];
  1649. afterValue = window.getComputedStyle(sortedColumn, ':after').getPropertyValue('content');
  1650. expect(afterValue === '' || afterValue === 'none').toBe(true);
  1651. hot.sort(1);
  1652. // ascending
  1653. sortedColumn = this.$container.find('th span.columnSorting')[1];
  1654. afterValue = window.getComputedStyle(sortedColumn, ':after').getPropertyValue('content');
  1655. expect(afterValue.indexOf(String.fromCharCode(9650))).toBeGreaterThan(-1);
  1656. hot.sort(1);
  1657. // descending
  1658. sortedColumn = this.$container.find('th span.columnSorting')[1];
  1659. afterValue = window.getComputedStyle(sortedColumn, ':after').getPropertyValue('content');
  1660. expect(afterValue.indexOf(String.fromCharCode(9660))).toBeGreaterThan(-1);
  1661. });
  1662. it('should change sorting indicator state on every `hot.sort()` method (calling for different columns)', function() {
  1663. var hot = handsontable({
  1664. data: [
  1665. [1, 'Ted', 'Right'],
  1666. [2, '', 'Honest'],
  1667. [3, '', 'Well'],
  1668. [4, 'Sid', 'Strong'],
  1669. [5, 'Jane', 'Neat'],
  1670. ],
  1671. colHeaders: true,
  1672. columnSorting: true,
  1673. sortIndicator: true,
  1674. });
  1675. hot.sort(1);
  1676. // ascending
  1677. var sortedColumn = this.$container.find('th span.columnSorting')[1];
  1678. var afterValue = window.getComputedStyle(sortedColumn, ':after').getPropertyValue('content');
  1679. expect(afterValue.indexOf(String.fromCharCode(9650))).toBeGreaterThan(-1);
  1680. hot.sort(2);
  1681. // ascending
  1682. sortedColumn = this.$container.find('th span.columnSorting')[2];
  1683. afterValue = window.getComputedStyle(sortedColumn, ':after').getPropertyValue('content');
  1684. expect(afterValue.indexOf(String.fromCharCode(9650))).toBeGreaterThan(-1);
  1685. hot.sort(1);
  1686. // ascending
  1687. sortedColumn = this.$container.find('th span.columnSorting')[1];
  1688. afterValue = window.getComputedStyle(sortedColumn, ':after').getPropertyValue('content');
  1689. expect(afterValue.indexOf(String.fromCharCode(9650))).toBeGreaterThan(-1);
  1690. hot.sort(2, false);
  1691. // descending
  1692. sortedColumn = this.$container.find('th span.columnSorting')[2];
  1693. afterValue = window.getComputedStyle(sortedColumn, ':after').getPropertyValue('content');
  1694. expect(afterValue.indexOf(String.fromCharCode(9660))).toBeGreaterThan(-1);
  1695. hot.sort(2, false);
  1696. // descending
  1697. sortedColumn = this.$container.find('th span.columnSorting')[2];
  1698. afterValue = window.getComputedStyle(sortedColumn, ':after').getPropertyValue('content');
  1699. expect(afterValue.indexOf(String.fromCharCode(9660))).toBeGreaterThan(-1);
  1700. hot.sort(2, true);
  1701. // ascending
  1702. sortedColumn = this.$container.find('th span.columnSorting')[2];
  1703. afterValue = window.getComputedStyle(sortedColumn, ':after').getPropertyValue('content');
  1704. expect(afterValue.indexOf(String.fromCharCode(9650))).toBeGreaterThan(-1);
  1705. });
  1706. it('should change sorting indicator state when initial column sorting was provided', function() {
  1707. var hot = handsontable({
  1708. data: [
  1709. [1, 'Ted', 'Right'],
  1710. [2, '', 'Honest'],
  1711. [3, '', 'Well'],
  1712. [4, 'Sid', 'Strong'],
  1713. [5, 'Jane', 'Neat'],
  1714. ],
  1715. colHeaders: true,
  1716. columnSorting: {
  1717. column: 1,
  1718. sortOrder: false
  1719. },
  1720. sortIndicator: true,
  1721. });
  1722. // descending
  1723. var sortedColumn = this.$container.find('th span.columnSorting')[1];
  1724. var afterValue = window.getComputedStyle(sortedColumn, ':after').getPropertyValue('content');
  1725. expect(afterValue.indexOf(String.fromCharCode(9660))).toBeGreaterThan(-1);
  1726. hot.sort(1);
  1727. // default
  1728. sortedColumn = this.$container.find('th span.columnSorting')[1];
  1729. afterValue = window.getComputedStyle(sortedColumn, ':after').getPropertyValue('content');
  1730. expect(afterValue === '' || afterValue === 'none').toBe(true);
  1731. hot.sort(1);
  1732. // ascending
  1733. sortedColumn = this.$container.find('th span.columnSorting')[1];
  1734. afterValue = window.getComputedStyle(sortedColumn, ':after').getPropertyValue('content');
  1735. expect(afterValue.indexOf(String.fromCharCode(9650))).toBeGreaterThan(-1);
  1736. hot.sort(1);
  1737. // descending
  1738. sortedColumn = this.$container.find('th span.columnSorting')[1];
  1739. afterValue = window.getComputedStyle(sortedColumn, ':after').getPropertyValue('content');
  1740. expect(afterValue.indexOf(String.fromCharCode(9660))).toBeGreaterThan(-1);
  1741. hot.sort(1);
  1742. // default
  1743. sortedColumn = this.$container.find('th span.columnSorting')[1];
  1744. afterValue = window.getComputedStyle(sortedColumn, ':after').getPropertyValue('content');
  1745. expect(afterValue === '' || afterValue === 'none').toBe(true);
  1746. });
  1747. it('should properly sort the table, when it\'s scrolled to the far right', () => {
  1748. var data = [
  1749. ['Jasmine Ferguson', 'Britney Carey', 'Kelly Decker', 'Lacey Mcleod', 'Leona Shaffer', 'Kelli Ochoa',
  1750. 'Adele Roberson', 'Viola Snow', 'Barron Cherry', 'Calhoun Lane', 'Elvia Andrews', 'Katheryn Dale', 'Dorthy Hale',
  1751. 'Munoz Randall', 'Fields Morse', 'Hubbard Nichols', 'Chang Yang', 'Osborn Anthony', 'Owens Warner', 'Gloria Hampton'],
  1752. ['Lane Hill', 'Belinda Mathews', 'York Gray', 'Celina Stone', 'Victoria Mays', 'Angelina Lott', 'Joyce Mason', 'Shawn Rodriguez',
  1753. 'Susanna Mayo', 'Wolf Fuller', 'Long Hester', 'Dudley Doyle', 'Wilder Sutton', 'Oneal Avery', 'James Mclaughlin',
  1754. 'Lenora Guzman', 'Mcmahon Sullivan', 'Abby Weeks', 'Beverly Joseph', 'Rosalind Church'],
  1755. ['Myrtle Landry', 'Hays Huff', 'Hernandez Benjamin', 'Mclaughlin Garza', 'Franklin Barton', 'Lara Buchanan', 'Ratliff Beck',
  1756. 'Rosario Munoz', 'Isabelle Dalton', 'Smith Woodard', 'Marjorie Marshall', 'Spears Stein', 'Brianna Bowman',
  1757. 'Marci Clay', 'Palmer Harrell', 'Ball Levy', 'Shelley Mendoza', 'Morrow Glass', 'Baker Knox', 'Adrian Holman'],
  1758. ['Trisha Howell', 'Brooke Harrison', 'Anthony Watkins', 'Ellis Cobb', 'Sheppard Dillon', 'Mathis Bray',
  1759. 'Foreman Burns', 'Lina Glenn', 'Giles Pollard', 'Weiss Ballard', 'Lynnette Smith', 'Flores Kline', 'Graciela Singleton',
  1760. 'Santiago Mcclure', 'Claudette Battle', 'Nita Holloway', 'Eula Wolfe', 'Pruitt Stokes', 'Felicia Briggs', 'Melba Bradshaw']
  1761. ];
  1762. var hot = handsontable({
  1763. data,
  1764. colHeaders: true,
  1765. columnSorting: true
  1766. });
  1767. hot.view.wt.wtOverlays.leftOverlay.scrollTo(15);
  1768. hot.render();
  1769. hot.sort(15);
  1770. expect(getDataAtCell(0, 15)).toEqual('Ball Levy');
  1771. expect(getDataAtCell(1, 15)).toEqual('Hubbard Nichols');
  1772. expect(getDataAtCell(2, 15)).toEqual('Lenora Guzman');
  1773. expect(getDataAtCell(3, 15)).toEqual('Nita Holloway');
  1774. hot.sort(15);
  1775. expect(getDataAtCell(3, 15)).toEqual('Ball Levy');
  1776. expect(getDataAtCell(2, 15)).toEqual('Hubbard Nichols');
  1777. expect(getDataAtCell(1, 15)).toEqual('Lenora Guzman');
  1778. expect(getDataAtCell(0, 15)).toEqual('Nita Holloway');
  1779. hot.sort(15);
  1780. expect(getDataAtCell(0, 15)).toEqual('Hubbard Nichols');
  1781. expect(getDataAtCell(1, 15)).toEqual('Lenora Guzman');
  1782. expect(getDataAtCell(2, 15)).toEqual('Ball Levy');
  1783. expect(getDataAtCell(3, 15)).toEqual('Nita Holloway');
  1784. });
  1785. it('should allow specifiyng a custom sorting function', () => {
  1786. var data = [['1 inch'], ['1 yard'], ['2 feet'], ['0.2 miles']];
  1787. var hot = handsontable({
  1788. data,
  1789. colHeaders: true,
  1790. columnSorting: true,
  1791. columns: [
  1792. {
  1793. sortFunction(sortOrder) {
  1794. return function(a, b) {
  1795. var unitsRatios = {
  1796. inch: 1,
  1797. yard: 36,
  1798. feet: 12,
  1799. miles: 63360
  1800. };
  1801. var newA = a[1],
  1802. newB = b[1];
  1803. Handsontable.helper.objectEach(unitsRatios, (val, prop) => {
  1804. if (a[1].indexOf(prop) > -1) {
  1805. newA = parseFloat(a[1].replace(prop, '')) * val;
  1806. return false;
  1807. }
  1808. });
  1809. Handsontable.helper.objectEach(unitsRatios, (val, prop) => {
  1810. if (b[1].indexOf(prop) > -1) {
  1811. newB = parseFloat(b[1].replace(prop, '')) * val;
  1812. return false;
  1813. }
  1814. });
  1815. if (newA < newB) {
  1816. return sortOrder ? -1 : 1;
  1817. }
  1818. if (newA > newB) {
  1819. return sortOrder ? 1 : -1;
  1820. }
  1821. return 0;
  1822. };
  1823. }
  1824. }
  1825. ]
  1826. });
  1827. expect(getDataAtCell(0, 0)).toEqual('1 inch');
  1828. expect(getDataAtCell(1, 0)).toEqual('1 yard');
  1829. expect(getDataAtCell(2, 0)).toEqual('2 feet');
  1830. expect(getDataAtCell(3, 0)).toEqual('0.2 miles');
  1831. hot.sort(0);
  1832. expect(getDataAtCell(0, 0)).toEqual('1 inch');
  1833. expect(getDataAtCell(1, 0)).toEqual('2 feet');
  1834. expect(getDataAtCell(2, 0)).toEqual('1 yard');
  1835. expect(getDataAtCell(3, 0)).toEqual('0.2 miles');
  1836. hot.sort(0);
  1837. expect(getDataAtCell(0, 0)).toEqual('0.2 miles');
  1838. expect(getDataAtCell(1, 0)).toEqual('1 yard');
  1839. expect(getDataAtCell(2, 0)).toEqual('2 feet');
  1840. expect(getDataAtCell(3, 0)).toEqual('1 inch');
  1841. hot.sort(0);
  1842. expect(getDataAtCell(0, 0)).toEqual('1 inch');
  1843. expect(getDataAtCell(1, 0)).toEqual('1 yard');
  1844. expect(getDataAtCell(2, 0)).toEqual('2 feet');
  1845. expect(getDataAtCell(3, 0)).toEqual('0.2 miles');
  1846. });
  1847. it('should properly sort integers with nulls', function() {
  1848. var hot = handsontable({
  1849. data: [
  1850. ['12'],
  1851. [null],
  1852. ['10'],
  1853. ['-5'],
  1854. [null],
  1855. ['1000']
  1856. ],
  1857. colHeaders: true,
  1858. columnSorting: true
  1859. });
  1860. this.sortByColumn(0);
  1861. expect(getDataAtCol(0)).toEqual(['-5', '10', '12', '1000', null, null]);
  1862. this.sortByColumn(0);
  1863. expect(getDataAtCol(0)).toEqual(['1000', '12', '10', '-5', null, null]);
  1864. });
  1865. it('should properly sort floating points', function() {
  1866. var hot = handsontable({
  1867. data: [
  1868. ['0.0561'],
  1869. ['-10.67'],
  1870. ['-4.1'],
  1871. ['-0.01'],
  1872. ['-127'],
  1873. ['1000']
  1874. ],
  1875. colHeaders: true,
  1876. columnSorting: true
  1877. });
  1878. this.sortByColumn(0);
  1879. expect(getDataAtCol(0)).toEqual(['-127', '-10.67', '-4.1', '-0.01', '0.0561', '1000']);
  1880. this.sortByColumn(0);
  1881. expect(getDataAtCol(0)).toEqual(['1000', '0.0561', '-0.01', '-4.1', '-10.67', '-127']);
  1882. });
  1883. it('should properly sort floating points with nulls', function() {
  1884. var hot = handsontable({
  1885. data: [
  1886. ['0.0561'],
  1887. ['-10.67'],
  1888. [null],
  1889. ['-4.1'],
  1890. ['-0.01'],
  1891. [null],
  1892. ['-127'],
  1893. ['1000'],
  1894. [null]
  1895. ],
  1896. colHeaders: true,
  1897. columnSorting: true
  1898. });
  1899. this.sortByColumn(0);
  1900. expect(getDataAtCol(0)).toEqual(['-127', '-10.67', '-4.1', '-0.01', '0.0561', '1000', null, null, null]);
  1901. this.sortByColumn(0);
  1902. expect(getDataAtCol(0)).toEqual(['1000', '0.0561', '-0.01', '-4.1', '-10.67', '-127', null, null, null]);
  1903. });
  1904. it('should properly sort floating points with non-numerical values', function() {
  1905. var hot = handsontable({
  1906. data: [
  1907. ['0.0561'],
  1908. ['-10.67'],
  1909. ['a'],
  1910. ['-4.1'],
  1911. ['-0.01'],
  1912. ['b'],
  1913. ['-127'],
  1914. ['1000'],
  1915. ['hello']
  1916. ],
  1917. colHeaders: true,
  1918. columnSorting: true
  1919. });
  1920. this.sortByColumn(0);
  1921. expect(getDataAtCol(0)).toEqual(['-127', '-10.67', '-4.1', '-0.01', '0.0561', '1000', 'a', 'b', 'hello']);
  1922. this.sortByColumn(0);
  1923. expect(getDataAtCol(0)).toEqual(['hello', 'b', 'a', '1000', '0.0561', '-0.01', '-4.1', '-10.67', '-127']);
  1924. });
  1925. it('should modify row translating process when soring is applied (visual to physical and vice versa)', function() {
  1926. var hot = handsontable({
  1927. data: [
  1928. [2],
  1929. [4],
  1930. [1],
  1931. [3]
  1932. ],
  1933. colHeaders: true,
  1934. columnSorting: true
  1935. });
  1936. this.sortByColumn(0);
  1937. expect(hot.toPhysicalRow(0)).toBe(2);
  1938. expect(hot.toPhysicalRow(1)).toBe(0);
  1939. expect(hot.toPhysicalRow(2)).toBe(3);
  1940. expect(hot.toPhysicalRow(3)).toBe(1);
  1941. expect(hot.toVisualRow(0)).toBe(1);
  1942. expect(hot.toVisualRow(1)).toBe(3);
  1943. expect(hot.toVisualRow(2)).toBe(0);
  1944. expect(hot.toVisualRow(3)).toBe(2);
  1945. });
  1946. describe('should return sorted properly data when maxRows or / and minSpareRow options are set', () => {
  1947. var testSorting = function(desc, config, result) {
  1948. it(desc, () => {
  1949. handsontable({
  1950. data: Handsontable.helper.createSpreadsheetData(config.rows, config.columns),
  1951. maxRows: config.maxRow,
  1952. minSpareRows: config.minSpareRows,
  1953. columnSorting: {
  1954. column: config.sortByColumnIndex,
  1955. sortOrder: config.sortOrder
  1956. }
  1957. });
  1958. expect(getData().length).toEqual(result.dataLength);
  1959. for (var i = 0; i < result.expectations.length; i += 1) {
  1960. expect(getDataAtCell(result.expectations[i].rowIndex, result.expectations[i].columnIndex)).toEqual(result.expectations[i].value);
  1961. }
  1962. });
  1963. };
  1964. testSorting(
  1965. 'maxRows < data.length',
  1966. {rows: 9, columns: 9, maxRow: 6, sortByColumnIndex: 1, sortOrder: false},
  1967. {dataLength: 6, expectations: [{rowIndex: 0, columnIndex: 2, value: 'C6'}]}
  1968. );
  1969. testSorting(
  1970. 'maxRows > data.length',
  1971. {rows: 8, columns: 8, maxRow: 20, sortByColumnIndex: 1, sortOrder: false},
  1972. {dataLength: 8, expectations: [{rowIndex: 0, columnIndex: 2, value: 'C8'}]}
  1973. );
  1974. testSorting(
  1975. 'minSpareRows is set; maxRows < data.length',
  1976. {rows: 9, columns: 9, maxRow: 5, minSpareRows: 3, sortByColumnIndex: 1, sortOrder: false},
  1977. {dataLength: 5, expectations: [{rowIndex: 0, columnIndex: 2, value: 'C5'}]}
  1978. );
  1979. testSorting(
  1980. 'minSpareRows is set; maxRows === data.length',
  1981. {rows: 6, columns: 6, maxRow: 9, minSpareRows: 3, sortByColumnIndex: 1, sortOrder: false},
  1982. {dataLength: 6 + 3, expectations: [{rowIndex: 0, columnIndex: 2, value: 'C6'}]}
  1983. );
  1984. testSorting(
  1985. 'minSpareRows is set; maxRows > data.length',
  1986. {rows: 9, columns: 9, maxRow: 15, minSpareRows: 2, sortByColumnIndex: 1, sortOrder: false},
  1987. {dataLength: 9 + 2, expectations: [{rowIndex: 0, columnIndex: 2, value: 'C9'}]}
  1988. );
  1989. });
  1990. });