// Author: David Qin // E-mail: david@hereapp.cn // Date: 2014-11-05 (function ($) { // a case insensitive jQuery :contains selector $.expr[":"].searchableSelectContains = $.expr.createPseudo(function (arg) { return function (elem) { if (arg) return $(elem).text().toUpperCase().indexOf(arg.toUpperCase()) >= 0; else $(".searchable-select-items>div").removeClass("searchable-select-hide"); }; }); $.searchableSelect = function (element, options) { this.element = element; this.options = options || {}; this.init(); var _this = this; this.searchableElement.click(function (event) { // event.stopPropagation(); _this.show(); }).on('keydown', function (event) { if (event.which === 13 || event.which === 40 || event.which == 38) { event.preventDefault(); _this.show(); } }); $(document).on('click', null, function (event) { if (_this.searchableElement.has($(event.target)).length === 0) _this.hide(); }); this.input.on('keydown', function (event) { event.stopPropagation(); if (event.which === 13) { //enter event.preventDefault(); _this.selectCurrentHoverItem(); //回车回调 if (_this.options.enterCallback) _this.options.enterCallback(_this.input); _this.hide(); } else if (event.which == 27) { //ese _this.hide(); } else if (event.which == 40) { //down _this.hoverNextItem(); } else if (event.which == 38) { //up _this.hoverPreviousItem(); } }).on('keyup', function (event) { if (event.which != 13 && event.which != 27 && event.which != 38 && event.which != 40) _this.filter(); //监听搜索输入框回调 if (_this.options.inputKeyUpCallback) _this.options.inputKeyUpCallback($(this)); }) } var $sS = $.searchableSelect; $sS.fn = $sS.prototype = { version: '0.0.1' }; $sS.fn.extend = $sS.extend = $.extend; $sS.fn.extend({ init: function () { var _this = this; this.element.hide(); this.searchableElement = $('
'); // this.holder = $('
');//旧的 this.holder = $(''); this.dropdown = $('
'); this.input = $(''); this.items = $('
'); this.caret = $(''); this.scrollPart = $('
'); this.hasPrivious = $('
...
'); this.hasNext = $('
...
'); this.hasNext.on('mouseenter', function () { _this.hasNextTimer = null; var f = function () { var scrollTop = _this.items.scrollTop(); _this.items.scrollTop(scrollTop + 20); _this.hasNextTimer = setTimeout(f, 50); } f(); }).on('mouseleave', function (event) { clearTimeout(_this.hasNextTimer); }); this.hasPrivious.on('mouseenter', function () { _this.hasPriviousTimer = null; var f = function () { var scrollTop = _this.items.scrollTop(); _this.items.scrollTop(scrollTop - 20); _this.hasPriviousTimer = setTimeout(f, 50); } f(); }).on('mouseleave', function (event) { clearTimeout(_this.hasPriviousTimer); }); this.dropdown.append(this.input); this.dropdown.append(this.scrollPart); this.scrollPart.append(this.hasPrivious); this.scrollPart.append(this.items); this.scrollPart.append(this.hasNext); this.searchableElement.append(this.caret); this.searchableElement.append(this.holder); this.searchableElement.append(this.dropdown); this.element.after(this.searchableElement); this.buildItems(); this.setPriviousAndNextVisibility(); }, filter: function () { var text = this.input.val(); this.items.find('.searchable-select-item').addClass('searchable-select-hide'); this.items.find('.searchable-select-item:searchableSelectContains(' + text + ')').removeClass('searchable-select-hide'); if (this.currentSelectedItem && this.currentSelectedItem.hasClass('searchable-select-hide') && this.items.find('.searchable-select-item:not(.searchable-select-hide)').length > 0) { this.hoverFirstNotHideItem(); } this.setPriviousAndNextVisibility(); }, hoverFirstNotHideItem: function () { this.hoverItem(this.items.find('.searchable-select-item:not(.searchable-select-hide)').first()); }, selectCurrentHoverItem: function () { if (this.currentHoverItem && !this.currentHoverItem.hasClass('searchable-select-hide')) this.selectItem(this.currentHoverItem); }, hoverPreviousItem: function () { if (!this.hasCurrentHoverItem()) this.hoverFirstNotHideItem(); else { var prevItem = this.currentHoverItem.prevAll('.searchable-select-item:not(.searchable-select-hide):first') if (prevItem.length > 0) this.hoverItem(prevItem); } }, hoverNextItem: function () { if (!this.hasCurrentHoverItem()) this.hoverFirstNotHideItem(); else { var nextItem = this.currentHoverItem.nextAll('.searchable-select-item:not(.searchable-select-hide):first') if (nextItem.length > 0) this.hoverItem(nextItem); } }, buildItems: function () { var _this = this; this.element.find('option').each(function () { if ($(this).text().length == 0) return; var item = $('
' + $(this).text() + '
'); if (this.selected) { _this.selectItem(item); _this.hoverItem(item); } item.on('mouseenter', function () { $(this).addClass('hover'); }).on('mouseleave', function () { $(this).removeClass('hover'); }).click(function (event) { event.stopPropagation(); _this.selectItem($(this)); _this.hide(); //选择option后执行回调 if (_this.options.optionCallback) { var value = $(this).attr("data-value"); var text = $(this).text(); _this.options.optionCallback(value, text); } }); _this.items.append(item); }); this.items.on('scroll', function () { _this.setPriviousAndNextVisibility(); }) }, show: function () { this.dropdown.removeClass('searchable-select-hide'); this.input.focus(); this.status = 'show'; this.caret.addClass("selected");//下三角 this.setPriviousAndNextVisibility(); }, hide: function () { if (!(this.status === 'show')) return; if (this.items.find(':not(.searchable-select-hide)').length === 0) this.input.val(''); this.dropdown.addClass('searchable-select-hide'); this.searchableElement.trigger('focus'); this.status = 'hide'; this.caret.removeClass("selected");//下三角 }, hasCurrentSelectedItem: function () { return this.currentSelectedItem && this.currentSelectedItem.length > 0; }, selectItem: function (item) { if (this.hasCurrentSelectedItem()) this.currentSelectedItem.removeClass('selected'); this.currentSelectedItem = item; item.addClass('selected'); this.hoverItem(item); this.holder.val(item.text()); var value = item.data('value'); this.holder.data('value', value); this.element.val(value); if (this.options.afterSelectItem) { this.options.afterSelectItem.apply(this); } }, hasCurrentHoverItem: function () { return this.currentHoverItem && this.currentHoverItem.length > 0; }, hoverItem: function (item) { if (this.hasCurrentHoverItem()) this.currentHoverItem.removeClass('hover'); if (item.outerHeight() + item.position().top > this.items.height()) this.items.scrollTop(this.items.scrollTop() + item.outerHeight() + item.position().top - this.items.height()); else if (item.position().top < 0) this.items.scrollTop(this.items.scrollTop() + item.position().top); this.currentHoverItem = item; item.addClass('hover'); }, setPriviousAndNextVisibility: function () { if (this.items.scrollTop() === 0) { this.hasPrivious.addClass('searchable-select-hide'); this.scrollPart.removeClass('has-privious'); } else { this.hasPrivious.removeClass('searchable-select-hide'); this.scrollPart.addClass('has-privious'); } if (this.items.scrollTop() + this.items.innerHeight() >= this.items[0].scrollHeight) { this.hasNext.addClass('searchable-select-hide'); this.scrollPart.removeClass('has-next'); } else { this.hasNext.removeClass('searchable-select-hide'); this.scrollPart.addClass('has-next'); } } }); $.fn.searchableSelect = function (options) { var sS; this.each(function () { sS = new $sS($(this), options); }); return sS;//返回当前对象,那边接收到后可以进行后期的修改对象操作 //return this;//以前的 }; })(jQuery);