| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292 |
- // 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 = $('<div tabindex="0" class="searchable-select"></div>');
- // this.holder = $('<div class="searchable-select-holder"></div>');//旧的
- this.holder = $('<input type="text" readonly class="searchable-select-holder" placeholder="' + (_this.options.placeholder ? _this.options.placeholder : "") + '" />');
- this.dropdown = $('<div class="searchable-select-dropdown searchable-select-hide"></div>');
- this.input = $('<input type="text" class="searchable-select-input" />');
- this.items = $('<div class="searchable-select-items"></div>');
- this.caret = $('<i class="layui-edge searchable-select-caret"></i>');
-
- this.scrollPart = $('<div class="searchable-scroll"></div>');
- this.hasPrivious = $('<div class="searchable-has-privious">...</div>');
- this.hasNext = $('<div class="searchable-has-next">...</div>');
-
- 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 = $('<div class="searchable-select-item" data-value="' + $(this).attr('value') + '">' + $(this).text() + '</div>');
- 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);
|