jquery.bootstrap-duallistbox.js 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710
  1. ;(function ($, window, document, undefined) {
  2. // Create the defaults once
  3. var pluginName = 'bootstrapDualListbox',
  4. defaults = {
  5. bootstrap2Compatible: false,
  6. filterTextClear: 'show all',
  7. filterPlaceHolder: 'Filter',
  8. moveSelectedLabel: 'Move selected',
  9. moveAllLabel: 'Move all',
  10. removeSelectedLabel: 'Remove selected',
  11. removeAllLabel: 'Remove all',
  12. moveOnSelect: true, // true/false (forced true on androids, see the comment later)
  13. preserveSelectionOnMove: false, // 'all' / 'moved' / false
  14. selectedListLabel: false, // 'string', false
  15. nonSelectedListLabel: false, // 'string', false
  16. helperSelectNamePostfix: '_helper', // 'string_of_postfix' / false
  17. selectorMinimalHeight: 100,
  18. showFilterInputs: true, // whether to show filter inputs
  19. nonSelectedFilter: '', // string, filter the non selected options
  20. selectedFilter: '', // string, filter the selected options
  21. infoText: 'Showing all {0}', // text when all options are visible / false for no info text
  22. infoTextFiltered: '<span class="label label-warning">Filtered</span> {0} from {1}', // when not all of the options are visible due to the filter
  23. infoTextEmpty: 'Empty list', // when there are no options present in the list
  24. filterOnValues: false // filter by selector's values, boolean
  25. , buttonClass: 'btn-white btn-bold'//ACE
  26. },
  27. // Selections are invisible on android if the containing select is styled with CSS
  28. // http://code.google.com/p/android/issues/detail?id=16922
  29. isBuggyAndroid = /android/i.test(navigator.userAgent.toLowerCase());
  30. // The actual plugin constructor
  31. function BootstrapDualListbox(element, options) {
  32. this.element = $(element);
  33. // jQuery has an extend method which merges the contents of two or
  34. // more objects, storing the result in the first object. The first object
  35. // is generally empty as we don't want to alter the default options for
  36. // future instances of the plugin
  37. this.settings = $.extend({}, defaults, options);
  38. this._defaults = defaults;
  39. this._name = pluginName;
  40. this.init();
  41. }
  42. function triggerChangeEvent(dualListbox) {
  43. dualListbox.element.trigger('change');
  44. }
  45. function updateSelectionStates(dualListbox) {
  46. dualListbox.element.find('option').each(function(index, item) {
  47. var $item = $(item);
  48. if (typeof($item.data('original-index')) === 'undefined') {
  49. $item.data('original-index', dualListbox.elementCount++);
  50. }
  51. if (typeof($item.data('_selected')) === 'undefined') {
  52. $item.data('_selected', false);
  53. }
  54. });
  55. }
  56. function changeSelectionState(dualListbox, original_index, selected) {
  57. dualListbox.element.find('option').each(function(index, item) {
  58. var $item = $(item);
  59. if ($item.data('original-index') === original_index) {
  60. $item.prop('selected', selected);
  61. }
  62. });
  63. }
  64. function formatString(s, args) {
  65. return s.replace(/\{(\d+)\}/g, function(match, number) {
  66. return typeof args[number] !== 'undefined' ? args[number] : match;
  67. });
  68. }
  69. function refreshInfo(dualListbox) {
  70. if (!dualListbox.settings.infoText) {
  71. return;
  72. }
  73. var visible1 = dualListbox.elements.select1.find('option').length,
  74. visible2 = dualListbox.elements.select2.find('option').length,
  75. all1 = dualListbox.element.find('option').length - dualListbox.selectedElements,
  76. all2 = dualListbox.selectedElements,
  77. content = '';
  78. if (all1 === 0) {
  79. content = dualListbox.settings.infoTextEmpty;
  80. } else if (visible1 === all1) {
  81. content = formatString(dualListbox.settings.infoText, [visible1, all1]);
  82. } else {
  83. content = formatString(dualListbox.settings.infoTextFiltered, [visible1, all1]);
  84. }
  85. dualListbox.elements.info1.html(content);
  86. dualListbox.elements.box1.toggleClass('filtered', !(visible1 === all1 || all1 === 0));
  87. if (all2 === 0) {
  88. content = dualListbox.settings.infoTextEmpty;
  89. } else if (visible2 === all2) {
  90. content = formatString(dualListbox.settings.infoText, [visible2, all2]);
  91. } else {
  92. content = formatString(dualListbox.settings.infoTextFiltered, [visible2, all2]);
  93. }
  94. dualListbox.elements.info2.html(content);
  95. dualListbox.elements.box2.toggleClass('filtered', !(visible2 === all2 || all2 === 0));
  96. }
  97. function refreshSelects(dualListbox) {
  98. dualListbox.selectedElements = 0;
  99. dualListbox.elements.select1.empty();
  100. dualListbox.elements.select2.empty();
  101. dualListbox.element.find('option').each(function(index, item) {
  102. var $item = $(item);
  103. if ($item.prop('selected')) {
  104. dualListbox.selectedElements++;
  105. dualListbox.elements.select2.append($item.clone(true).prop('selected', $item.data('_selected')));
  106. } else {
  107. dualListbox.elements.select1.append($item.clone(true).prop('selected', $item.data('_selected')));
  108. }
  109. });
  110. if (dualListbox.settings.showFilterInputs) {
  111. filter(dualListbox, 1);
  112. filter(dualListbox, 2);
  113. }
  114. refreshInfo(dualListbox);
  115. }
  116. function filter(dualListbox, selectIndex) {
  117. if (!dualListbox.settings.showFilterInputs) {
  118. return;
  119. }
  120. saveSelections(dualListbox, selectIndex);
  121. dualListbox.elements['select'+selectIndex].empty().scrollTop(0);
  122. var regex = new RegExp($.trim(dualListbox.elements['filterInput'+selectIndex].val()), 'gi'),
  123. options = dualListbox.element;
  124. if (selectIndex === 1) {
  125. options = options.find('option').not(':selected');
  126. } else {
  127. options = options.find('option:selected');
  128. }
  129. options.each(function(index, item) {
  130. var $item = $(item),
  131. isFiltered = true;
  132. if (item.text.match(regex) || (dualListbox.settings.filterOnValues && $item.attr('value').match(regex) ) ) {
  133. isFiltered = false;
  134. dualListbox.elements['select'+selectIndex].append($item.clone(true).prop('selected', $item.data('_selected')));
  135. }
  136. dualListbox.element.find('option').eq($item.data('original-index')).data('filtered'+selectIndex, isFiltered);
  137. });
  138. refreshInfo(dualListbox);
  139. }
  140. function saveSelections(dualListbox, selectIndex) {
  141. dualListbox.elements['select'+selectIndex].find('option').each(function(index, item) {
  142. var $item = $(item);
  143. dualListbox.element.find('option').eq($item.data('original-index')).data('_selected', $item.prop('selected'));
  144. });
  145. }
  146. function sortOptions(select) {
  147. select.find('option').sort(function(a, b) {
  148. return ($(a).data('original-index') > $(b).data('original-index')) ? 1 : -1;
  149. }).appendTo(select);
  150. }
  151. function clearSelections(dualListbox) {
  152. dualListbox.elements.select1.find('option').each(function() {
  153. dualListbox.element.find('option').data('_selected', false);
  154. });
  155. }
  156. function move(dualListbox) {
  157. if (dualListbox.settings.preserveSelectionOnMove === 'all' && !dualListbox.settings.moveOnSelect) {
  158. saveSelections(dualListbox, 1);
  159. saveSelections(dualListbox, 2);
  160. } else if (dualListbox.settings.preserveSelectionOnMove === 'moved' && !dualListbox.settings.moveOnSelect) {
  161. saveSelections(dualListbox, 1);
  162. }
  163. dualListbox.elements.select1.find('option:selected').each(function(index, item) {
  164. var $item = $(item);
  165. if (!$item.data('filtered1')) {
  166. changeSelectionState(dualListbox, $item.data('original-index'), true);
  167. }
  168. });
  169. refreshSelects(dualListbox);
  170. triggerChangeEvent(dualListbox);
  171. sortOptions(dualListbox.elements.select2);
  172. }
  173. function remove(dualListbox) {
  174. if (dualListbox.settings.preserveSelectionOnMove === 'all' && !dualListbox.settings.moveOnSelect) {
  175. saveSelections(dualListbox, 1);
  176. saveSelections(dualListbox, 2);
  177. } else if (dualListbox.settings.preserveSelectionOnMove === 'moved' && !dualListbox.settings.moveOnSelect) {
  178. saveSelections(dualListbox, 2);
  179. }
  180. dualListbox.elements.select2.find('option:selected').each(function(index, item) {
  181. var $item = $(item);
  182. if (!$item.data('filtered2')) {
  183. changeSelectionState(dualListbox, $item.data('original-index'), false);
  184. }
  185. });
  186. refreshSelects(dualListbox);
  187. triggerChangeEvent(dualListbox);
  188. sortOptions(dualListbox.elements.select1);
  189. }
  190. function moveAll(dualListbox) {
  191. if (dualListbox.settings.preserveSelectionOnMove === 'all' && !dualListbox.settings.moveOnSelect) {
  192. saveSelections(dualListbox, 1);
  193. saveSelections(dualListbox, 2);
  194. } else if (dualListbox.settings.preserveSelectionOnMove === 'moved' && !dualListbox.settings.moveOnSelect) {
  195. saveSelections(dualListbox, 1);
  196. }
  197. dualListbox.element.find('option').each(function(index, item) {
  198. var $item = $(item);
  199. if (!$item.data('filtered1')) {
  200. $item.prop('selected', true);
  201. }
  202. });
  203. refreshSelects(dualListbox);
  204. triggerChangeEvent(dualListbox);
  205. }
  206. function removeAll(dualListbox) {
  207. if (dualListbox.settings.preserveSelectionOnMove === 'all' && !dualListbox.settings.moveOnSelect) {
  208. saveSelections(dualListbox, 1);
  209. saveSelections(dualListbox, 2);
  210. } else if (dualListbox.settings.preserveSelectionOnMove === 'moved' && !dualListbox.settings.moveOnSelect) {
  211. saveSelections(dualListbox, 2);
  212. }
  213. dualListbox.element.find('option').each(function(index, item) {
  214. var $item = $(item);
  215. if (!$item.data('filtered2')) {
  216. $item.prop('selected', false);
  217. }
  218. });
  219. refreshSelects(dualListbox);
  220. triggerChangeEvent(dualListbox);
  221. }
  222. function bindEvents(dualListbox) {
  223. dualListbox.elements.form.submit(function(e) {
  224. if (dualListbox.elements.filterInput1.is(':focus')) {
  225. e.preventDefault();
  226. dualListbox.elements.filterInput1.focusout();
  227. } else if (dualListbox.elements.filterInput2.is(':focus')) {
  228. e.preventDefault();
  229. dualListbox.elements.filterInput2.focusout();
  230. }
  231. });
  232. dualListbox.element.on('bootstrapDualListbox.refresh', function(e, mustClearSelections){
  233. dualListbox.refresh(mustClearSelections);
  234. });
  235. dualListbox.elements.filterClear1.on('click', function() {
  236. dualListbox.setNonSelectedFilter('', true);
  237. });
  238. dualListbox.elements.filterClear2.on('click', function() {
  239. dualListbox.setSelectedFilter('', true);
  240. });
  241. dualListbox.elements.moveButton.on('click', function() {
  242. move(dualListbox);
  243. });
  244. dualListbox.elements.moveAllButton.on('click', function() {
  245. moveAll(dualListbox);
  246. });
  247. dualListbox.elements.removeButton.on('click', function() {
  248. remove(dualListbox);
  249. });
  250. dualListbox.elements.removeAllButton.on('click', function() {
  251. removeAll(dualListbox);
  252. });
  253. dualListbox.elements.filterInput1.on('change keyup', function() {
  254. filter(dualListbox, 1);
  255. });
  256. dualListbox.elements.filterInput2.on('change keyup', function() {
  257. filter(dualListbox, 2);
  258. });
  259. }
  260. BootstrapDualListbox.prototype = {
  261. init: function () {
  262. // Add the custom HTML template
  263. this.container = $('' +
  264. '<div class="bootstrap-duallistbox-container">' +
  265. ' <div class="box1">' +
  266. ' <label></label>' +
  267. ' <span class="info-container">' +
  268. ' <span class="info"></span>' +
  269. ' <button type="button" class="btn clear1 pull-right"></button>' +
  270. ' </span>' +
  271. ' <input class="filter" type="text">' +
  272. ' <div class="btn-group buttons">' +
  273. ' <button type="button" class="btn moveall">' +
  274. ' <i></i>' +
  275. ' <i></i>' +
  276. ' </button>' +
  277. ' <button type="button" class="btn move">' +
  278. ' <i></i>' +
  279. ' </button>' +
  280. ' </div>' +
  281. ' <select multiple="multiple"></select>' +
  282. ' </div>' +
  283. ' <div class="box2">' +
  284. ' <label></label>' +
  285. ' <span class="info-container">' +
  286. ' <span class="info"></span>' +
  287. ' <button type="button" class="btn clear2 pull-right"></button>' +
  288. ' </span>' +
  289. ' <input class="filter" type="text">' +
  290. ' <div class="btn-group buttons">' +
  291. ' <button type="button" class="btn remove">' +
  292. ' <i></i>' +
  293. ' </button>' +
  294. ' <button type="button" class="btn removeall">' +
  295. ' <i></i>' +
  296. ' <i></i>' +
  297. ' </button>' +
  298. ' </div>' +
  299. ' <select multiple="multiple"></select>' +
  300. ' </div>' +
  301. '</div>')
  302. .insertBefore(this.element);
  303. // Cache the inner elements
  304. this.elements = {
  305. originalSelect: this.element,
  306. box1: $('.box1', this.container),
  307. box2: $('.box2', this.container),
  308. filterInput1: $('.box1 .filter', this.container),
  309. filterInput2: $('.box2 .filter', this.container),
  310. filterClear1: $('.box1 .clear1', this.container),
  311. filterClear2: $('.box2 .clear2', this.container),
  312. label1: $('.box1 > label', this.container),
  313. label2: $('.box2 > label', this.container),
  314. info1: $('.box1 .info', this.container),
  315. info2: $('.box2 .info', this.container),
  316. select1: $('.box1 select', this.container),
  317. select2: $('.box2 select', this.container),
  318. moveButton: $('.box1 .move', this.container),
  319. removeButton: $('.box2 .remove', this.container),
  320. moveAllButton: $('.box1 .moveall', this.container),
  321. removeAllButton: $('.box2 .removeall', this.container),
  322. form: $($('.box1 .filter', this.container)[0].form)
  323. };
  324. // Set select IDs
  325. this.originalSelectName = this.element.attr('name') || '';
  326. var select1Id = 'bootstrap-duallistbox-nonselected-list_' + this.originalSelectName,
  327. select2Id = 'bootstrap-duallistbox-selected-list_' + this.originalSelectName;
  328. this.elements.select1.attr('id', select1Id);
  329. this.elements.select2.attr('id', select2Id);
  330. this.elements.label1.attr('for', select1Id);
  331. this.elements.label2.attr('for', select2Id);
  332. // Apply all settings
  333. this.selectedElements = 0;
  334. this.elementCount = 0;
  335. this.setBootstrap2Compatible(this.settings.bootstrap2Compatible);
  336. this.setFilterTextClear(this.settings.filterTextClear);
  337. this.setFilterPlaceHolder(this.settings.filterPlaceHolder);
  338. this.setMoveSelectedLabel(this.settings.moveSelectedLabel);
  339. this.setMoveAllLabel(this.settings.moveAllLabel);
  340. this.setRemoveSelectedLabel(this.settings.removeSelectedLabel);
  341. this.setRemoveAllLabel(this.settings.removeAllLabel);
  342. this.setMoveOnSelect(this.settings.moveOnSelect);
  343. this.setPreserveSelectionOnMove(this.settings.preserveSelectionOnMove);
  344. this.setSelectedListLabel(this.settings.selectedListLabel);
  345. this.setNonSelectedListLabel(this.settings.nonSelectedListLabel);
  346. this.setHelperSelectNamePostfix(this.settings.helperSelectNamePostfix);
  347. this.setSelectOrMinimalHeight(this.settings.selectorMinimalHeight);
  348. updateSelectionStates(this);
  349. this.setShowFilterInputs(this.settings.showFilterInputs);
  350. this.setNonSelectedFilter(this.settings.nonSelectedFilter);
  351. this.setSelectedFilter(this.settings.selectedFilter);
  352. this.setInfoText(this.settings.infoText);
  353. this.setInfoTextFiltered(this.settings.infoTextFiltered);
  354. this.setInfoTextEmpty(this.settings.infoTextEmpty);
  355. this.setFilterOnValues(this.settings.filterOnValues);
  356. // Hide the original select
  357. this.element.hide();
  358. bindEvents(this);
  359. refreshSelects(this);
  360. return this.element;
  361. },
  362. setBootstrap2Compatible: function(value, refresh) {
  363. this.settings.bootstrap2Compatible = value;
  364. if (value) {
  365. this.container.removeClass('row').addClass('row-fluid bs2compatible');
  366. this.container.find('.box1, .box2').removeClass('col-md-6').addClass('span6');
  367. this.container.find('.clear1, .clear2').removeClass('btn-default btn-xs').addClass('btn-mini');
  368. this.container.find('input, select').removeClass('form-control');
  369. this.container.find('.btn').removeClass('btn-default');
  370. this.container.find('.moveall > i, .move > i').removeClass('glyphicon glyphicon-arrow-right').addClass('icon-arrow-right');
  371. this.container.find('.removeall > i, .remove > i').removeClass('glyphicon glyphicon-arrow-left').addClass('icon-arrow-left');
  372. } else {
  373. this.container.removeClass('row-fluid bs2compatible').addClass('row');
  374. this.container.find('.box1, .box2').removeClass('span6').addClass('col-md-6');
  375. this.container.find('.clear1, .clear2').removeClass('btn-mini').addClass('btn-default btn-xs');
  376. this.container.find('input, select').addClass('form-control');
  377. this.container.find('.btn').addClass(this.settings.buttonClass)//ACE;//s.addClass('btn-default');
  378. this.container.find('.moveall > i, .move > i').removeClass('icon-arrow-right').addClass('glyphicon glyphicon-arrow-right');
  379. this.container.find('.removeall > i, .remove > i').removeClass('icon-arrow-left').addClass('glyphicon glyphicon-arrow-left');
  380. }
  381. if (refresh) {
  382. refreshSelects(this);
  383. }
  384. return this.element;
  385. },
  386. setFilterTextClear: function(value, refresh) {
  387. this.settings.filterTextClear = value;
  388. this.elements.filterClear1.html(value);
  389. this.elements.filterClear2.html(value);
  390. if (refresh) {
  391. refreshSelects(this);
  392. }
  393. return this.element;
  394. },
  395. setFilterPlaceHolder: function(value, refresh) {
  396. this.settings.filterPlaceHolder = value;
  397. this.elements.filterInput1.attr('placeholder', value);
  398. this.elements.filterInput2.attr('placeholder', value);
  399. if (refresh) {
  400. refreshSelects(this);
  401. }
  402. return this.element;
  403. },
  404. setMoveSelectedLabel: function(value, refresh) {
  405. this.settings.moveSelectedLabel = value;
  406. this.elements.moveButton.attr('title', value);
  407. if (refresh) {
  408. refreshSelects(this);
  409. }
  410. return this.element;
  411. },
  412. setMoveAllLabel: function(value, refresh) {
  413. this.settings.moveAllLabel = value;
  414. this.elements.moveAllButton.attr('title', value);
  415. if (refresh) {
  416. refreshSelects(this);
  417. }
  418. return this.element;
  419. },
  420. setRemoveSelectedLabel: function(value, refresh) {
  421. this.settings.removeSelectedLabel = value;
  422. this.elements.removeButton.attr('title', value);
  423. if (refresh) {
  424. refreshSelects(this);
  425. }
  426. return this.element;
  427. },
  428. setRemoveAllLabel: function(value, refresh) {
  429. this.settings.removeAllLabel = value;
  430. this.elements.removeAllButton.attr('title', value);
  431. if (refresh) {
  432. refreshSelects(this);
  433. }
  434. return this.element;
  435. },
  436. setMoveOnSelect: function(value, refresh) {
  437. if (isBuggyAndroid) {
  438. value = true;
  439. }
  440. this.settings.moveOnSelect = value;
  441. if (this.settings.moveOnSelect) {
  442. this.container.addClass('moveonselect');
  443. var self = this;
  444. this.elements.select1.on('change', function() {
  445. move(self);
  446. });
  447. this.elements.select2.on('change', function() {
  448. remove(self);
  449. });
  450. } else {
  451. this.container.removeClass('moveonselect');
  452. this.elements.select1.off('change');
  453. this.elements.select2.off('change');
  454. }
  455. if (refresh) {
  456. refreshSelects(this);
  457. }
  458. return this.element;
  459. },
  460. setPreserveSelectionOnMove: function(value, refresh) {
  461. // We are forcing to move on select and disabling preserveSelectionOnMove on Android
  462. if (isBuggyAndroid) {
  463. value = false;
  464. }
  465. this.settings.preserveSelectionOnMove = value;
  466. if (refresh) {
  467. refreshSelects(this);
  468. }
  469. return this.element;
  470. },
  471. setSelectedListLabel: function(value, refresh) {
  472. this.settings.selectedListLabel = value;
  473. if (value) {
  474. this.elements.label2.show().html(value);
  475. } else {
  476. this.elements.label2.hide().html(value);
  477. }
  478. if (refresh) {
  479. refreshSelects(this);
  480. }
  481. return this.element;
  482. },
  483. setNonSelectedListLabel: function(value, refresh) {
  484. this.settings.nonSelectedListLabel = value;
  485. if (value) {
  486. this.elements.label1.show().html(value);
  487. } else {
  488. this.elements.label1.hide().html(value);
  489. }
  490. if (refresh) {
  491. refreshSelects(this);
  492. }
  493. return this.element;
  494. },
  495. setHelperSelectNamePostfix: function(value, refresh) {
  496. this.settings.helperSelectNamePostfix = value;
  497. if (value) {
  498. this.elements.select1.attr('name', this.originalSelectName + value + '1');
  499. this.elements.select2.attr('name', this.originalSelectName + value + '2');
  500. } else {
  501. this.elements.select1.removeAttr('name');
  502. this.elements.select2.removeAttr('name');
  503. }
  504. if (refresh) {
  505. refreshSelects(this);
  506. }
  507. return this.element;
  508. },
  509. setSelectOrMinimalHeight: function(value, refresh) {
  510. this.settings.selectorMinimalHeight = value;
  511. var height = this.element.height();
  512. if (this.element.height() < value) {
  513. height = value;
  514. }
  515. this.elements.select1.height(height);
  516. this.elements.select2.height(height);
  517. if (refresh) {
  518. refreshSelects(this);
  519. }
  520. return this.element;
  521. },
  522. setShowFilterInputs: function(value, refresh) {
  523. if (!value) {
  524. this.setNonSelectedFilter('');
  525. this.setSelectedFilter('');
  526. refreshSelects(this);
  527. this.elements.filterInput1.hide();
  528. this.elements.filterInput2.hide();
  529. } else {
  530. this.elements.filterInput1.show();
  531. this.elements.filterInput2.show();
  532. }
  533. this.settings.showFilterInputs = value;
  534. if (refresh) {
  535. refreshSelects(this);
  536. }
  537. return this.element;
  538. },
  539. setNonSelectedFilter: function(value, refresh) {
  540. if (this.settings.showFilterInputs) {
  541. this.settings.nonSelectedFilter = value;
  542. this.elements.filterInput1.val(value);
  543. if (refresh) {
  544. refreshSelects(this);
  545. }
  546. return this.element;
  547. }
  548. },
  549. setSelectedFilter: function(value, refresh) {
  550. if (this.settings.showFilterInputs) {
  551. this.settings.selectedFilter = value;
  552. this.elements.filterInput2.val(value);
  553. if (refresh) {
  554. refreshSelects(this);
  555. }
  556. return this.element;
  557. }
  558. },
  559. setInfoText: function(value, refresh) {
  560. this.settings.infoText = value;
  561. if (refresh) {
  562. refreshSelects(this);
  563. }
  564. return this.element;
  565. },
  566. setInfoTextFiltered: function(value, refresh) {
  567. this.settings.infoTextFiltered = value;
  568. if (refresh) {
  569. refreshSelects(this);
  570. }
  571. return this.element;
  572. },
  573. setInfoTextEmpty: function(value, refresh) {
  574. this.settings.infoTextEmpty = value;
  575. if (refresh) {
  576. refreshSelects(this);
  577. }
  578. return this.element;
  579. },
  580. setFilterOnValues: function(value, refresh) {
  581. this.settings.filterOnValues = value;
  582. if (refresh) {
  583. refreshSelects(this);
  584. }
  585. return this.element;
  586. },
  587. getContainer: function() {
  588. return this.container;
  589. },
  590. refresh: function(mustClearSelections) {
  591. updateSelectionStates(this);
  592. if (!mustClearSelections) {
  593. saveSelections(this, 1);
  594. saveSelections(this, 2);
  595. } else {
  596. clearSelections(this);
  597. }
  598. refreshSelects(this);
  599. },
  600. destroy: function() {
  601. this.container.remove();
  602. this.element.show();
  603. $.data(this, 'plugin_' + pluginName, null);
  604. return this.element;
  605. }
  606. };
  607. // A really lightweight plugin wrapper around the constructor,
  608. // preventing against multiple instantiations
  609. $.fn[ pluginName ] = function (options) {
  610. var args = arguments;
  611. // Is the first parameter an object (options), or was omitted, instantiate a new instance of the plugin.
  612. if (options === undefined || typeof options === 'object') {
  613. return this.each(function () {
  614. // If this is not a select
  615. if (!$(this).is('select')) {
  616. $(this).find('select').each(function(index, item) {
  617. // For each nested select, instantiate the Dual List Box
  618. $(item).bootstrapDualListbox(options);
  619. });
  620. } else if (!$.data(this, 'plugin_' + pluginName)) {
  621. // Only allow the plugin to be instantiated once so we check that the element has no plugin instantiation yet
  622. // if it has no instance, create a new one, pass options to our plugin constructor,
  623. // and store the plugin instance in the elements jQuery data object.
  624. $.data(this, 'plugin_' + pluginName, new BootstrapDualListbox(this, options));
  625. }
  626. });
  627. // If the first parameter is a string and it doesn't start with an underscore or "contains" the `init`-function,
  628. // treat this as a call to a public method.
  629. } else if (typeof options === 'string' && options[0] !== '_' && options !== 'init') {
  630. // Cache the method call to make it possible to return a value
  631. var returns;
  632. this.each(function () {
  633. var instance = $.data(this, 'plugin_' + pluginName);
  634. // Tests that there's already a plugin-instance and checks that the requested public method exists
  635. if (instance instanceof BootstrapDualListbox && typeof instance[options] === 'function') {
  636. // Call the method of our plugin instance, and pass it the supplied arguments.
  637. returns = instance[options].apply(instance, Array.prototype.slice.call(args, 1));
  638. }
  639. });
  640. // If the earlier cached method gives a value back return the value,
  641. // otherwise return this to preserve chainability.
  642. return returns !== undefined ? returns : this;
  643. }
  644. };
  645. })(jQuery, window, document);