bootstrap-multiselect.js 92 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328
  1. describe('Bootstrap Multiselect "Core".', function() {
  2. var onInitialized = false;
  3. beforeEach(function() {
  4. var $select = $('<select id="multiselect" multiple="multiple"></select>');
  5. for (var i = 1; i < 100; i++) {
  6. var $option = $('<option value="' + i + '">' + i + '</option>');
  7. if (i < 10) {
  8. $option.prop('selected', true);
  9. }
  10. $select.append($option);
  11. }
  12. $('body').append($select);
  13. $select.multiselect({
  14. buttonContainer: '<div id="multiselect-container"></div>',
  15. onInitialized: function($select) {
  16. onInitialized = true;
  17. },
  18. checkboxName: function($option) {
  19. return 'value-' + $($option).attr('value');
  20. }
  21. });
  22. });
  23. it('Should add the container after the select.', function() {
  24. expect($('#multiselect-container').length).toBe(1);
  25. });
  26. it('Should add the multiselect button.', function() {
  27. expect($('#multiselect-container .multiselect').length).toBe(1);
  28. });
  29. it('Should add the dropdown menu.', function() {
  30. expect($('#multiselect-container .dropdown-menu').length).toBe(1);
  31. });
  32. it('Should add an li element with checkbox and label for each option.', function() {
  33. expect($('#multiselect-container li').length).toBe(99);
  34. expect($('#multiselect-container label').length).toBe(99);
  35. expect($('#multiselect-container input[type="checkbox"]').length).toBe(99);
  36. });
  37. it('Should preserve selected options.', function() {
  38. expect($('#multiselect-container input[type="checkbox"]:checked').length).toBe(9);
  39. expect($('#multiselect option:selected').length).toBe(9);
  40. });
  41. it('Should be able to select options by value.', function() {
  42. $('#multiselect').multiselect('select', '10');
  43. expect($('#multiselect option[value="10"]').prop('selected')).toBe(true);
  44. expect($('#multiselect-container input[value="10"]').prop('checked')).toBe(true);
  45. });
  46. it('Select method should handle "null" and "undefined" correctly.', function() {
  47. expect($('#multiselect option:selected').length).toBe(9);
  48. $('#multiselect').multiselect('select', null);
  49. expect($('#multiselect option:selected').length).toBe(9);
  50. $('#multiselect').multiselect('select', undefined);
  51. expect($('#multiselect option:selected').length).toBe(9);
  52. });
  53. it('Should be able to deselect options by value.', function() {
  54. $('#multiselect').multiselect('select', '10');
  55. $('#multiselect').multiselect('deselect', '10');
  56. expect($('#multiselect option[value="10"]').prop('selected')).toBe(false);
  57. expect($('#multiselect-container input[value="10"]').prop('checked')).toBe(false);
  58. });
  59. it('Deselect method should handle "null" and "undefined" correctly.', function() {
  60. expect($('#multiselect option:selected').length).toBe(9);
  61. $('#multiselect').multiselect('deselect', null);
  62. expect($('#multiselect option:selected').length).toBe(9);
  63. $('#multiselect').multiselect('deselect', undefined);
  64. expect($('#multiselect option:selected').length).toBe(9);
  65. });
  66. it('Should be able to select options using an array of values.', function() {
  67. $('#multiselect').multiselect('select', ['10', '11']);
  68. expect($('#multiselect option[value="10"]').prop('selected')).toBe(true);
  69. expect($('#multiselect-container input[value="10"]').prop('checked')).toBe(true);
  70. expect($('#multiselect option[value="11"]').prop('selected')).toBe(true);
  71. expect($('#multiselect-container input[value="11"]').prop('checked')).toBe(true);
  72. });
  73. it('Should be able to deselect options using an array of values.', function() {
  74. $('#multiselect').multiselect('select', ['10', '11']);
  75. $('#multiselect').multiselect('deselect', ['10', '11']);
  76. expect($('#multiselect option[value="10"]').prop('selected')).toBe(false);
  77. expect($('#multiselect-container input[value="10"]').prop('checked')).toBe(false);
  78. expect($('#multiselect option[value="11"]').prop('selected')).toBe(false);
  79. expect($('#multiselect-container input[value="11"]').prop('checked')).toBe(false);
  80. });
  81. it('Should be able to disable the multiselect', function() {
  82. $('#multiselect').multiselect('disable');
  83. expect($('#multiselect').prop('disabled')).toBe(true);
  84. });
  85. it('Should be able to enable the multiselect', function() {
  86. $('#multiselect').multiselect('disable');
  87. $('#multiselect').multiselect('enable');
  88. expect($('#multiselect').prop('disabled')).toBe(false);
  89. });
  90. it('Should be able to select all options.', function() {
  91. $('#multiselect').multiselect('selectAll');
  92. for (var i = 1; i < 100; i++) {
  93. expect($('#multiselect option[value="' + i.toString() + '"]').prop('selected')).toBe(true);
  94. expect($('#multiselect-container input[value="' + i.toString() + '"]').prop('checked')).toBe(true);
  95. }
  96. });
  97. it('Should be able to deselect all options.', function() {
  98. $('#multiselect').multiselect('selectAll');
  99. for (var i = 1; i < 100; i++) {
  100. expect($('#multiselect option[value="' + i.toString() + '"]').prop('selected')).toBe(true);
  101. expect($('#multiselect-container input[value="' + i.toString() + '"]').prop('checked')).toBe(true);
  102. }
  103. $('#multiselect').multiselect('deselectAll');
  104. for (var i = 1; i < 100; i++) {
  105. expect($('#multiselect option[value="' + i.toString() + '"]').prop('selected')).toBe(false);
  106. expect($('#multiselect-container input[value="' + i.toString() + '"]').prop('checked')).toBe(false);
  107. }
  108. });
  109. it('Should update the checkboxes according to the selected options after using refresh.', function() {
  110. for (var i = 10; i < 20; i++) {
  111. $('#multiselect option[value="' + i + '"]').prop('selected', true);
  112. }
  113. expect($('#multiselect option:selected').length).toBe(19);
  114. expect($('#multiselect-container input[type="checkbox"]:checked').length).toBe(9);
  115. $('#multiselect').multiselect('refresh');
  116. expect($('#multiselect-container input[type="checkbox"]:checked').length).toBe(19);
  117. for (var i = 10; i < 20; i++) {
  118. expect($('#multiselect option[value="' + i + '"]').prop('selected')).toBe(true);
  119. }
  120. });
  121. it('Should remove container, button and ul after destroy.', function() {
  122. $('#multiselect').multiselect('destroy');
  123. // Destroy should remove container, button and ul.
  124. expect($('#multiselect-container.multiselect-container').length).toBe(0);
  125. expect($('#multiselect-container .multiselect').length).toBe(0);
  126. expect($('#multiselect-container .dropdown-menu').length).toBe(0);
  127. });
  128. it('Should select an option when checkbox is changed (change event).', function() {
  129. $('#multiselect-container li input[value="10"]').prop('checked', true);
  130. $('#multiselect-container li input[value="10"]').trigger('change');
  131. expect($('#multiselect-container input[value="10"]').prop('checked')).toBe(true);
  132. expect($('#multiselect option[value="10"]').prop('selected')).toBe(true);
  133. });
  134. it('Should deselect an option when checkbox is changed (change event).', function() {
  135. $('#multiselect-container li input[value="10"]').prop('checked', true);
  136. $('#multiselect-container li input[value="10"]').trigger('change');
  137. // Already checked above.
  138. $('#multiselect-container li input[value="10"]').prop('checked', false);
  139. $('#multiselect-container li input[value="10"]').trigger('change');
  140. expect($('#multiselect-container input[value="10"]').prop('checked')).toBe(false);
  141. expect($('#multiselect option[value="10"]').prop('selected')).toBe(false);
  142. });
  143. it('Should select an option when checkbox is clicked.', function() {
  144. $('#multiselect-container li input[value="10"]').click();
  145. expect($('#multiselect-container input[value="10"]').prop('checked')).toBe(true);
  146. expect($('#multiselect option[value="10"]').prop('selected')).toBe(true);
  147. });
  148. it('Should deselect an option when checkbox is clicked.', function() {
  149. $('#multiselect-container li input[value="10"]').click();
  150. $('#multiselect-container li input[value="10"]').click();
  151. expect($('#multiselect-container input[value="10"]').prop('checked')).toBe(false);
  152. expect($('#multiselect option[value="10"]').prop('selected')).toBe(false);
  153. });
  154. it('Should trigger onInitialized.', function() {
  155. expect(onInitialized).toBe(true);
  156. });
  157. it('Should correctly apply checkboxName.', function() {
  158. $('#multiselect-container input').each(function() {
  159. expect($(this).attr('name')).toBe('value-' + $(this).attr('value'));
  160. });
  161. });
  162. afterEach(function() {
  163. $('#multiselect').multiselect('destroy');
  164. $('#multiselect').remove();
  165. });
  166. });
  167. describe('Bootstrap Multiselect "Multiple Multiselects".', function() {
  168. var multiselects = ['one', 'two', 'three'];
  169. var onSelectAllTriggered = 0;
  170. var onDeselectAllTriggered = 0;
  171. var onChangeFired = 0;
  172. beforeEach(function() {
  173. onSelectAllTriggered = 0;
  174. onDeselectAllTriggered = 0;
  175. onChangeFired = 0;
  176. for (var m = 0; m < 3; m++) {
  177. var $select = $('<select id="multiselect-' + multiselects[m] + '" multiple="multiple"></select>');
  178. for (var i = 1; i < 10; i++) {
  179. $select.append('<option value="' + i + '">Option ' + i + '</option>');
  180. }
  181. $('body').append($select);
  182. $select.multiselect({
  183. buttonContainer: '<div id="multiselect-container-' + multiselects[m] + '"></div>',
  184. includeSelectAllOption: true,
  185. selectAllValue: 'multiselect-all',
  186. onSelectAll: function() {
  187. onSelectAllTriggered++;
  188. },
  189. onDeselectAll: function() {
  190. onDeselectAllTriggered++;
  191. },
  192. onChange: function(option, checked) {
  193. onChangeFired++;
  194. }
  195. });
  196. }
  197. });
  198. it('Should initialize all multiselects.', function() {
  199. expect($('.multiselect').length).toBe(3);
  200. for (var m = 0; m < 3; m++) {
  201. expect($('#multiselect-' + multiselects[m]).length).toBe(1);
  202. expect($('#multiselect-container-' + multiselects[m]).length).toBe(1);
  203. expect($('#multiselect-container-' + multiselects[m] + ' .multiselect').length).toBe(1);
  204. expect($('#multiselect-container-' + multiselects[m] + ' .dropdown-menu').length).toBe(1);
  205. expect($('#multiselect-container-' + multiselects[m] + ' li').length).toBe(10); // including select all
  206. expect($('#multiselect-container-' + multiselects[m] + ' label').length).toBe(10); // including select all
  207. expect($('#multiselect-container-' + multiselects[m] + ' input[type="checkbox"]').length).toBe(10); // including select all
  208. }
  209. });
  210. it('Should not select/deselect options in other multiselects.', function() {
  211. for (var m = 0; m < 3; m++) {
  212. for (var i = 1; i < 10; i++) {
  213. $('#multiselect-container-' + multiselects[m] + ' input[value="' + i + '"]').click();
  214. expect($('#multiselect-container-' + multiselects[m] + ' input[value!="multiselect-all"]:checked').length).toBe(i);
  215. for (var n = 0; n < 3; n++) {
  216. if (m != n) {
  217. expect($('#multiselect-container-' + multiselects[n] + ' input[value!="multiselect-all"]:checked').length).toBe(0);
  218. }
  219. }
  220. }
  221. for (var i = 9; i >= 1; i--) {
  222. $('#multiselect-container-' + multiselects[m] + ' input[value="' + i + '"]').click();
  223. expect($('#multiselect-container-' + multiselects[m] + ' input[value!="multiselect-all"]:checked').length).toBe(i - 1);
  224. for (var n = 0; n < 3; n++) {
  225. if (m != n) {
  226. expect($('#multiselect-container-' + multiselects[n] + ' input[value!="multiselect-all"]:checked').length).toBe(0);
  227. }
  228. }
  229. }
  230. }
  231. });
  232. it('Should not trigger onChange in other multiselects.', function() {
  233. for (var m = 0; m < 3; m++) {
  234. for (var i = 1; i < 10; i++) {
  235. $('#multiselect-container-' + multiselects[m] + ' input[value="' + i + '"]').click();
  236. expect(onChangeFired).toBe(1);
  237. onChangeFired = 0;
  238. }
  239. }
  240. });
  241. it('Should not select all/deselect all options in other multiselects.', function() {
  242. for (var m = 0; m < 3; m++) {
  243. $('#multiselect-container-' + multiselects[m] + ' input[value="multiselect-all"]').click();
  244. expect($('#multiselect-container-' + multiselects[m] + ' input[value!="multiselect-all"]:checked').length).toBe(9);
  245. for (var n = 0; n < 3; n++) {
  246. if (n != m) {
  247. expect($('#multiselect-container-' + multiselects[n] + ' input[value!="multiselect-all"]:checked').length).toBe(0);
  248. expect($('#multiselect-container-' + multiselects[n] + ' input[value="multiselect-all"]:checked').length).toBe(0);
  249. }
  250. }
  251. $('#multiselect-container-' + multiselects[m] + ' input[value="multiselect-all"]').click();
  252. expect($('#multiselect-container-' + multiselects[m] + ' input[value!="multiselect-all"]:checked').length).toBe(0);
  253. }
  254. });
  255. it('Should not trigger onSelectAll in other multiselects.', function() {
  256. for (var m = 0; m < 3; m++) {
  257. $('#multiselect-container-' + multiselects[m] + ' input[value="multiselect-all"]').click();
  258. expect(onSelectAllTriggered).toBe(1);
  259. expect(onChangeFired).toBe(0);
  260. $('#multiselect-container-' + multiselects[m] + ' input[value="multiselect-all"]').click();
  261. onSelectAllTriggered = 0;
  262. }
  263. });
  264. it('Should not trigger onDeselectAll in other multiselects', function() {
  265. for (var m = 0; m < 3; m++) {
  266. $('#multiselect-container-' + multiselects[m] + ' input[value="multiselect-all"]').click();
  267. $('#multiselect-container-' + multiselects[m] + ' input[value="multiselect-all"]').click();
  268. expect(onSelectAllTriggered).toBe(1);
  269. expect(onDeselectAllTriggered).toBe(1);
  270. expect(onChangeFired).toBe(0);
  271. onSelectAllTriggered = 0;
  272. onDeselectAllTriggered = 0;
  273. }
  274. });
  275. afterEach(function() {
  276. for (var m = 0; m < 3; m++) {
  277. $('#multiselect-' + multiselects[m]).multiselect('destroy');
  278. $('#multiselect-' + multiselects[m]).remove();
  279. }
  280. });
  281. });
  282. describe('Bootstrap Multiselect "Single Selection".', function() {
  283. beforeEach(function() {
  284. var $select = $('<select id="multiselect"></select>');
  285. for (var i = 1; i < 100; i++) {
  286. $select.append('<option value="' + i + '">Option ' + i + '</option>');
  287. }
  288. $('body').append($select);
  289. $select.multiselect({
  290. buttonContainer: '<div id="multiselect-container"></div>'
  291. });
  292. });
  293. it('Should create radio buttons instead of checkboxes.', function() {
  294. expect($('#multiselect-container input[type="radio"]').length).toBe(99);
  295. expect($('#multiselect-container input[type="checkbox"]').length).toBe(0);
  296. // Browser selects one option per default.
  297. expect($('#multiselect option:selected').length).toBe(1);
  298. });
  299. it('Only one option at a time can be selected.', function() {
  300. expect($('#multiselect option:selected').length).toBe(1);
  301. var i = 0;
  302. $('#multiselect-container input').each(function() {
  303. if (i === 0) {
  304. expect($(this).prop('checked')).toBe(true);
  305. i++;
  306. }
  307. else {
  308. expect($(this).prop('checked')).toBe(false);
  309. $(this).click();
  310. expect($('#multiselect option:selected').length).toBe(1);
  311. expect($(this).prop('checked')).toBe(true);
  312. i++;
  313. }
  314. });
  315. });
  316. it('Deselect all should work.', function() {
  317. expect($('#multiselect option:selected').length).toBe(1);
  318. });
  319. afterEach(function() {
  320. $('#multiselect').multiselect('destroy');
  321. $('#multiselect').remove();
  322. });
  323. });
  324. describe('Bootstrap Multiselect "Individual Configuration Options".', function() {
  325. describe('disableIfEmpty.', function() {
  326. var $select = null;
  327. beforeEach(function() {
  328. $select = $('<select id="multiselect"></select>');
  329. $('body').append($select);
  330. $select.multiselect({
  331. buttonContainer: '<div id="multiselect-container"></div>',
  332. disableIfEmpty: true
  333. });
  334. });
  335. it('Should disable button if emppty.', function() {
  336. expect($('#multiselect-container button').prop('disabled')).toBe(true);
  337. });
  338. it('Should still be disabled after invoking rebuild.', function() {
  339. $select.multiselect('rebuild');
  340. expect($('#multiselect-container button').prop('disabled')).toBe(true);
  341. });
  342. it('Should not be disabled after invoking rebuild after adding options.', function() {
  343. $select.append('<option value="value-1">Option 1</option>');
  344. $select.multiselect('rebuild');
  345. expect($('#multiselect-container button').prop('disabled')).toBe(false);
  346. });
  347. it('Should not be disabled after rebuilding with more options after invoking destroy.', function() {
  348. $select.append('<option value="value-1">Option 1</option>');
  349. $select.multiselect('destroy');
  350. $select.multiselect({
  351. buttonContainer: '<div id="multiselect-container"></div>',
  352. disableIfEmpty: true
  353. });
  354. expect($('#multiselect-container button').prop('disabled')).toBe(false);
  355. });
  356. afterEach(function() {
  357. $('#multiselect').multiselect('destroy');
  358. $('#multiselect').remove();
  359. });
  360. });
  361. });
  362. describe('Bootstrap Multiselect "individual Methods".', function() {
  363. describe('Method "clearSelection" should clear selection in multiple mode.', function() {
  364. beforeEach(function() {
  365. var $select = $('<select id="multiselect" multiple="multiple"></select>');
  366. $select.append('<option value="value-1">Option 1</option>');
  367. $select.append('<option value="value-2">Option 2</option>');
  368. $select.append('<option value="value-3">Option 3</option>');
  369. $('body').append($select);
  370. $select.multiselect({
  371. buttonContainer: '<div id="multiselect-container"></div>'
  372. });
  373. });
  374. it('Method "clearSelection" should clear selection.', function() {
  375. $('#multiselect-container input[value="value-1"]').click();
  376. $('#multiselect-container input[value="value-2"]').click();
  377. expect($('#multiselect-container input:checked').length).toBe(2);
  378. expect($('#multiselect option:selected').length).toBe(2);
  379. $('#multiselect').multiselect('clearSelection');
  380. expect($('#multiselect-container input:checked').length).toBe(0);
  381. expect($('#multiselect option:selected').length).toBe(0);
  382. });
  383. afterEach(function() {
  384. $('#multiselect').multiselect('destroy');
  385. $('#multiselect').remove();
  386. });
  387. });
  388. describe('Method "clearSelection" should correctly update select all.', function() {
  389. beforeEach(function() {
  390. var $select = $('<select id="multiselect" multiple="multiple"></select>');
  391. $select.append('<option value="value-1">Option 1</option>');
  392. $select.append('<option value="value-2">Option 2</option>');
  393. $select.append('<option value="value-3">Option 3</option>');
  394. $('body').append($select);
  395. $select.multiselect({
  396. buttonContainer: '<div id="multiselect-container"></div>',
  397. includeSelectAllOption: true,
  398. selectAllValue: 'multiselect-all'
  399. });
  400. });
  401. it('Method "clearSelection" should clear selection.', function() {
  402. $('#multiselect-container input[value="multiselect-all"]').click();
  403. expect($('#multiselect-container input:checked').length).toBe(4);
  404. expect($('#multiselect option:selected').length).toBe(3);
  405. $('#multiselect').multiselect('clearSelection');
  406. expect($('#multiselect-container input:checked').length).toBe(0);
  407. expect($('#multiselect option:selected').length).toBe(0);
  408. });
  409. afterEach(function() {
  410. $('#multiselect').multiselect('destroy');
  411. $('#multiselect').remove();
  412. });
  413. });
  414. describe('Method "clearSelection" should clear selection in single mode.', function() {
  415. beforeEach(function() {
  416. var $select = $('<select id="multiselect"></select>');
  417. $select.append('<option value="value-1">Option 1</option>');
  418. $select.append('<option value="value-2">Option 2</option>');
  419. $select.append('<option value="value-3">Option 3</option>');
  420. $('body').append($select);
  421. $select.multiselect({
  422. buttonContainer: '<div id="multiselect-container"></div>'
  423. });
  424. });
  425. it('Method "clearSelection" is NOT able to clear selection.', function() {
  426. $('#multiselect-container input[value="value-2"]').click();
  427. expect($('#multiselect-container input:checked').length).toBe(1);
  428. expect($('#multiselect option:selected').length).toBe(1);
  429. $('#multiselect').multiselect('clearSelection');
  430. expect($('#multiselect-container input:checked').length).toBe(1);
  431. expect($('#multiselect option:selected').length).toBe(1);
  432. });
  433. afterEach(function() {
  434. $('#multiselect').multiselect('destroy');
  435. $('#multiselect').remove();
  436. });
  437. });
  438. });
  439. describe('Bootstrap Multiselect "Clickable Optgroups"', function() {
  440. // Count the number of onChanges fired.
  441. var fired = 0;
  442. beforeEach(function() {
  443. var $select = $('<select id="multiselect" multiple="multiple"></select>');
  444. for (var i = 1; i < 11; i++) {
  445. var $optgroup = $('<optgroup label="Group ' + i + '"></optgroup>');
  446. for (var j = 1; j < 11; j++) {
  447. if (i == 1) {
  448. $optgroup.append('<option value="' + i + '-' + j + '" selected="selected">Option ' + i + '.' + j + '</option>');
  449. }
  450. else {
  451. $optgroup.append('<option value="' + i + '-' + j + '">Option ' + i + '.' + j + '</option>');
  452. }
  453. }
  454. $select.append($optgroup);
  455. }
  456. $('body').append($select);
  457. $select.multiselect({
  458. buttonContainer: '<div id="multiselect-container"></div>',
  459. enableClickableOptGroups: true,
  460. numberDisplayed: 10,
  461. onChange: function(option, checked) {
  462. fired++;
  463. }
  464. });
  465. });
  466. it('Should correctly create inputs for optgroups.', function() {
  467. expect($('#multiselect-container li.multiselect-group').length).toBe(10);
  468. expect($('#multiselect-container li.multiselect-group input').length).toBe(10);
  469. $('#multiselect-container label.multiselect-group').each(function() {
  470. expect($('input', $(this)).length).toBe(10);
  471. });
  472. });
  473. it('Groups should be clickable and correctly initialized.', function() {
  474. expect($('#multiselect option:selected').length).toBe(10);
  475. expect(fired).toBe(0);
  476. var i = 0;
  477. $('#multiselect-container li.multiselect-group').each(function() {
  478. if (i == 0) {
  479. $('label', $(this)).click();
  480. expect($('option:selected', $('#multiselect optgroup')[i]).length).toBe(0);
  481. expect($('#multiselect option:selected').length).toBe(0);
  482. $('label', $(this)).click()
  483. expect($('option:selected', $('#multiselect optgroup')[i]).length).toBe(10);
  484. expect($('#multiselect option:selected').length).toBe(10);
  485. }
  486. else {
  487. $('label', $(this)).click();
  488. expect($('option:selected', $('#multiselect optgroup')[i]).length).toBe(10);
  489. expect($('#multiselect option:selected').length).toBe(20);
  490. $('label', $(this)).click();
  491. }
  492. i++;
  493. });
  494. });
  495. it('Clickable groups should fire onChange only once.', function() {
  496. expect($('#multiselect option:selected').length).toBe(10);
  497. fired = 0;
  498. expect(fired).toBe(0);
  499. var i = 0;
  500. $('#multiselect-container li.multiselect-group').each(function() {
  501. $('label', $(this)).click();
  502. // Selected
  503. expect(fired).toBe(1);
  504. fired = 0;
  505. $('label', $(this)).click();
  506. // Deselected
  507. expect(fired).toBe(1);
  508. fired = 0;
  509. i++;
  510. });
  511. });
  512. it('Clickable groups should fire change only once', function() {
  513. expect($('#multiselect option:selected').length).toBe(10);
  514. var changed = 0;
  515. $('#multiselect').on('change', function() {
  516. changed++;
  517. });
  518. $('#multiselect-container li.multiselect-group').each(function() {
  519. $('label', $(this)).click();
  520. // Selected
  521. expect(changed).toBe(1);
  522. changed = 0;
  523. $('label', $(this)).click();
  524. // Deselected
  525. expect(changed).toBe(1);
  526. changed = 0;
  527. });
  528. fired = 0;
  529. });
  530. it('Should update button text.', function() {
  531. expect($('#multiselect option:selected').length).toBe(10);
  532. expect(fired).toBe(0);
  533. var i = 0;
  534. $('#multiselect-container li.multiselect-group').each(function() {
  535. if (i == 0) {
  536. var text = ''
  537. $('option:selected', $('#multiselect optgroup')[i]).each(function() {
  538. text += $(this).text() + ', '
  539. });
  540. text = text.substr(0, text.length - 2);
  541. expect($('#multiselect-container .multiselect-selected-text').text()).toBe(text);
  542. $('label', $(this)).click();
  543. }
  544. else {
  545. $('label', $(this)).click();
  546. var text = ''
  547. $('option:selected', $('#multiselect optgroup')[i]).each(function() {
  548. text += $(this).text() + ', '
  549. });
  550. text = text.substr(0, text.length - 2);
  551. expect($('#multiselect-container .multiselect-selected-text').text()).toBe(text);
  552. $('label', $(this)).click();
  553. }
  554. i++;
  555. });
  556. });
  557. it('Should be updated by clicking corresponding options.', function() {
  558. for (var i = 1; i < 10; i++) {
  559. expect($('option:selected', $('#multiselect optgroup')[0]).length).toBe(10);
  560. expect($('#multiselect option:selected').length).toBe(10);
  561. var $group = $($('#multiselect-container li.multiselect-group')[i]);
  562. var $optGroup = $($('#multiselect optgroup')[i]);
  563. $group.nextUntil('li.multiselect-item').each(function() {
  564. var $input = $('input', this);
  565. $input.click();
  566. expect($input.prop('checked')).toBe(true);
  567. });
  568. expect($('option:selected', $optGroup).length).toBe(10);
  569. expect($('#multiselect option:selected').length).toBe(20);
  570. expect($('input', $group).prop('checked')).toBe(true);
  571. // Undo changes
  572. $group.nextUntil('li.multiselect-item').each(function() {
  573. var $input = $('input', this);
  574. $input.click();
  575. expect($input.prop('checked')).toBe(false);
  576. });
  577. expect($('#multiselect option:selected').length).toBe(10);
  578. expect($('input', $group).prop('checked')).toBe(false);
  579. }
  580. });
  581. it('Should be updated through select/deselect.', function() {
  582. var values = [];
  583. for (var i = 1; i < 11; i++) {
  584. values.push('1-' + i)
  585. }
  586. var $group = $('#multiselect-container li.multiselect-group')[0];
  587. $('#multiselect').multiselect('deselect', values);
  588. expect($('input', $group).prop('checked')).toBe(false);
  589. $('#multiselect').multiselect('select', values);
  590. expect($('input', $group).prop('checked')).toBe(true);
  591. });
  592. afterEach(function() {
  593. $('#multiselect').multiselect('destroy');
  594. $('#multiselect').remove();
  595. });
  596. });
  597. describe('Bootstrap Multiselect "Collapsible Optgroups"', function() {
  598. // Count the number of onChanges fired.
  599. var fired = 0;
  600. beforeEach(function() {
  601. var $select = $('<select id="multiselect" multiple="multiple"></select>');
  602. for (var i = 1; i < 11; i++) {
  603. var $optgroup = $('<optgroup label="Group ' + i + '"></optgroup>');
  604. for (var j = 1; j < 11; j++) {
  605. $optgroup.append('<option value="' + i + '-' + j + '">Option ' + i + '.' + j + '</option>');
  606. }
  607. $select.append($optgroup);
  608. }
  609. $('body').append($select);
  610. $select.multiselect({
  611. buttonContainer: '<div id="multiselect-container"></div>',
  612. enableCollapsibleOptGroups: true,
  613. onChange: function(option, checked) {
  614. fired++;
  615. }
  616. });
  617. });
  618. it('Should correctly create headers for optgroups.', function() {
  619. expect($('#multiselect-container li.multiselect-group').length).toBe(10);
  620. $('#multiselect-container label.multiselect-group').each(function() {
  621. expect($('input', $(this)).length).toBe(10);
  622. });
  623. });
  624. if ('Should not create inputs.', function() {
  625. expect($('#multiselect-container li.multiselect-group input').length).toBe(0);
  626. });
  627. it('Groups should not be clickable.', function() {
  628. expect($('#multiselect option:selected').length).toBe(0);
  629. var i = 0;
  630. $('#multiselect-container li.multiselect-group').each(function() {
  631. $('label', $(this)).click();
  632. expect($('option:selected', $('#multiselect optgroup')[i]).length).toBe(0);
  633. expect($('#multiselect option:selected').length).toBe(0);
  634. $('label', $(this)).click();
  635. i++;
  636. });
  637. });
  638. it('Should be collapsible.', function() {
  639. var $group = $('#multiselect-container li.multiselect-group:first');
  640. $('.caret-container', $group).click();
  641. var $lis = $group.nextUntil('li.multiselect-group');
  642. $lis.each(function() {
  643. expect($(this).hasClass('multiselect-collapsible-hidden')).toBe(true);
  644. expect($(this).hasClass('multiselect-collapsible-hidden')).toBe($(this).is(':hidden'));
  645. });
  646. $('.caret-container', $group).click();
  647. var $lis = $group.nextUntil('li.multiselect-group');
  648. $lis.each(function() {
  649. expect($(this).hasClass('multiselect-collapsible-hidden')).toBe(false);
  650. expect($(this).hasClass('multiselect-collapsible-hidden')).toBe($(this).is(':hidden'));
  651. });
  652. });
  653. afterEach(function() {
  654. $('#multiselect').multiselect('destroy');
  655. $('#multiselect').remove();
  656. });
  657. });
  658. describe('Bootstrap Multiselect "Clickable+Collapsible Optgroups"', function() {
  659. // Count the number of onChanges fired.
  660. var fired = 0;
  661. beforeEach(function() {
  662. var $select = $('<select id="multiselect" multiple="multiple"></select>');
  663. for (var i = 1; i < 11; i++) {
  664. var $optgroup = $('<optgroup label="Group ' + i + '"></optgroup>');
  665. for (var j = 1; j < 11; j++) {
  666. $optgroup.append('<option value="' + i + '-' + j + '">Option ' + i + '.' + j + '</option>');
  667. }
  668. $select.append($optgroup);
  669. }
  670. $('body').append($select);
  671. $select.multiselect({
  672. buttonContainer: '<div id="multiselect-container"></div>',
  673. enableClickableOptGroups: true,
  674. enableCollapsibleOptGroups: true,
  675. onChange: function(option, checked) {
  676. fired++;
  677. }
  678. });
  679. });
  680. it('Should correctly create inputs for optgroups.', function() {
  681. expect($('#multiselect-container li.multiselect-group').length).toBe(10);
  682. expect($('#multiselect-container li.multiselect-group input').length).toBe(10);
  683. $('#multiselect-container label.multiselect-group').each(function() {
  684. expect($('input', $(this)).length).toBe(10);
  685. });
  686. });
  687. it('Groups should be clickable.', function() {
  688. expect($('#multiselect option:selected').length).toBe(0);
  689. var i = 0;
  690. $('#multiselect-container li.multiselect-group').each(function() {
  691. $('label', $(this)).click();
  692. expect($('option:selected', $('#multiselect optgroup')[i]).length).toBe(10);
  693. expect($('#multiselect option:selected').length).toBe(10);
  694. $('label', $(this)).click();
  695. i++;
  696. });
  697. });
  698. it('Clickable groups should fire onChange only once.', function() {
  699. expect($('#multiselect option:selected').length).toBe(0);
  700. fired = 0;
  701. expect(fired).toBe(0);
  702. var i = 0;
  703. $('#multiselect-container li.multiselect-group').each(function() {
  704. $('label', $(this)).click();
  705. // Selected
  706. expect(fired).toBe(1);
  707. fired = 0;
  708. $('label', $(this)).click();
  709. // Deselected
  710. expect(fired).toBe(1);
  711. fired = 0;
  712. i++;
  713. });
  714. });
  715. it('Should be collapsible.', function() {
  716. var $group = $('#multiselect-container li.multiselect-group:first');
  717. $('.caret-container', $group).click();
  718. var $lis = $group.nextUntil('li.multiselect-group');
  719. $lis.each(function() {
  720. expect($(this).hasClass('multiselect-collapsible-hidden')).toBe(true);
  721. expect($(this).hasClass('multiselect-collapsible-hidden')).toBe($(this).is(':hidden'));
  722. });
  723. $('.caret-container', $group).click();
  724. var $lis = $group.nextUntil('li.multiselect-group');
  725. $lis.each(function() {
  726. expect($(this).hasClass('multiselect-collapsible-hidden')).toBe(false);
  727. expect($(this).hasClass('multiselect-collapsible-hidden')).toBe($(this).is(':hidden'));
  728. });
  729. });
  730. afterEach(function() {
  731. $('#multiselect').multiselect('destroy');
  732. $('#multiselect').remove();
  733. });
  734. });
  735. describe('Bootstrap Multiselect "Clickable+Collapsible+SelectAll Optgroups"', function() {
  736. // Count the number of onChanges fired.
  737. var fired = 0;
  738. beforeEach(function() {
  739. var $select = $('<select id="multiselect" multiple="multiple"></select>');
  740. for (var i = 1; i < 11; i++) {
  741. var $optgroup = $('<optgroup label="Group ' + i + '"></optgroup>');
  742. for (var j = 1; j < 11; j++) {
  743. $optgroup.append('<option value="' + i + '-' + j + '">Option ' + i + '.' + j + '</option>');
  744. }
  745. $select.append($optgroup);
  746. }
  747. $('body').append($select);
  748. $select.multiselect({
  749. buttonContainer: '<div id="multiselect-container"></div>',
  750. enableClickableOptGroups: true,
  751. enableCollapsibleOptGroups: true,
  752. includeSelectAllOption: true,
  753. selectAllValue: 'multiselect-all'
  754. });
  755. });
  756. it('Should NOT handle option groups differently, i.e. not set class to active.', function() {
  757. // Otherwise they are hidden.
  758. $('#multiselect-container input[value="multiselect-all"]').click();
  759. var $groups = $('#multiselect-container li.multiselect-group');
  760. $groups.each(function() {
  761. expect($(this).hasClass('active')).toBe(true);
  762. });
  763. var $lis = $('#multiselect-container li:not(.multiselect-group)');
  764. $lis.each(function() {
  765. expect($(this).hasClass('active')).toBe(true);
  766. });
  767. });
  768. it('Should select all options (including option groups).', function() {
  769. //$('#multiselect-container li.multiselect-group .caret-container').click();
  770. $('#multiselect-container input[value="multiselect-all"]').click();
  771. var $lis = $('#multiselect-container li');
  772. $lis.each(function() {
  773. expect($('input', this).prop('checked')).toBe(true);
  774. });
  775. });
  776. it('Should automatically update select all.', function() {
  777. var i = 0;
  778. $('#multiselect-container li.multiselect-group').each(function() {
  779. $('label', $(this)).click();
  780. expect($('option:selected', $('#multiselect optgroup')[i]).length).toBe(10);
  781. expect($('#multiselect option:selected').length).toBe((i + 1)*10);
  782. i++;
  783. });
  784. expect($('#multiselect-container li input[value="multiselect-all"]').prop('checked')).toBe(true);
  785. });
  786. afterEach(function() {
  787. $('#multiselect').multiselect('destroy');
  788. $('#multiselect').remove();
  789. });
  790. });
  791. describe('Bootstrap Multiselect "Dataprovider"', function() {
  792. beforeEach(function() {
  793. var $select = $('<select id="multiselect" multiple="multiple"></select>');
  794. $('body').append($select);
  795. $select.multiselect({
  796. buttonContainer: '<div id="multiselect-container"></div>'
  797. });
  798. });
  799. var options = [
  800. {label: 'Option 1', value: '1', selected: true, title: 'Option 1 Title'},
  801. {label: 'Option 2', value: '2', title: 'Option 2 Title'},
  802. {label: 'Option 3', value: '3', selected: true, title: 'Option 3 Title'},
  803. {label: 'Option 4', value: '4', title: 'Option 4 Title'},
  804. {label: 'Option 5', value: '5', title: 'Option 5 Title'},
  805. {label: 'Option 6', value: '6', title: 'Option 6 Title'}
  806. ];
  807. var options_attributes = [
  808. {label: 'Option 1', value: '1', attributes: {'some-attribute': 'test'}}
  809. ];
  810. it("Should be able to add options.", function() {
  811. $('#multiselect').multiselect('dataprovider', options);
  812. expect($('#multiselect option').length).toBe(6);
  813. expect($('#multiselect-container input').length).toBe(6);
  814. expect($('#multiselect option[value="1"]').length).toBe(1);
  815. expect($('#multiselect option[value="1"]').prop('selected')).toBe(true);
  816. expect($('#multiselect-container input[value="1"]').prop('checked')).toBe(true);
  817. expect($('#multiselect option[value="2"]').length).toBe(1);
  818. expect($('#multiselect option[value="2"]').prop('selected')).toBe(false);
  819. expect($('#multiselect-container input[value="2"]').prop('checked')).toBe(false);
  820. expect($('#multiselect option[value="3"]').length).toBe(1);
  821. expect($('#multiselect option[value="3"]').prop('selected')).toBe(true);
  822. expect($('#multiselect-container input[value="3"]').prop('checked')).toBe(true);
  823. expect($('#multiselect option[value="4"]').length).toBe(1);
  824. expect($('#multiselect option[value="4"]').prop('selected')).toBe(false);
  825. expect($('#multiselect-container input[value="4"]').prop('checked')).toBe(false);
  826. expect($('#multiselect option[value="5"]').length).toBe(1);
  827. expect($('#multiselect option[value="5"]').prop('selected')).toBe(false);
  828. expect($('#multiselect-container input[value="5"]').prop('checked')).toBe(false);
  829. expect($('#multiselect option[value="6"]').length).toBe(1);
  830. expect($('#multiselect option[value="6"]').prop('selected')).toBe(false);
  831. expect($('#multiselect-container input[value="6"]').prop('checked')).toBe(false);
  832. });
  833. it("Should be able to define title.", function() {
  834. $('#multiselect').multiselect('dataprovider', options);
  835. expect($('#multiselect option[value="1"]').attr('title')).toBe('Option 1 Title');
  836. expect($('#multiselect option[value="2"]').attr('title')).toBe('Option 2 Title');
  837. expect($('#multiselect option[value="3"]').attr('title')).toBe('Option 3 Title');
  838. expect($('#multiselect option[value="4"]').attr('title')).toBe('Option 4 Title');
  839. expect($('#multiselect option[value="5"]').attr('title')).toBe('Option 5 Title');
  840. expect($('#multiselect option[value="6"]').attr('title')).toBe('Option 6 Title');
  841. expect($('#multiselect-container input[value="1"]').closest('label').attr('title')).toBe('Option 1 Title');
  842. expect($('#multiselect-container input[value="2"]').closest('label').attr('title')).toBe('Option 2 Title');
  843. expect($('#multiselect-container input[value="3"]').closest('label').attr('title')).toBe('Option 3 Title');
  844. expect($('#multiselect-container input[value="4"]').closest('label').attr('title')).toBe('Option 4 Title');
  845. expect($('#multiselect-container input[value="5"]').closest('label').attr('title')).toBe('Option 5 Title');
  846. expect($('#multiselect-container input[value="6"]').closest('label').attr('title')).toBe('Option 6 Title');
  847. });
  848. it("Should be able to define data attributes.", function() {
  849. $('#multiselect').multiselect('dataprovider', options_attributes)
  850. expect($('#multiselect option[value="1"]').attr('value')).toBe('1');
  851. expect($('#multiselect option[value="1"]').attr('data-some-attribute')).toBe('test');
  852. });
  853. var optgroups = [
  854. {
  855. label: 'Group 1', children: [
  856. {label: 'Option 1.1', value: '1-1'},
  857. {label: 'Option 1.2', value: '1-2'},
  858. {label: 'Option 1.3', value: '1-3'}
  859. ]
  860. },
  861. {
  862. label: 'Group 2', children: [
  863. {label: 'Option 2.1', value: '1'},
  864. {label: 'Option 2.2', value: '2'},
  865. {label: 'Option 2.3', value: '3'}
  866. ]
  867. }
  868. ];
  869. it('Should be able to handle optgroups.', function() {
  870. $('#multiselect').multiselect('dataprovider', optgroups);
  871. expect($('#multiselect optgroup').length).toBe(2);
  872. expect($('#multiselect option').length).toBe(6);
  873. expect($('#multiselect-container input').length).toBe(6);
  874. expect($('#multiselect optgroup[label="Group 1"] option').length).toBe(3);
  875. expect($('#multiselect optgroup[label="Group 2"] option').length).toBe(3);
  876. });
  877. afterEach(function() {
  878. $('#multiselect').multiselect('destroy');
  879. $('#multiselect').remove();
  880. });
  881. });
  882. describe('Bootstrap Multiselect "Select All".', function() {
  883. var onSelectAllTriggered = false;
  884. var onDeselectAllTriggered = false;
  885. var fired = 0;
  886. beforeEach(function() {
  887. onSelectAllTriggered = false;
  888. onDeselectAllTriggered = false;
  889. fired = 0;
  890. var $select = $('<select id="multiselect" multiple="multiple"></select>');
  891. for (var i = 1; i < 100; i++) {
  892. $select.append('<option value="' + i + '">1</option>');
  893. }
  894. $('body').append($select);
  895. $select.multiselect({
  896. buttonContainer: '<div id="multiselect-container"></div>',
  897. includeSelectAllOption: true,
  898. selectAllValue: 'multiselect-all',
  899. onSelectAll: function() {
  900. onSelectAllTriggered = true;
  901. },
  902. onDeselectAll: function() {
  903. onDeselectAllTriggered = true;
  904. },
  905. onChange: function(option, checked) {
  906. fired++;
  907. }
  908. });
  909. });
  910. it('Should not add an additional option to the select.', function() {
  911. expect($('#multiselect option[value="multiselect-all"]').length).toBe(0);
  912. expect($('#multiselect-container input[value="multiselect-all"]').length).toBe(1);
  913. expect($('#multiselect option').length).toBe(99);
  914. expect($('#multiselect-container input').length).toBe(100);
  915. });
  916. it('Should update the select all when all options are selected by the "select" method.', function() {
  917. expect($('#multiselect option:selected').length).toBe(0);
  918. expect($('#multiselect-container input[value="multiselect-all"]').prop('checked')).toBe(false);
  919. for (var i = 1; i < 100; i++) {
  920. $('#multiselect').multiselect('select', i.toString());
  921. expect($('#multiselect option[value="' + i.toString() + '"]').prop('selected')).toBe(true);
  922. }
  923. expect($('#multiselect option:selected').length).toBe(99);
  924. expect($('#multiselect-container input').length).toBe(100);
  925. expect($('#multiselect-container input[value="multiselect-all"]').prop('checked')).toBe(true);
  926. });
  927. it('Should update the select all when all options are deselected by the "deselect" method (first all options are selected as before).', function() {
  928. expect($('#multiselect option:selected').length).toBe(0);
  929. expect($('#multiselect-container input[value="multiselect-all"]').prop('checked')).toBe(false);
  930. for (var i = 1; i < 100; i++) {
  931. $('#multiselect').multiselect('select', i.toString());
  932. }
  933. expect($('#multiselect option:selected').length).toBe(99);
  934. expect($('#multiselect-container input:checked').length).toBe(100);
  935. expect($('#multiselect-container input[value="multiselect-all"]').prop('checked')).toBe(true);
  936. for (var i = 1; i < 100; i++) {
  937. $('#multiselect').multiselect('deselect', i.toString());
  938. }
  939. expect($('#multiselect option:selected').length).toBe(0);
  940. expect($('#multiselect-container input[value="multiselect-all"]').prop('checked')).toBe(false);
  941. });
  942. it('Should update the select all option when all options are selected by the change event.', function() {
  943. expect($('#multiselect option:selected').length).toBe(0);
  944. expect($('#multiselect-container input[value="multiselect-all"]').prop('checked')).toBe(false);
  945. // Change all checkboxes except the select all one.
  946. $('#multiselect-container input[value!="multiselect-all"]').prop('checked', true);
  947. $('#multiselect-container input[value!="multiselect-all"]').trigger('change');
  948. expect($('#multiselect option:selected[value!="multiselect-all"]').length).toBe(99);
  949. // 100 options seleted including the select all.
  950. expect($('#multiselect option:selected').length).toBe(99);
  951. expect($('#multiselect-container input[value="multiselect-all"]').prop('checked')).toBe(true);
  952. });
  953. it('Should update the select all option when all options are deselected by the change event.', function() {
  954. expect($('#multiselect option:selected').length).toBe(0);
  955. expect($('#multiselect-container input[value="multiselect-all"]').prop('checked')).toBe(false);
  956. $('#multiselect-container input[value!="multiselect-all"]').prop('checked', true);
  957. $('#multiselect-container input[value!="multiselect-all"]').trigger('change');
  958. expect($('#multiselect option:selected[value!="multiselect-all"]').length).toBe(99);
  959. expect($('#multiselect option:selected').length).toBe(99);
  960. expect($('#multiselect-container input[value="multiselect-all"]').prop('checked')).toBe(true);
  961. // Change all checkboxes except the select all one.
  962. $('#multiselect-container input[value!="multiselect-all"]').prop('checked', false);
  963. $('#multiselect-container input[value!="multiselect-all"]').trigger('change');
  964. expect($('#multiselect option:selected').length).toBe(0);
  965. expect($('#multiselect-container input[value="multiselect-all"]').prop('checked')).toBe(false);
  966. });
  967. it('Should update the select all option when all options are selected by the click event.', function() {
  968. expect($('#multiselect option:selected').length).toBe(0);
  969. expect($('#multiselect-container input[value="multiselect-all"]').prop('checked')).toBe(false);
  970. $('#multiselect-container input[value!="multiselect-all"]').click();
  971. expect($('#multiselect option:selected').length).toBe(99);
  972. expect($('#multiselect-container input[value="multiselect-all"]').prop('checked')).toBe(true);
  973. });
  974. it('Should update the select all option when all options are deselected by the click event.', function() {
  975. expect($('#multiselect option:selected').length).toBe(0);
  976. expect($('#multiselect-container input[value="multiselect-all"]').prop('checked')).toBe(false);
  977. $('#multiselect-container input[value!="multiselect-all"]').click();
  978. expect($('#multiselect option:selected').length).toBe(99);
  979. expect($('#multiselect-container input[value="multiselect-all"]').prop('checked')).toBe(true);
  980. $('#multiselect-container input[value!="multiselect-all"]').click();
  981. expect($('#multiselect option:selected').length).toBe(0);
  982. expect($('#multiselect-container input[value="multiselect-all"]').prop('checked')).toBe(false);
  983. });
  984. it('Should trigger onSelectAll/onDeselectAll when changing the select all option.', function() {
  985. expect($('#multiselect option:selected').length).toBe(0);
  986. expect($('#multiselect-container input[value="multiselect-all"]').prop('checked')).toBe(false);
  987. $('#multiselect-container input[value="multiselect-all"]').prop('checked', true);
  988. $('#multiselect-container input[value="multiselect-all"]').trigger('change');
  989. expect($('#multiselect option:selected').length).toBe(99);
  990. expect($('#multiselect-container input:checked').length).toBe(100); // including select all
  991. expect(onSelectAllTriggered).toBe(true);
  992. $('#multiselect-container input[value="multiselect-all"]').prop('checked', false);
  993. $('#multiselect-container input[value="multiselect-all"]').trigger('change');
  994. expect($('#multiselect option:selected[value!="multiselect-all"]').length).toBe(0);
  995. expect($('#multiselect option:selected').length).toBe(0);
  996. expect(onDeselectAllTriggered).toBe(true);
  997. });
  998. it('Should trigger the onSelectAll/onDeselectAll when clicking the select all option.', function() {
  999. expect($('#multiselect option:selected').length).toBe(0);
  1000. expect($('#multiselect-container input[value="multiselect-all"]').prop('checked')).toBe(false);
  1001. $('#multiselect-container input[value="multiselect-all"]').click();
  1002. expect($('#multiselect option:selected').length).toBe(99);
  1003. expect($('#multiselect-container input:checked').length).toBe(100); // including select all
  1004. expect(onSelectAllTriggered).toBe(true);
  1005. $('#multiselect-container input[value="multiselect-all"]').click();
  1006. expect($('#multiselect option:selected[value!="multiselect-all"]').length).toBe(0);
  1007. expect($('#multiselect option:selected').length).toBe(0);
  1008. expect(onDeselectAllTriggered).toBe(true);
  1009. });
  1010. it('Should NOT trigger onSelectAll/onDeselectAll based on the change event.', function() {
  1011. expect($('#multiselect option:selected').length).toBe(0);
  1012. expect($('#multiselect-container input[value="multiselect-all"]').prop('checked')).toBe(false);
  1013. $('#multiselect-container input[value!="multiselect-all"]').prop('checked', true);
  1014. $('#multiselect-container input[value!="multiselect-all"]').trigger('change');
  1015. expect($('#multiselect option:selected[value!="multiselect-all"]').length).toBe(99);
  1016. expect($('#multiselect option:selected').length).toBe(99);
  1017. expect($('#multiselect-container input[value="multiselect-all"]').prop('checked')).toBe(true);
  1018. expect(onSelectAllTriggered).toBe(false);
  1019. $('#multiselect-container input[value!="multiselect-all"]').prop('checked', false);
  1020. $('#multiselect-container input[value!="multiselect-all"]').trigger('change');
  1021. expect($('#multiselect option:selected[value!="multiselect-all"]').length).toBe(0);
  1022. expect($('#multiselect option:selected').length).toBe(0);
  1023. expect($('#multiselect-container input[value="multiselect-all"]').prop('checked')).toBe(false);
  1024. expect(onDeselectAllTriggered).toBe(false);
  1025. });
  1026. it('Should NOT trigger onSelectAll/onDeselectAll based on the click event.', function() {
  1027. expect($('#multiselect option:selected').length).toBe(0);
  1028. expect($('#multiselect-container input[value="multiselect-all"]').prop('checked')).toBe(false);
  1029. $('#multiselect-container input[value!="multiselect-all"]').click();
  1030. expect($('#multiselect option:selected').length).toBe(99);
  1031. expect($('#multiselect-container input[value="multiselect-all"]').prop('checked')).toBe(true);
  1032. expect(onSelectAllTriggered).toBe(false);
  1033. $('#multiselect-container input[value!="multiselect-all"]').click();
  1034. expect($('#multiselect option:selected').length).toBe(0);
  1035. expect($('#multiselect-container input[value="multiselect-all"]').prop('checked')).toBe(false);
  1036. expect(onDeselectAllTriggered).toBe(false);
  1037. });
  1038. it('Should trigger onSelectAll/onDeselectAll on function call.', function() {
  1039. $('#multiselect').multiselect('selectAll', true, true);
  1040. expect(onSelectAllTriggered).toBe(true);
  1041. $('#multiselect').multiselect('deselectAll', true, true);
  1042. expect(onDeselectAllTriggered).toBe(true);
  1043. });
  1044. it('Should NOT trigger onSelectAll on initialization but initialize the select all option correctly.', function() {
  1045. var $select = $('<select id="multiselect-onSelectAll" multiple="multiple"></select>');
  1046. for (var i = 1; i < 10; i++) {
  1047. $select.append('<option value="' + i + '" selected>1</option>');
  1048. }
  1049. $('body').append($select);
  1050. onSelectAllTriggered = false;
  1051. $select.multiselect({
  1052. buttonContainer: '<div id="multiselect-onSelectAll-container"></div>',
  1053. includeSelectAllOption: true,
  1054. selectAllValue: 'multiselect-all',
  1055. onSelectAll: function() {
  1056. onSelectAllTriggered = true;
  1057. },
  1058. });
  1059. expect($('#multiselect-onSelectAll-container input[value="multiselect-all"]').prop('checked')).toBe(true);
  1060. expect(onSelectAllTriggered).toBe(false);
  1061. $('#multiselect-onSelectAll').multiselect('destroy');
  1062. $('#multiselect-onSelectAll').remove();
  1063. });
  1064. it('Should NOT trigger onDeselectAll on initialization but initialize the select all option correctly.', function() {
  1065. var $select = $('<select id="multiselect-onDeselectAll" multiple="multiple"></select>');
  1066. for (var i = 1; i < 10; i++) {
  1067. $select.append('<option value="' + i + '">1</option>');
  1068. }
  1069. $('body').append($select);
  1070. onDeselectAllTriggered = false;
  1071. $select.multiselect({
  1072. buttonContainer: '<div id="multiselect-onDeselectAll-container"></div>',
  1073. includeSelectAllOption: true,
  1074. selectAllValue: 'multiselect-all',
  1075. onDeselectAll: function() {
  1076. onDeselectAllTriggered = true;
  1077. },
  1078. });
  1079. expect($('#multiselect-onDeselectAll-container input[value="multiselect-all"]').prop('checked')).toBe(false);
  1080. expect(onDeselectAllTriggered).toBe(false);
  1081. $('#multiselect-onDeselectAll').multiselect('destroy');
  1082. $('#multiselect-onDeselectAll').remove();
  1083. });
  1084. afterEach(function() {
  1085. $('#multiselect').multiselect('destroy');
  1086. $('#multiselect').remove();
  1087. });
  1088. });
  1089. describe('Bootstrap Multiselect "Filter".', function() {
  1090. var $select = null;
  1091. beforeEach(function() {
  1092. $('#multiselect').multiselect('destroy');
  1093. $('#multiselect').remove();
  1094. $select = $('<select id="multiselect" multiple="multiple"></select>');
  1095. for (var i = 1; i < 10; i++) {
  1096. $select.append('<option value="value-' + i + '">Option ' + i + '</option>');
  1097. }
  1098. $('body').append($select);
  1099. });
  1100. describe('Should create filter.', function() {
  1101. beforeEach(function() {
  1102. $select.multiselect({
  1103. buttonContainer: '<div id="multiselect-container"></div>',
  1104. enableFiltering: true,
  1105. filterBehavior: 'value'
  1106. });
  1107. });
  1108. it('Should create filter.', function() {
  1109. expect($('#multiselect-container li.multiselect-filter').length).toBe(1);
  1110. expect($('#multiselect-container li.multiselect-filter input').length).toBe(1);
  1111. expect($('#multiselect-container li.multiselect-filter .multiselect-clear-filter').length).toBe(1);
  1112. });
  1113. });
  1114. describe('Should filter elements by value.', function() {
  1115. beforeEach(function(done) {
  1116. $select.multiselect({
  1117. buttonContainer: '<div id="multiselect-container"></div>',
  1118. enableFiltering: true,
  1119. filterBehavior: 'value',
  1120. onFiltering: function() {
  1121. done();
  1122. }
  1123. });
  1124. $('#multiselect-container li.multiselect-filter input').val('value-9').trigger('keydown');
  1125. });
  1126. it('Should filter elements.', function() {
  1127. for (var i = 1; i < 10; i++) {
  1128. if (i != 9) {
  1129. expect($('#multiselect-container li input[value="value-' + i + '"]').closest('li').hasClass('multiselect-filter-hidden')).toBe(true, i);
  1130. }
  1131. else {
  1132. expect($('#multiselect-container li input[value="value-' + i + '"]').closest('li').hasClass('multiselect-filter-hidden')).toBe(false, i);
  1133. }
  1134. }
  1135. });
  1136. });
  1137. describe('Should filter elements by value only.', function() {
  1138. beforeEach(function(done) {
  1139. $select.multiselect({
  1140. buttonContainer: '<div id="multiselect-container"></div>',
  1141. enableFiltering: true,
  1142. filterBehavior: 'value',
  1143. onFiltering: function() {
  1144. done();
  1145. }
  1146. });
  1147. $('#multiselect-container li.multiselect-filter input').val('Option').trigger('keydown');
  1148. });
  1149. it('Should filter elements.', function() {
  1150. for (var i = 1; i < 10; i++) {
  1151. expect($('#multiselect-container li input[value="value-' + i + '"]').closest('li').hasClass('multiselect-filter-hidden')).toBe(true, i);
  1152. }
  1153. });
  1154. });
  1155. describe('Should filter elements by text.', function() {
  1156. beforeEach(function(done) {
  1157. $select.multiselect({
  1158. buttonContainer: '<div id="multiselect-container"></div>',
  1159. enableFiltering: true,
  1160. filterBehavior: 'text',
  1161. onFiltering: function() {
  1162. done();
  1163. }
  1164. });
  1165. $('#multiselect-container li.multiselect-filter input').val('Option 9').trigger('keydown');
  1166. });
  1167. it('Should filter elements.', function() {
  1168. for (var i = 1; i < 10; i++) {
  1169. if (i != 9) {
  1170. expect($('#multiselect-container li input[value="value-' + i + '"]').closest('li').hasClass('multiselect-filter-hidden')).toBe(true, i);
  1171. }
  1172. else {
  1173. expect($('#multiselect-container li input[value="value-' + i + '"]').closest('li').hasClass('multiselect-filter-hidden')).toBe(false, i);
  1174. }
  1175. }
  1176. });
  1177. });
  1178. describe('Should filter elements by text only.', function() {
  1179. beforeEach(function(done) {
  1180. $select.multiselect({
  1181. buttonContainer: '<div id="multiselect-container"></div>',
  1182. enableFiltering: true,
  1183. filterBehavior: 'text',
  1184. onFiltering: function() {
  1185. done();
  1186. }
  1187. });
  1188. $('#multiselect-container li.multiselect-filter input').val('value').trigger('keydown');
  1189. });
  1190. it('Should filter elements.', function() {
  1191. for (var i = 1; i < 10; i++) {
  1192. expect($('#multiselect-container li input[value="value-' + i + '"]').closest('li').hasClass('multiselect-filter-hidden')).toBe(true, i);
  1193. }
  1194. });
  1195. });
  1196. describe('Should filter elements by text and value - text.', function() {
  1197. beforeEach(function(done) {
  1198. $select.multiselect({
  1199. buttonContainer: '<div id="multiselect-container"></div>',
  1200. enableFiltering: true,
  1201. filterBehavior: 'both',
  1202. onFiltering: function() {
  1203. done();
  1204. }
  1205. });
  1206. $('#multiselect-container li.multiselect-filter input').val('Option 9').trigger('keydown');
  1207. });
  1208. it('Should filter elements.', function() {
  1209. for (var i = 1; i < 10; i++) {
  1210. if (i != 9) {
  1211. expect($('#multiselect-container li input[value="value-' + i + '"]').closest('li').hasClass('multiselect-filter-hidden')).toBe(true, i);
  1212. }
  1213. else {
  1214. expect($('#multiselect-container li input[value="value-' + i + '"]').closest('li').hasClass('multiselect-filter-hidden')).toBe(false, i);
  1215. }
  1216. }
  1217. });
  1218. });
  1219. describe('Should filter elements by text and value - value.', function() {
  1220. beforeEach(function(done) {
  1221. $select.multiselect({
  1222. buttonContainer: '<div id="multiselect-container"></div>',
  1223. enableFiltering: true,
  1224. filterBehavior: 'both',
  1225. onFiltering: function() {
  1226. done();
  1227. }
  1228. });
  1229. $('#multiselect-container li.multiselect-filter input').val('value-9').trigger('keydown');
  1230. });
  1231. it('Should filter elements.', function() {
  1232. for (var i = 1; i < 10; i++) {
  1233. if (i != 9) {
  1234. expect($('#multiselect-container li input[value="value-' + i + '"]').closest('li').hasClass('multiselect-filter-hidden')).toBe(true, i);
  1235. }
  1236. else {
  1237. expect($('#multiselect-container li input[value="value-' + i + '"]').closest('li').hasClass('multiselect-filter-hidden')).toBe(false, i);
  1238. }
  1239. }
  1240. });
  1241. });
  1242. describe('Should remove filter on clicking the clear button.', function() {
  1243. beforeEach(function(done) {
  1244. $select.multiselect({
  1245. buttonContainer: '<div id="multiselect-container"></div>',
  1246. enableFiltering: true,
  1247. filterBehavior: 'value',
  1248. onFiltering: function() {
  1249. done();
  1250. }
  1251. });
  1252. $('#multiselect-container li.multiselect-filter input').val('value-9').trigger('keydown');
  1253. });
  1254. it('Should remove filter.', function() {
  1255. for (var i = 1; i < 10; i++) {
  1256. if (i != 9) {
  1257. expect($('#multiselect-container li input[value="value-' + i + '"]').closest('li').hasClass('multiselect-filter-hidden')).toBe(true, i);
  1258. }
  1259. else {
  1260. expect($('#multiselect-container li input[value="value-' + i + '"]').closest('li').hasClass('multiselect-filter-hidden')).toBe(false, i);
  1261. }
  1262. }
  1263. $('#multiselect-container li.multiselect-filter .multiselect-clear-filter').click();
  1264. for (var i = 1; i < 10; i++) {
  1265. expect($('#multiselect-container li input[value="value-' + i + '"]').closest('li').hasClass('multiselect-filter-hidden')).toBe(false, i);
  1266. }
  1267. });
  1268. });
  1269. describe('Filtering and removing the filter should not alter selection.', function() {
  1270. beforeEach(function(done) {
  1271. $select.multiselect({
  1272. buttonContainer: '<div id="multiselect-container"></div>',
  1273. enableFiltering: true,
  1274. filterBehavior: 'value',
  1275. onFiltering: function() {
  1276. done();
  1277. }
  1278. });
  1279. $('#multiselect-container li input[value="value-1"]').click();
  1280. $('#multiselect-container li input[value="value-9"]').click();
  1281. for (var i = 1; i < 10; i++) {
  1282. if (i != 9 && i != 1) {
  1283. expect($('#multiselect-container li input[value="value-' + i + '"]').prop('checked')).toBe(false, i);
  1284. }
  1285. else {
  1286. expect($('#multiselect-container li input[value="value-' + i + '"]').prop('checked')).toBe(true, i);
  1287. }
  1288. }
  1289. $('#multiselect-container li.multiselect-filter input').val('value-9').trigger('keydown');
  1290. });
  1291. it('Should not alter selection.', function() {
  1292. for (var i = 1; i < 10; i++) {
  1293. if (i != 9 && i != 1) {
  1294. expect($('#multiselect-container li input[value="value-' + i + '"]').prop('checked')).toBe(false, i);
  1295. }
  1296. else {
  1297. expect($('#multiselect-container li input[value="value-' + i + '"]').prop('checked')).toBe(true, i);
  1298. }
  1299. }
  1300. $('#multiselect-container li.multiselect-filter .multiselect-clear-filter').click();
  1301. for (var i = 1; i < 10; i++) {
  1302. if (i != 9 && i != 1) {
  1303. expect($('#multiselect-container li input[value="value-' + i + '"]').prop('checked')).toBe(false, i);
  1304. }
  1305. else {
  1306. expect($('#multiselect-container li input[value="value-' + i + '"]').prop('checked')).toBe(true, i);
  1307. }
  1308. }
  1309. });
  1310. });
  1311. describe('Select method should select both hidden and visible options.', function() {
  1312. beforeEach(function(done) {
  1313. $select.multiselect({
  1314. buttonContainer: '<div id="multiselect-container"></div>',
  1315. enableFiltering: true,
  1316. filterBehavior: 'value',
  1317. onFiltering: function() {
  1318. done();
  1319. }
  1320. });
  1321. for (var i = 1; i < 10; i++) {
  1322. expect($('#multiselect-container li input[value="value-' + i + '"]').prop('checked')).toBe(false, i);
  1323. }
  1324. $('#multiselect-container li.multiselect-filter input').val('value-9').trigger('keydown');
  1325. });
  1326. it('Should not alter selection.', function() {
  1327. $('#multiselect').multiselect('select', 'value-1');
  1328. expect($('#multiselect-container li input[value="value-1"]').prop('checked')).toBe(true);
  1329. expect($('#multiselect option[value="value-1"]').prop('selected')).toBe(true);
  1330. $('#multiselect').multiselect('select', 'value-9');
  1331. expect($('#multiselect-container li input[value="value-9"]').prop('checked')).toBe(true);
  1332. expect($('#multiselect option[value="value-9"]').prop('selected')).toBe(true);
  1333. });
  1334. });
  1335. describe('Deselect method should select both hidden and visible options.', function() {
  1336. beforeEach(function(done) {
  1337. $select.multiselect({
  1338. buttonContainer: '<div id="multiselect-container"></div>',
  1339. enableFiltering: true,
  1340. filterBehavior: 'value',
  1341. onFiltering: function() {
  1342. done();
  1343. }
  1344. });
  1345. $('#multiselect-container li input[value="value-9"]').click();
  1346. $('#multiselect-container li input[value="value-1"]').click();
  1347. for (var i = 1; i < 10; i++) {
  1348. if (i != 9 && i != 1) {
  1349. expect($('#multiselect-container li input[value="value-' + i + '"]').prop('checked')).toBe(false, i);
  1350. }
  1351. else {
  1352. expect($('#multiselect-container li input[value="value-' + i + '"]').prop('checked')).toBe(true, i);
  1353. }
  1354. }
  1355. $('#multiselect-container li.multiselect-filter input').val('value-9').trigger('keydown');
  1356. });
  1357. it('Should not alter selection.', function() {
  1358. $('#multiselect').multiselect('deselect', 'value-1');
  1359. expect($('#multiselect-container li input[value="value-1"]').prop('checked')).toBe(false);
  1360. expect($('#multiselect option[value="value-1"]').prop('selected')).toBe(false);
  1361. $('#multiselect').multiselect('deselect', 'value-9');
  1362. expect($('#multiselect-container li input[value="value-9"]').prop('checked')).toBe(false);
  1363. expect($('#multiselect option[value="value-9"]').prop('selected')).toBe(false);
  1364. });
  1365. });
  1366. afterEach(function() {
  1367. $('#multiselect').multiselect('destroy');
  1368. $('#multiselect').remove();
  1369. });
  1370. });
  1371. describe('Bootstrap Multiselect "Select All+Filter+selectAllJustVisible".', function() {
  1372. var $select = null;
  1373. beforeEach(function() {
  1374. $('#multiselect').multiselect('destroy');
  1375. $('#multiselect').remove();
  1376. $select = $('<select id="multiselect" multiple="multiple"></select>');
  1377. for (var i = 1; i < 10; i++) {
  1378. $select.append('<option value="value-' + i + '">Option ' + i + '</option>');
  1379. }
  1380. $('body').append($select);
  1381. });
  1382. describe('Should select only visible options if selectAllJustVisible is true.', function() {
  1383. beforeEach(function(done) {
  1384. $select.multiselect({
  1385. buttonContainer: '<div id="multiselect-container"></div>',
  1386. enableFiltering: true,
  1387. filterBehavior: 'value',
  1388. includeSelectAllOption: true,
  1389. selectAllJustVisible: true,
  1390. selectAllValue: 'multiselect-all',
  1391. onFiltering: function() {
  1392. done();
  1393. }
  1394. });
  1395. for (var i = 1; i < 10; i++) {
  1396. expect($('#multiselect-container li input[value="value-' + i + '"]').prop('checked')).toBe(false, i);
  1397. }
  1398. $('#multiselect-container li.multiselect-filter input').val('value-9').trigger('keydown');
  1399. });
  1400. it('Should select one option.', function() {
  1401. $('#multiselect-container li input[value="multiselect-all"]').click();
  1402. for (var i = 1; i < 10; i++) {
  1403. if (i != 9) {
  1404. expect($('#multiselect-container li input[value="value-' + i + '"]').prop('checked')).toBe(false, i);
  1405. }
  1406. else {
  1407. expect($('#multiselect-container li input[value="value-' + i + '"]').prop('checked')).toBe(true, i);
  1408. }
  1409. }
  1410. });
  1411. });
  1412. describe('Should deselect only visible options if selectAllJustVisible is true.', function() {
  1413. beforeEach(function(done) {
  1414. $select.multiselect({
  1415. buttonContainer: '<div id="multiselect-container"></div>',
  1416. enableFiltering: true,
  1417. filterBehavior: 'value',
  1418. includeSelectAllOption: true,
  1419. selectAllJustVisible: true,
  1420. selectAllValue: 'multiselect-all',
  1421. onFiltering: function() {
  1422. done();
  1423. }
  1424. });
  1425. $('#multiselect-container li input[value="value-1"]').click();
  1426. $('#multiselect-container li input[value="value-9"]').click();
  1427. for (var i = 1; i < 10; i++) {
  1428. if (i != 9 && i != 1) {
  1429. expect($('#multiselect-container li input[value="value-' + i + '"]').prop('checked')).toBe(false, i);
  1430. }
  1431. else {
  1432. expect($('#multiselect-container li input[value="value-' + i + '"]').prop('checked')).toBe(true, i);
  1433. }
  1434. }
  1435. $('#multiselect-container li.multiselect-filter input').val('value-9').trigger('keydown');
  1436. });
  1437. it('Should deselect one option.', function() {
  1438. $('#multiselect-container li input[value="multiselect-all"]').click();
  1439. for (var i = 1; i < 10; i++) {
  1440. if (i != 1) {
  1441. expect($('#multiselect-container li input[value="value-' + i + '"]').prop('checked')).toBe(false, i);
  1442. }
  1443. else {
  1444. expect($('#multiselect-container li input[value="value-' + i + '"]').prop('checked')).toBe(true, i);
  1445. }
  1446. }
  1447. });
  1448. });
  1449. describe('Should select all options if selectAllJustVisible is false.', function() {
  1450. beforeEach(function(done) {
  1451. $select.multiselect({
  1452. buttonContainer: '<div id="multiselect-container"></div>',
  1453. enableFiltering: true,
  1454. filterBehavior: 'value',
  1455. includeSelectAllOption: true,
  1456. selectAllJustVisible: false,
  1457. selectAllValue: 'multiselect-all',
  1458. onFiltering: function() {
  1459. done();
  1460. }
  1461. });
  1462. for (var i = 1; i < 10; i++) {
  1463. expect($('#multiselect-container li input[value="value-' + i + '"]').prop('checked')).toBe(false, i);
  1464. }
  1465. $('#multiselect-container li.multiselect-filter input').val('value-9').trigger('keydown');
  1466. });
  1467. it('Should select all options.', function() {
  1468. $('#multiselect-container li input[value="multiselect-all"]').click();
  1469. for (var i = 1; i < 10; i++) {
  1470. expect($('#multiselect-container li input[value="value-' + i + '"]').prop('checked')).toBe(true, i);
  1471. }
  1472. });
  1473. });
  1474. describe('Should deselect all options if selectAllJustVisible is false.', function() {
  1475. beforeEach(function(done) {
  1476. $select.multiselect({
  1477. buttonContainer: '<div id="multiselect-container"></div>',
  1478. enableFiltering: true,
  1479. filterBehavior: 'value',
  1480. includeSelectAllOption: true,
  1481. selectAllJustVisible: false,
  1482. selectAllValue: 'multiselect-all',
  1483. onFiltering: function() {
  1484. done();
  1485. }
  1486. });
  1487. for (var i = 1; i < 10; i++) {
  1488. $('#multiselect-container li input[value="value-' + i + '"]').click();
  1489. expect($('#multiselect-container li input[value="value-' + i + '"]').prop('checked')).toBe(true, i);
  1490. }
  1491. $('#multiselect-container li.multiselect-filter input').val('value-9').trigger('keydown');
  1492. });
  1493. it('Should select all options.', function() {
  1494. $('#multiselect-container li input[value="multiselect-all"]').click();
  1495. for (var i = 1; i < 10; i++) {
  1496. expect($('#multiselect-container li input[value="value-' + i + '"]').prop('checked')).toBe(false, i);
  1497. }
  1498. });
  1499. });
  1500. afterEach(function() {
  1501. $('#multiselect').multiselect('destroy');
  1502. $('#multiselect').remove();
  1503. });
  1504. });
  1505. describe('Bootstrap Multiselect "Specific Issues".', function() {
  1506. it('#393.', function() {
  1507. var $select = $('<select id="multiselect" multiple="multiple"></select>');
  1508. for (var i = 1; i < 100; i++) {
  1509. $select.append('<option value="' + i + '">1</option>');
  1510. }
  1511. $('body').append($select);
  1512. $select.multiselect({
  1513. buttonContainer: '<div id="multiselect-container"></div>',
  1514. includeSelectAllOption: true,
  1515. selectAllValue: 0
  1516. });
  1517. expect($('#multiselect-container input[value="0"]').length).toBe(1);
  1518. expect($('#multiselect-container input[value="0"]').prop('checked')).toBe(false);
  1519. $('#multiselect').multiselect('selectAll');
  1520. expect($('#multiselect option:selected').length).toBe(99);
  1521. expect($('#multiselect-container input[value="0"]').prop('checked')).toBe(true);
  1522. $('#multiselect').multiselect('deselectAll');
  1523. expect($('#multiselect option:selected').length).toBe(0);
  1524. expect($('#multiselect-container input[value="0"]').prop('checked')).toBe(false);
  1525. $('#multiselect-container input[value="0"]').click();
  1526. expect($('#multiselect option:selected').length).toBe(99);
  1527. expect($('#multiselect-container input[value="0"]').prop('checked')).toBe(true);
  1528. $('#multiselect-container input[value="0"]').click();
  1529. expect($('#multiselect option:selected').length).toBe(0);
  1530. expect($('#multiselect-container input[value="0"]').prop('checked')).toBe(false);
  1531. $('#multiselect').multiselect('destroy');
  1532. $('#multiselect').remove();
  1533. });
  1534. it('#405.', function() {
  1535. var selection = document.getSelection();
  1536. var range = document.createRange();
  1537. var $selection = $('<span>Some text to select</span>');
  1538. var $select = $('<select id="multiselect" multiple="multiple"></select>');
  1539. for (var i = 1; i < 5; i++) {
  1540. $select.append('<option value="' + i + '">select option</option>');
  1541. }
  1542. $('body').append($selection).append($select);
  1543. $select.multiselect({
  1544. buttonContainer: '<div id="multiselect-container"></div>',
  1545. });
  1546. range.selectNodeContents($selection.get(0));
  1547. selection.removeAllRanges();
  1548. selection.addRange(range);
  1549. if (document.getSelection().type === 'Range') {
  1550. $('#multiselect-container').find('a:first label').trigger('click');
  1551. expect($('#multiselect-container').find('input:first').prop('checked')).toBe(true);
  1552. }
  1553. $('#multiselect').multiselect('destroy');
  1554. $('#multiselect').remove();
  1555. $selection.remove();
  1556. });
  1557. it('#679.', function() {
  1558. var $select = $('<select id="multiselect" multiple="multiple"></select>');
  1559. for (var i = 1; i < 11; i++) {
  1560. var $optgroup = $('<optgroup label="Group ' + i + '"></optgroup>');
  1561. for (var j = 1; j < 11; j++) {
  1562. $optgroup.append('<option value="' + i + '-' + j + '">Option ' + i + '.' + j + '</option>');
  1563. }
  1564. $select.append($optgroup);
  1565. }
  1566. $('body').append($select);
  1567. var fired = 0;
  1568. $select.multiselect({
  1569. buttonContainer: '<div id="multiselect-container"></div>',
  1570. enableClickableOptGroups: true,
  1571. enableCollapsibleOptGroups: true,
  1572. onChange: function(option, checked) {
  1573. fired++;
  1574. }
  1575. });
  1576. expect($('#multiselect option:selected').length).toBe(0);
  1577. expect(fired).toBe(0);
  1578. var i = 0;
  1579. $('#multiselect-container li.multiselect-group').each(function() {
  1580. $('label', $(this)).click();
  1581. // Selected
  1582. expect(fired).toBe(1);
  1583. fired = 0;
  1584. $('label', $(this)).click();
  1585. // Deselected
  1586. expect(fired).toBe(1);
  1587. fired = 0;
  1588. i++;
  1589. });
  1590. $('#multiselect').multiselect('destroy');
  1591. $('#multiselect').remove();
  1592. });
  1593. it('#655/1 when clicking the options.', function() {
  1594. var $select = $('<select id="multiselect" multiple="multiple"></select>');
  1595. $select.append('<optgroup label="Group 1"><option value="1-1">Option 1.1</option><option value="1-2">Option 1.2</option><option value="1-3">Option 1.3</option></optgroup>');
  1596. $select.append('<optgroup label="Group 2"><option value="2-1">Option 2.1</option><option value="2-2">Option 2.2</option><option value="2-3">Option 2.3</option></optgroup>');
  1597. $('body').append($select);
  1598. $select.multiselect({
  1599. buttonContainer: '<div id="multiselect-container"></div>',
  1600. enableClickableOptGroups: true
  1601. });
  1602. $('#multiselect-container input[value="2-1"]').click();
  1603. $('#multiselect-container input[value="2-2"]').click();
  1604. $('#multiselect-container input[value="2-3"]').click();
  1605. expect($($('#multiselect-container li.multiselect-group input')[0]).prop('checked')).toBe(false);
  1606. expect($('#multiselect-container input[value="1-1"]').prop('checked')).toBe(false);
  1607. expect($('#multiselect-container input[value="1-2"]').prop('checked')).toBe(false);
  1608. expect($('#multiselect-container input[value="1-3"]').prop('checked')).toBe(false);
  1609. expect($($('#multiselect-container li.multiselect-group input')[1]).prop('checked')).toBe(true);
  1610. expect($('#multiselect-container input[value="2-1"]').prop('checked')).toBe(true);
  1611. expect($('#multiselect-container input[value="2-2"]').prop('checked')).toBe(true);
  1612. expect($('#multiselect-container input[value="2-3"]').prop('checked')).toBe(true);
  1613. $('#multiselect').multiselect('destroy');
  1614. $('#multiselect').remove();
  1615. });
  1616. it('#655/1 when clicking the optgroup.', function() {
  1617. var $select = $('<select id="multiselect" multiple="multiple"></select>');
  1618. $select.append('<optgroup label="Group 1"><option value="1-1">Option 1.1</option><option value="1-2">Option 1.2</option><option value="1-3">Option 1.3</option></optgroup>');
  1619. $select.append('<optgroup label="Group 2"><option value="2-1">Option 2.1</option><option value="2-2">Option 2.2</option><option value="2-3">Option 2.3</option></optgroup>');
  1620. $('body').append($select);
  1621. $select.multiselect({
  1622. buttonContainer: '<div id="multiselect-container"></div>',
  1623. enableClickableOptGroups: true
  1624. });
  1625. $($('#multiselect-container li.multiselect-group input')[1]).click();
  1626. expect($($('#multiselect-container li.multiselect-group input')[0]).prop('checked')).toBe(false);
  1627. expect($('#multiselect-container input[value="1-1"]').prop('checked')).toBe(false);
  1628. expect($('#multiselect-container input[value="1-2"]').prop('checked')).toBe(false);
  1629. expect($('#multiselect-container input[value="1-3"]').prop('checked')).toBe(false);
  1630. expect($($('#multiselect-container li.multiselect-group input')[1]).prop('checked')).toBe(true);
  1631. expect($('#multiselect-container input[value="2-1"]').prop('checked')).toBe(true);
  1632. expect($('#multiselect-container input[value="2-2"]').prop('checked')).toBe(true);
  1633. expect($('#multiselect-container input[value="2-3"]').prop('checked')).toBe(true);
  1634. $('#multiselect').multiselect('destroy');
  1635. $('#multiselect').remove();
  1636. });
  1637. it('#655/2 when clicking the options.', function() {
  1638. var $select = $('<select id="multiselect" multiple="multiple"></select>');
  1639. $select.append('<optgroup label="Group 1"><option value="1-1">Option 1.1</option><option value="1-2">Option 1.2</option><option value="1-3">Option 1.3</option></optgroup>');
  1640. $select.append('<optgroup label="Group 2"><option value="2-1">Option 2.1</option><option value="2-2">Option 2.2</option><option value="2-3">Option 2.3</option></optgroup>');
  1641. $('body').append($select);
  1642. $select.multiselect({
  1643. buttonContainer: '<div id="multiselect-container"></div>',
  1644. enableClickableOptGroups: true,
  1645. selectedClass: 'multiselect-custom-selected'
  1646. });
  1647. $('#multiselect-container input[value="2-1"]').click();
  1648. $('#multiselect-container input[value="2-2"]').click();
  1649. $('#multiselect-container input[value="2-3"]').click();
  1650. expect($($('#multiselect-container li.multiselect-group')[0]).prop('class').split(' ')).not.toContain('multiselect-custom-selected');
  1651. expect($('#multiselect-container li:has(input[value="1-1"])').prop('class').split(' ')).not.toContain('multiselect-custom-selected');
  1652. expect($('#multiselect-container li:has(input[value="1-2"])').prop('class').split(' ')).not.toContain('multiselect-custom-selected');
  1653. expect($('#multiselect-container li:has(input[value="1-3"])').prop('class').split(' ')).not.toContain('multiselect-custom-selected');
  1654. expect($($('#multiselect-container li.multiselect-group')[1]).prop('class').split(' ')).toContain('multiselect-custom-selected');
  1655. expect($('#multiselect-container li:has(input[value="2-1"])').prop('class').split(' ')).toContain('multiselect-custom-selected');
  1656. expect($('#multiselect-container li:has(input[value="2-2"])').prop('class').split(' ')).toContain('multiselect-custom-selected');
  1657. expect($('#multiselect-container li:has(input[value="2-3"])').prop('class').split(' ')).toContain('multiselect-custom-selected');
  1658. $('#multiselect').multiselect('destroy');
  1659. $('#multiselect').remove();
  1660. });
  1661. it('#655/2 when clicking the optgroup.', function() {
  1662. var $select = $('<select id="multiselect" multiple="multiple"></select>');
  1663. $select.append('<optgroup label="Group 1"><option value="1-1">Option 1.1</option><option value="1-2">Option 1.2</option><option value="1-3">Option 1.3</option></optgroup>');
  1664. $select.append('<optgroup label="Group 2"><option value="2-1">Option 2.1</option><option value="2-2">Option 2.2</option><option value="2-3">Option 2.3</option></optgroup>');
  1665. $('body').append($select);
  1666. $select.multiselect({
  1667. buttonContainer: '<div id="multiselect-container"></div>',
  1668. enableClickableOptGroups: true,
  1669. selectedClass: 'multiselect-custom-selected'
  1670. });
  1671. $($('#multiselect-container li.multiselect-group input')[1]).click();
  1672. expect($($('#multiselect-container li.multiselect-group')[0]).prop('class').split(' ')).not.toContain('multiselect-custom-selected');
  1673. expect($('#multiselect-container li:has(input[value="1-1"])').prop('class').split(' ')).not.toContain('multiselect-custom-selected');
  1674. expect($('#multiselect-container li:has(input[value="1-2"])').prop('class').split(' ')).not.toContain('multiselect-custom-selected');
  1675. expect($('#multiselect-container li:has(input[value="1-3"])').prop('class').split(' ')).not.toContain('multiselect-custom-selected');
  1676. expect($($('#multiselect-container li.multiselect-group')[1]).prop('class').split(' ')).toContain('multiselect-custom-selected');
  1677. expect($('#multiselect-container li:has(input[value="2-1"])').prop('class').split(' ')).toContain('multiselect-custom-selected');
  1678. expect($('#multiselect-container li:has(input[value="2-2"])').prop('class').split(' ')).toContain('multiselect-custom-selected');
  1679. expect($('#multiselect-container li:has(input[value="2-3"])').prop('class').split(' ')).toContain('multiselect-custom-selected');
  1680. $('#multiselect').multiselect('destroy');
  1681. $('#multiselect').remove();
  1682. });
  1683. describe('#732.', function() {
  1684. var triggeredOnSelectAll = false;
  1685. var triggeredOnDeselectAll = false;
  1686. beforeEach(function(done) {
  1687. triggeredOnSelectAll = false;
  1688. triggeredOnDeselectAll = false;
  1689. var $select = $('<select id="multiselect" multiple="multiple"></select>');
  1690. $select.append('<option value="value-1">Option 1</option><option value="value-2">Option 2</option><option value="value-1">Option 1</option>');
  1691. $('body').append($select);
  1692. $select.multiselect({
  1693. buttonContainer: '<div id="multiselect-container"></div>',
  1694. enableFiltering: true,
  1695. includeSelectAllOption: true,
  1696. onSelectAll: function() {
  1697. triggeredOnSelectAll = true;
  1698. },
  1699. onDeselectAll: function() {
  1700. triggeredOnDeselectAll = false;
  1701. },
  1702. onFiltering: function() {
  1703. done();
  1704. }
  1705. });
  1706. $('#multiselect-container li.multiselect-filter input').val('2').trigger('keydown');
  1707. });
  1708. it('Should not fire onSelectAll or onDeselectAll when filtering or clearing filter.', function() {
  1709. expect(triggeredOnSelectAll).toBe(false);
  1710. expect(triggeredOnDeselectAll).toBe(false);
  1711. $('#multiselect-container li.multiselect-filter .multiselect-clear-filter').click();
  1712. expect(triggeredOnSelectAll).toBe(false);
  1713. expect(triggeredOnDeselectAll).toBe(false);
  1714. });
  1715. afterEach(function() {
  1716. $('#multiselect').multiselect('destroy');
  1717. $('#multiselect').remove();
  1718. });
  1719. });
  1720. it('#759.', function() {
  1721. var $select = $('<select data-placeholder="Test" id="multiselect" multiple="multiple"></select>');
  1722. $select.append('<option value="value-1">Option 1</option><option value="value-2">Option 2</option><option value="value-3">Option 3</option>');
  1723. $('body').append($select);
  1724. $select.multiselect({
  1725. buttonContainer: '<div id="multiselect-container"></div>'
  1726. });
  1727. expect($('#multiselect-container .multiselect-selected-text').text()).toBe('Test');
  1728. $('#multiselect').multiselect('destroy');
  1729. $('#multiselect').remove();
  1730. });
  1731. });
  1732. describe('Knockout Binding.', function() {
  1733. var $testArea;
  1734. afterEach(function() {
  1735. if ($testArea) {
  1736. $testArea.multiselect('destroy').remove();
  1737. }
  1738. });
  1739. it('Should update values and options with an observable array.', function() {
  1740. jasmine.clock().install();
  1741. $testArea = $('<select multiple="multiple" data-bind="selectedOptions: myValues, options: myOptions, multiselect: {numberDisplayed: 1}"></select>').appendTo(document.body);
  1742. var viewModel = {
  1743. myValues: ko.observableArray(),
  1744. myOptions: ko.observableArray([])
  1745. };
  1746. expect(ko.bindingHandlers.multiselect.init !== undefined).toEqual(true);
  1747. var optionSpy = spyOn(ko.bindingHandlers.selectedOptions, 'init').and.callThrough();
  1748. var multiSpy = spyOn(ko.bindingHandlers.multiselect, 'init').and.callThrough();
  1749. ko.applyBindings(viewModel, $testArea[0]);
  1750. // knockout bindings were called
  1751. expect(optionSpy.calls.count()).toEqual(1);
  1752. expect(multiSpy.calls.count()).toEqual(1);
  1753. // no options are present since myOptions was empty
  1754. expect($testArea.find('option').length).toEqual(0);
  1755. expect($testArea.val()).toEqual(null);
  1756. expect($testArea.next().find('button.multiselect').text().trim()).toEqual('None selected');
  1757. expect($testArea.next().find('ul li').length).toEqual(0);
  1758. // Add more options
  1759. viewModel.myOptions(['option1', 'option2']);
  1760. jasmine.clock().tick(1000);
  1761. expect($testArea.next().find('ul li').length).toEqual(2);
  1762. expect($testArea.find('option').length).toEqual(2);
  1763. expect($testArea.find('option:checked').length).toEqual(0);
  1764. // select one
  1765. viewModel.myValues(['option2']);
  1766. jasmine.clock().tick(1000);
  1767. expect($testArea.find('option:checked').length).toEqual(1);
  1768. expect($testArea.find('option:checked').text().trim()).toEqual('option2');
  1769. // select all
  1770. viewModel.myValues(['option1', 'option2']);
  1771. jasmine.clock().tick(1000);
  1772. expect($testArea.find('option:checked').length).toEqual(2);
  1773. expect($testArea.find('option:checked').map(function() { return $(this).text().trim() }).toArray()).toEqual(['option1', 'option2']);
  1774. expect($testArea.next().find('button.multiselect').text().trim()).toEqual('All selected (2)');
  1775. // add another option
  1776. viewModel.myOptions.push('wacky option');
  1777. jasmine.clock().tick(1000);
  1778. expect($testArea.find('option:checked').length).toEqual(2);
  1779. expect($testArea.find('option:checked').map(function() { return $(this).text().trim() }).toArray()).toEqual(['option1', 'option2']);
  1780. expect($testArea.find('option').map(function() { return $(this).text().trim() }).toArray()).toEqual(['option1', 'option2', 'wacky option']);
  1781. expect($testArea.next().find('button.multiselect').text().trim()).toEqual('2 selected');
  1782. });
  1783. });
  1784. describe('Bootstrap Multiselect "Reset".', function() {
  1785. var $select;
  1786. beforeEach(function() {
  1787. $select = $('<select id="multiselect" multiple="multiple"></select>');
  1788. for (var i = 1; i < 100; i++) {
  1789. $select.append('<option value="' + i + '">1</option>');
  1790. }
  1791. $('body').append($select);
  1792. $select.multiselect({
  1793. buttonContainer: '<div id="multiselect-container"></div>',
  1794. includeResetOption: true
  1795. });
  1796. });
  1797. it('Should not add an additional option to the select.', function() {
  1798. expect($select.find('option').length).toBe(99);
  1799. });
  1800. it('Should add reset button.', function() {
  1801. expect($('#multiselect-container').find('li.multiselect-reset a').text()).toBe('Reset');
  1802. });
  1803. it('Should reset if button clicked.', function() {
  1804. $select.multiselect('selectAll', true, false);
  1805. expect($select.find('option:selected').length).toBe(99);
  1806. $('#multiselect-container').find('li.multiselect-reset a').click();
  1807. expect($select.find('option:selected').length).toBe(0);
  1808. });
  1809. afterEach(function() {
  1810. $select.multiselect('destroy');
  1811. $select.remove();
  1812. });
  1813. });