$().typeahead({ ajax: { url: , //timeout: 300, method: , triggerLength: 1, loadingClass: null, preProcess: function (result) { return result; } }, display: , val: , items: 10, itemSelected: function (item, val, text) { $().val(val); } });
这种 typeahead自动补全不是bootstrap常用的typeahead.js。 以下是typeahead.js代码(如果有bootstrap3-typeahead.js更好)
// ---------------------------------------------------------------------------- // // bootstrap-typeahead.js // // Twitter Bootstrap Typeahead Plugin // v1.2.2 Author // ---------- // Terry Rosen // tcrosen@gmail.com | @rerrify | github.com/tcrosen/ Description // ---------- // Custom implementation of Twitter's Bootstrap Typeahead Plugin // #typeahead Requirements // ---------- // jQuery 1.7+ // Twitter Bootstrap 2.0+ ! function ($) { ; //------------------------------------------------------------------ // // Constructor // var Typeahead = function (element, options) { this.$element = $(element); this.options = $.extend(true, {}, $.fn.typeahead.defaults, options); ); this.shown = false; .eventSupported = this.options.eventSupported || this.eventSupported; this.grepper = this.options.grepper || this.grepper; this.highlighter = this.options.highlighter || this.highlighter; this.lookup = this.options.lookup || this.lookup; this.matcher = this.options.matcher || this.matcher; this.render = this.options.render || this.render; this.select = this.options.select || this.select; this.sorter = this.options.sorter || this.sorter; this.source = this.options.source || this.source; if (!this.source.length) { var ajax = this.options.ajax; ) { this.ajax = $.extend({}, $.fn.typeahead.defaults.ajax, { url: ajax }); } else { this.ajax = $.extend({}, $.fn.typeahead.defaults.ajax, ajax); } if (!this.ajax.url) { this.ajax = null; } } this.listen(); } Typeahead.prototype = { constructor: Typeahead, //============================================================================================================= // // Utils // //============================================================================================================= //------------------------------------------------------------------ // // Check if an event is supported by the browser eg. 'keypress' // * This was included to handle the "exhaustive deprecation" of jQuery.browser in jQuery 1.8 // eventSupported: function (eventName) { var isSupported = (eventName in this.$element); if (!isSupported) { ); isSupported = ; } return isSupported; }, //============================================================================================================= // // AJAX // //============================================================================================================= //------------------------------------------------------------------ // // Handle AJAX source // ajaxer: function () { var that = this, query = that.$element.val(); if (query === that.query) { return that; } // Query changed that.query = query; (that.ajax.timerId) { clearTimeout(that.ajax.timerId); that.ajax.timerId = null; } if (!query || query.length < that.ajax.triggerLength) { (that.ajax.xhr) { that.ajax.xhr.abort(); that.ajax.xhr = null; that.ajaxToggleLoadClass(false); } return that.shown ? that.hide() : that; } // Query is good to send, set a timer that.ajax.timerId = setTimeout(function () { $.proxy(that.ajaxExecute(query), that) }, that.ajax.timeout); return that; }, //------------------------------------------------------------------ // // Execute an AJAX request // ajaxExecute: function (query) { this.ajaxToggleLoadClass(true); (this.ajax.xhr) this.ajax.xhr.abort(); var params = this.ajax.preDispatch ? this.ajax.preDispatch(query) : { query: query }; ) ? $.post : $.get; this.ajax.xhr = jAjax(this.ajax.url, params, $.proxy(this.ajaxLookup, this)); this.ajax.timerId = null; }, //------------------------------------------------------------------ // // Perform a lookup in the AJAX results // ajaxLookup: function (data) { var items; this.ajaxToggleLoadClass(false); if (!this.ajax.xhr) return; if (this.ajax.preProcess) { data = this.ajax.preProcess(data); } .ajax.data = data; items = this.grepper(this.ajax.data); if (!items || !items.length) { return this.shown ? this.hide() : this; } this.ajax.xhr = null; return this.render(items.slice(0, this.options.items)).show(); }, //------------------------------------------------------------------ // // Toggle the loading class // ajaxToggleLoadClass: function (enable) { if (!this.ajax.loadingClass) return; this.$element.toggleClass(this.ajax.loadingClass, enable); }, //============================================================================================================= // // Data manipulation // //============================================================================================================= //------------------------------------------------------------------ // // Search source // lookup: function (event) { var that = this, items; if (that.ajax) { that.ajaxer(); } else { that.query = that.$element.val(); if (!that.query) { return that.shown ? that.hide() : that; } items = that.grepper(that.source); if (!items || !items.length) { return that.shown ? that.hide() : that; } return that.render(items.slice(0, that.options.items)).show(); } }, //------------------------------------------------------------------ // // Filters relevent results // grepper: function (data) { var that = this, items; if (data && data.length && !data[0].hasOwnProperty(that.options.display)) { return null; } items = $.grep(data, function (item) { return that.matcher(item[that.options.display], item); }); return this.sorter(items); }, //------------------------------------------------------------------ // // Looks for a match in the source // matcher: function (item) { return ~item.toLowerCase().indexOf(this.query.toLowerCase()); }, //------------------------------------------------------------------ // // Sorts the results // sorter: function (items) { var that = this, beginswith = [], caseSensitive = [], caseInsensitive = [], item; while (item = items.shift()) { if (!item[that.options.display].toLowerCase().indexOf(this.query.toLowerCase())) { beginswith.push(item); } else if (~item[that.options.display].indexOf(this.query)) { caseSensitive.push(item); } else { caseInsensitive.push(item); } } return beginswith.concat(caseSensitive, caseInsensitive); }, //============================================================================================================= // // DOM manipulation // //============================================================================================================= //------------------------------------------------------------------ // // Shows the results list // show: function () { var pos = $.extend({}, this.$element.offset(), { height: this.$element[0].offsetHeight }); this.$menu.css({ top: pos.top + pos.height, left: pos.left }); this.$menu.show(); this.shown = true; return this; }, //------------------------------------------------------------------ // // Hides the results list // hide: function () { this.$menu.hide(); this.shown = false; return this; }, //------------------------------------------------------------------ // // Highlights the match(es) within the results // highlighter: function (item) { ); + query + , ), function ($1, match) { + match + ; }); }, //------------------------------------------------------------------ // // Renders the results list // render: function (items) { var that = this; items = $(items).map(function (i, item) { i = $(that.options.item).attr(, item[that.options.val]); i.find().html(that.highlighter(item[that.options.display], item)); return i[0]; }); items.first().addClass(); this.$menu.html(items); return this; }, //------------------------------------------------------------------ // // Item is selected // select: function () { ); this.$element.val($selectedItem.text()).change(); ), $selectedItem.text()); return this.hide(); }, //------------------------------------------------------------------ // // Selects the next result // next: function (event) { ).removeClass(); var next = active.next(); if (!next.length) { next = $()[0]); } next.addClass(); }, //------------------------------------------------------------------ // // Selects the previous result // prev: function (event) { ).removeClass(); var prev = active.prev(); if (!prev.length) { prev = ).last(); } prev.addClass(); }, //============================================================================================================= // // Events // //============================================================================================================= //------------------------------------------------------------------ // // Listens for user events // listen: function () { , $.proxy(this.blur, this)) .on(, $.proxy(this.keyup, this)); )) { , $.proxy(this.keypress, this)); } else { , $.proxy(this.keypress, this)); } , $.proxy(this.click, this)) .on(, , $.proxy(this.mouseenter, this)); }, //------------------------------------------------------------------ // // Handles a key being raised up // keyup: function (e) { e.stopPropagation(); e.preventDefault(); switch (e.keyCode) { case 40: : ; case 9: : (!this.shown) { return; } this.select(); break; case 27: .hide(); break; default: this.lookup(); } }, //------------------------------------------------------------------ // // Handles a key being pressed // keypress: function (e) { e.stopPropagation(); if (!this.shown) { return; } switch (e.keyCode) { case 9: : : // escape e.preventDefault(); break; case 38: // up arrow e.preventDefault(); this.prev(); break; case 40: // down arrow e.preventDefault(); this.next(); break; } }, //------------------------------------------------------------------ // // Handles cursor exiting the textbox // blur: function (e) { var that = this; e.stopPropagation(); e.preventDefault(); setTimeout(function () { )) { that.hide(); } }, 150) }, //------------------------------------------------------------------ // // Handles clicking on the results list // click: function (e) { e.stopPropagation(); e.preventDefault(); this.select(); }, //------------------------------------------------------------------ // // Handles the mouse entering the results list // mouseenter: function (e) { ).removeClass(); $(e.currentTarget).addClass(); } } //------------------------------------------------------------------ // // Plugin definition // $.fn.typeahead = function (option) { return this.each(function () { var $this = $(this), data = $), options = && option; if (!data) { $, (data = new Typeahead(this, options))); } ) { data[option](); } }); } //------------------------------------------------------------------ // // Defaults // $.fn.typeahead.defaults = { source: [], items: 8, menu: , item: , display: , val: , itemSelected: function () { }, ajax: { url: null, timeout: 300, method: , triggerLength: 3, loadingClass: null, displayField: null, preDispatch: null, preProcess: null } } $.fn.typeahead.Constructor = Typeahead; //------------------------------------------------------------------ // // DOM-ready call for the Data API (no-JS implementation) // // Note: As of Bootstrap v2.0 this feature may be disabled using $('body').off('.data-api') // $(function () { $().on(, , function (e) { var $this = $(this); )) { return; } e.preventDefault(); $this.typeahead($this.data()); }) }); }(window.jQuery);