/* * selectList jQuery plugin * version 0.4.2 * * Copyright (c) 2009-2011 Michal Wojciechowski (odyniec.net) * * Dual licensed under the MIT (MIT-LICENSE.txt) * and GPL (GPL-LICENSE.txt) licenses. * * http://odyniec.net/projects/selectlist/ * */ (function ($) { $.selectList = function (select, options) { var $selectSingle, $list, $item, $newItem, $option, keyEvent, ready, first = 0, change, click, keypress, enter; function show($item, callback) { if (options.addAnimate && ready) if (typeof options.addAnimate == 'function') options.addAnimate($item.hide()[0], callback); else $item.hide().fadeIn(300, callback); else { $item.show(); if (callback) callback.call($item[0]); } } function hide($item, callback) { if (options.removeAnimate && ready) if (typeof options.removeAnimate == 'function') options.removeAnimate($item[0], callback); else $item.fadeOut(300, callback); else { $item.hide(); if (callback) callback.call($item[0]); } } function cmp(item1, item2) { return typeof options.sort == 'function' ? options.sort(item1, item2) : ($(item1).data('text') > $(item2).data('text')) == (options.sort != 'desc'); } function add(value, text, callHandler) { if ($(value).is('option')) { $option = $(value); if ($option[0].index < first) return; value = $option.val(); text = $option.text(); } else { $option = $selectSingle.find("option[value=\"" + value.replace("'", "\\\"") + "\"]"); if ($option.length) $option = $option.filter(function () { return !text || $(this).text() == text; }) .add($option).eq(0); else $option = null; } if (text === undefined) text = $option ? $option.text() : value; if ($option && !options.duplicates) $option.attr('disabled', 'disabled') .data('disabled', 1); $newItem = $(options.template.replace(/%text%/g, $('').text(text).html()).replace(/%value%/g, value)).hide(); $newItem.data('value', value).data('text', text).data('option', $option) .addClass(options.classPrefix + '-item'); $newItem.click(function () { if (options.clickRemove) remove($(this)); }); if (first && !keypress) $selectSingle[0].selectedIndex = 0; var callback = function () { if (callHandler !== false) options.onAdd(select, value, text); }; if (options.sort && ($item = $list.children().eq(0)).length) { while ($item.length && cmp($newItem[0], $item[0])) $item = $item.next(); show($item.length ? $newItem.insertBefore($item) : $newItem.appendTo($list), callback); } else show($newItem.appendTo($list), callback); $(select).empty(); $list.children().each(function () { $(select).append($("").attr({ value: $(this).data('value'), selected: "selected" })); }); checkValidation(); } function remove($item, callHandler) { hide($item, function () { var value = $(this).data('value'), text = $(this).data('text'); if ($(this).data('option')) $(this).data('option').removeAttr('disabled') .removeData('disabled'); $(this).remove(); $(select).find("option[value=\"" + value + "\"]").remove(); checkValidation(); if (callHandler !== false) options.onRemove(select, value, text); }); } function checkValidation() { if (select.form && typeof ($(select.form).validate) == "function" && $(select).add($selectSingle).hasClass($(select.form) .validate().settings.errorClass)) $(select.form).validate().element(select); } this.val = function () { return $(select).val(); }; this.add = function (value, text) { add(value, text); }; this.remove = function (value) { $list.children().each(function () { if ($(this).data('value') == value || typeof value == 'undefined') remove($(this)); }); }; this.setOptions = function (newOptions) { var sort = newOptions.sort && newOptions.sort != options.sort; options = $.extend(options, newOptions); if (sort) { var items = []; $list.children().each(function () { items[items.length] = $(this).data('value') items[items.length] = $(this).data('text'); }); $list.empty(); for (var i = 0; i < items.length; i += 2) add(items[i], items[i+1], false); } }; this.setOptions(options = $.extend({ addAnimate: true, classPrefix: 'selectlist', clickRemove: true, removeAnimate: true, template: '