!function ($) { "use strict"; function ninjaSelect(element, options) { this.$element = $(element); this.options = $.extend({}, $.fn.ninjaSelect.defaults, options); this.page = 1; this.init(); } ninjaSelect.prototype = { constructor: ninjaSelect, init: function() { var self = this, allow = true; self.$div = $('
', {'id': 'ninja_' + this.$element.attr('id'), 'class': 'ninjaSelect'}), self.$input = $(''), self.$list = $('
', {'class': 'ninjaSelect_wrapper'}).hide(); self.$selected = $('
', {'class': 'ninjaSelect_selected'}); self.$ul = $('
    ', {'class': 'ninjaSelect_list'}); self.$element.hide().after( self.$div.append( self.$input, self.$selected, self.$list.append( self.$ul ) ) ); self.$input.on('keyup', function(e) { self.loadData($(this).val()); }); self.$ul.delegate('li', 'click', function(e) { var id = $(this).data().id, allow = true; self.$selected.show().find('.ninjaSelect_item').each(function() { if ($(this).data().id == id) { allow = false; } }); if (!self.options.multiple && $('.ninjaSelect_item').length == 1) { allow = false; } if (allow) { $(this).addClass('active'); self.$selected.append( $('
    ', {'class': 'ninjaSelect_item'}).data({'id': id, 'index': $(this).index()}).text($(this).text()).click(function() { self.$ul.find('li').eq($(this).data().index).removeClass('active'); $(this).next().remove().end().remove(); if (!self.$selected.find('.ninjaSelect_item').length) { self.$selected.hide() } }), $('', {'type': 'hidden', 'name': $(this).text() + '_' + id}).val($(this).text()) ) } }); self.$list.mousewheel(function(e, delta) { if (delta < 0) { if ($(this).scrollTop() + $(this).innerHeight() >= self.$ul.innerHeight() && allow) { allow = false; self.loadData(self.$input.val(), function() { allow = true; }) } } }); $(document).delegate('body', 'click', function(e) { if ($(e.target).closest('.ninjaSelect_list').length == 0) { self.$list.hide(); self.$ul.empty(); } }) }, loadData: function(val, callback) { var self = this, len = val.length; if (len >= self.options.minLength) { $.get(self.options.url, {offset: self.page, count: self.options.itemsPerPage, value: val, data: self.options.data}, function(json) { if (json.length) { if (json.length >= self.options.itemsPerPage) { self.page++; } self.$list.show(); json.forEach(function(item, i, arr) { self.$ul.append( $('
  • ').text(item.text).data('id', item.id) ) }) if (self.page == 1) { self.$list.animate({scrollTop: 0}, 0); } else { self.$list.css({scrollTop: self.$list.scrollTop()}, 0); } if (callback) { callback(); } } else { self.$list.hide(); self.$ul.empty(); } }, 'json'); } else { self.$list.hide(); self.$ul.empty(); } } } $.fn.ninjaSelect = function(options) { return this.each(function() { var $this = $(this), data = $this.data('ninjaSelect'); if (!data) { $this.data('ninjaSelect', (data = new ninjaSelect(this, options))) } }) } $.fn.ninjaSelect.defaults = { url: '/ajax.php', data: {}, minLength: 2, itemsPerPage: 3, multiple: true } }(jQuery);