jquery.selectlist.js 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. /*
  2. * selectList jQuery plugin
  3. * version 0.4.2
  4. *
  5. * Copyright (c) 2009-2011 Michal Wojciechowski (odyniec.net)
  6. *
  7. * Dual licensed under the MIT (MIT-LICENSE.txt)
  8. * and GPL (GPL-LICENSE.txt) licenses.
  9. *
  10. * http://odyniec.net/projects/selectlist/
  11. *
  12. */
  13. (function ($) {
  14. $.selectList = function (select, options) {
  15. var
  16. $selectSingle,
  17. $list,
  18. $item, $newItem,
  19. $option,
  20. keyEvent,
  21. ready,
  22. first = 0,
  23. change, click, keypress, enter;
  24. function show($item, callback) {
  25. if (options.addAnimate && ready)
  26. if (typeof options.addAnimate == 'function')
  27. options.addAnimate($item.hide()[0], callback);
  28. else
  29. $item.hide().fadeIn(300, callback);
  30. else {
  31. $item.show();
  32. if (callback)
  33. callback.call($item[0]);
  34. }
  35. }
  36. function hide($item, callback) {
  37. if (options.removeAnimate && ready)
  38. if (typeof options.removeAnimate == 'function')
  39. options.removeAnimate($item[0], callback);
  40. else
  41. $item.fadeOut(300, callback);
  42. else {
  43. $item.hide();
  44. if (callback)
  45. callback.call($item[0]);
  46. }
  47. }
  48. function cmp(item1, item2) {
  49. return typeof options.sort == 'function' ?
  50. options.sort(item1, item2)
  51. : ($(item1).data('text') > $(item2).data('text'))
  52. == (options.sort != 'desc');
  53. }
  54. function add(value, text, callHandler) {
  55. if ($(value).is('option')) {
  56. $option = $(value);
  57. if ($option[0].index < first)
  58. return;
  59. value = $option.val();
  60. text = $option.text();
  61. }
  62. else {
  63. $option = $selectSingle.find("option[value=\"" +
  64. value.replace("'", "\\\"") + "\"]");
  65. if ($option.length)
  66. $option = $option.filter(function () {
  67. return !text || $(this).text() == text;
  68. })
  69. .add($option).eq(0);
  70. else
  71. $option = null;
  72. }
  73. if (text === undefined)
  74. text = $option ? $option.text() : value;
  75. if ($option && !options.duplicates)
  76. $option.attr('disabled', 'disabled')
  77. .data('disabled', 1);
  78. $newItem = $(options.template.replace(/%text%/g,
  79. $('<b/>').text(text).html()).replace(/%value%/g, value)).hide();
  80. $newItem.data('value', value).data('text', text).data('option', $option)
  81. .addClass(options.classPrefix + '-item');
  82. $newItem.click(function () {
  83. if (options.clickRemove)
  84. remove($(this));
  85. });
  86. if (first && !keypress)
  87. $selectSingle[0].selectedIndex = 0;
  88. var callback = function () {
  89. if (callHandler !== false)
  90. options.onAdd(select, value, text);
  91. };
  92. if (options.sort && ($item = $list.children().eq(0)).length) {
  93. while ($item.length && cmp($newItem[0], $item[0]))
  94. $item = $item.next();
  95. show($item.length ? $newItem.insertBefore($item)
  96. : $newItem.appendTo($list), callback);
  97. }
  98. else
  99. show($newItem.appendTo($list), callback);
  100. $(select).empty();
  101. $list.children().each(function () {
  102. $(select).append($("<option/>").attr({ value: $(this).data('value'),
  103. selected: "selected" }));
  104. });
  105. checkValidation();
  106. }
  107. function remove($item, callHandler) {
  108. hide($item, function () {
  109. var value = $(this).data('value'),
  110. text = $(this).data('text');
  111. if ($(this).data('option'))
  112. $(this).data('option').removeAttr('disabled')
  113. .removeData('disabled');
  114. $(this).remove();
  115. $(select).find("option[value=\"" + value + "\"]").remove();
  116. checkValidation();
  117. if (callHandler !== false)
  118. options.onRemove(select, value, text);
  119. });
  120. }
  121. function checkValidation() {
  122. if (select.form && typeof ($(select.form).validate) == "function" &&
  123. $(select).add($selectSingle).hasClass($(select.form)
  124. .validate().settings.errorClass))
  125. $(select.form).validate().element(select);
  126. }
  127. this.val = function () {
  128. return $(select).val();
  129. };
  130. this.add = function (value, text) {
  131. add(value, text);
  132. };
  133. this.remove = function (value) {
  134. $list.children().each(function () {
  135. if ($(this).data('value') == value || typeof value == 'undefined')
  136. remove($(this));
  137. });
  138. };
  139. this.setOptions = function (newOptions) {
  140. var sort = newOptions.sort && newOptions.sort != options.sort;
  141. options = $.extend(options, newOptions);
  142. if (sort) {
  143. var items = [];
  144. $list.children().each(function () {
  145. items[items.length] = $(this).data('value')
  146. items[items.length] = $(this).data('text');
  147. });
  148. $list.empty();
  149. for (var i = 0; i < items.length; i += 2)
  150. add(items[i], items[i+1], false);
  151. }
  152. };
  153. this.setOptions(options = $.extend({
  154. addAnimate: true,
  155. classPrefix: 'selectlist',
  156. clickRemove: true,
  157. removeAnimate: true,
  158. template: '<li>%text%</li>',
  159. onAdd: function () {},
  160. onRemove: function () {}
  161. }, options));
  162. $selectSingle = $(select).clone();
  163. $selectSingle.removeAttr('id').removeAttr('name')
  164. .addClass(options.classPrefix + '-select').insertAfter($(select));
  165. $(select).empty().hide();
  166. ($list = $(options.list || $("<ul/>").insertAfter($selectSingle)))
  167. .addClass(options.classPrefix + '-list');
  168. $selectSingle.find(':selected').each(function () {
  169. add($(this), null, false);
  170. });
  171. $selectSingle.removeAttr('multiple');
  172. $selectSingle.get(0).removeAttribute('size');
  173. if ($selectSingle.attr("title")) {
  174. $selectSingle.prepend($("<option/>")
  175. .text($selectSingle.attr("title")));
  176. first = 1;
  177. $selectSingle[0].selectedIndex = 0;
  178. }
  179. keyEvent = $.browser.msie || $.browser.safari ? 'keydown' : 'keypress';
  180. $selectSingle.bind(keyEvent, function (event) {
  181. keypress = true;
  182. if ((event.keyCode || event.which) == 13) {
  183. enter = true;
  184. $selectSingle.change();
  185. keypress = true;
  186. return false;
  187. }
  188. })
  189. .change(function() {
  190. if (!keypress && !click) return;
  191. change = true;
  192. $option = $selectSingle.find("option:selected");
  193. if (!$option.data("disabled") && (!keypress || enter))
  194. add($option);
  195. if (keypress)
  196. keypress = change = click = false;
  197. enter = false;
  198. })
  199. .mousedown(function () {
  200. click = true;
  201. });
  202. $selectSingle.find('option').click(function (event) {
  203. if ($.browser.mozilla && event.pageX >= $selectSingle.offset().left &&
  204. event.pageX <= $selectSingle.offset().left +
  205. $selectSingle.outerWidth() &&
  206. event.pageY >= $selectSingle.offset().top &&
  207. event.pageY <= $selectSingle.offset().top +
  208. $selectSingle.outerHeight())
  209. return false;
  210. click = true;
  211. if (!($(this).attr('disabled') || $(this).data('disabled') || keypress
  212. || change))
  213. add($(this));
  214. if (!keypress)
  215. change = click = false;
  216. return false;
  217. });
  218. ready = true;
  219. };
  220. $.fn.selectList = function (options) {
  221. options = options || {};
  222. this.filter('select').each(function () {
  223. if ($(this).data('selectList'))
  224. $(this).data('selectList').setOptions(options);
  225. else
  226. $(this).data('selectList', new $.selectList(this, options));
  227. });
  228. if (options.instance)
  229. return this.filter('select').data('selectList');
  230. return this;
  231. };
  232. })(jQuery);