(function($){ $.fn.autoComplete = function(options){ var o = $.extend({}, $.fn.autoComplete.defaults, options); // public methods if (typeof options == 'string') { this.each(function(){ var that = $(this); if (options == 'destroy') { $(window).off('resize.autocomplete', that.updateSC); that.off('blur.autocomplete focus.autocomplete keydown.autocomplete keyup.autocomplete'); if (that.data('autocomplete')) that.attr('autocomplete', that.data('autocomplete')); else that.removeAttr('autocomplete'); $(that.data('sc')).remove(); that.removeData('sc').removeData('autocomplete'); } }); return this; } return this.each(function(){ var that = $(this); // sc = 'suggestions container' that.sc = $('
'); that.data('sc', that.sc).data('autocomplete', that.attr('autocomplete')); that.attr('autocomplete', 'off'); that.cache = {}; that.last_val = ''; that.updateSC = function(resize, next){ that.sc.css({ top: that.offset().top + that.outerHeight(), left: that.offset().left, width: that.outerWidth() }); if (!resize) { that.sc.show(); if (!that.sc.maxHeight) that.sc.maxHeight = parseInt(that.sc.css('max-height')); if (!that.sc.suggestionHeight) that.sc.suggestionHeight = $('.autocomplete-suggestion', that.sc).first().outerHeight(); if (that.sc.suggestionHeight) if (!next) that.sc.scrollTop(0); else { var scrTop = that.sc.scrollTop(), selTop = next.offset().top - that.sc.offset().top; if (selTop + that.sc.suggestionHeight - that.sc.maxHeight > 0) that.sc.scrollTop(selTop + that.sc.suggestionHeight + scrTop - that.sc.maxHeight); else if (selTop < 0) that.sc.scrollTop(selTop + scrTop); } } } $(window).on('resize.autocomplete', that.updateSC); that.sc.appendTo('body'); that.sc.on('mouseleave', '.autocomplete-suggestion', function (){ $('.autocomplete-suggestion.selected').removeClass('selected'); }); that.sc.on('mouseenter', '.autocomplete-suggestion', function (){ $('.autocomplete-suggestion.selected').removeClass('selected'); $(this).addClass('selected'); }); that.sc.on('mousedown', '.autocomplete-suggestion', function (e){ var item = $(this), v = item.data('val'); if (v || item.hasClass('autocomplete-suggestion')) { // else outside click that.val(v); o.onSelect(e, v, item); that.sc.hide(); } return false; }); that.on('blur.autocomplete', function(){ try { over_sb = $('.autocomplete-suggestions:hover').length; } catch(e){ over_sb = 0; } // IE7 fix :hover if (!over_sb) { that.last_val = that.val(); that.sc.hide(); setTimeout(function(){ that.sc.hide(); }, 350); // hide suggestions on fast input } else if (!that.is(':focus')) setTimeout(function(){ that.focus(); }, 20); }); if (!o.minChars) that.on('focus.autocomplete', function(){ that.last_val = '\n'; that.trigger('keyup.autocomplete'); }); function suggest(data){ var val = that.val(); that.cache[val] = data; if (data.length && val.length >= o.minChars) { var s = ''; for (var i=0;i= o.minChars) { if (val != that.last_val) { that.last_val = val; clearTimeout(that.timer); if (o.cache) { if (val in that.cache) { suggest(that.cache[val]); return; } // no requests if previous suggestions were empty for (var i=1; i' + item.replace(re, "$1") + ''; }, onSelect: function(e, term, item){} }; }(jQuery));