Bootstrap 中的 Typeahead 組件就是一般所說的自動完成 AutoComplete,功能很強大,可是,使用上並不太方便。這裏咱們將介紹一下這個組件的使用。css
首先,最簡單的使用方式,就是直接在標記中聲明,經過 data-provide="typeahead" 來聲明這是一個 typeahead 組件,經過 data-source= 來提供數據。固然了,你還必須提供 bootstrap-typeahead.js 腳本。html
<html> <head> <link href="bootstrap.min.css" rel="stylesheet" type="text/css" /> </head> <body> <div style="margin: 50px 50px"> <label for="product_search">Product Search: </label> <input id="product_search" type="text" data-provide="typeahead" data-source='["Deluxe Bicycle", "Super Deluxe Trampoline", "Super Duper Scooter"]'> </div> <script src="js/jquery-1.8.3.min.js"></script> <script src="js/bootstrap-typeahead.js"></script> </body> </html>
一般,咱們使用腳原本填充數據,那麼,頁面能夠變成以下的形式。jquery
<html> <head> <link href="bootstrap.min.css" rel="stylesheet" type="text/css" /> </head> <body> <div style="margin: 50px 50px"> <label for="product_search">Product Search: </label> <input id="product_search" type="text" data-provide="typeahead"> </div> <script src="js/jquery-1.8.3.min.js"></script> <script src="js/bootstrap-typeahead.js"></script> <script> $(document).ready(function($) { // Workaround for bug in mouse item selection $.fn.typeahead.Constructor.prototype.blur = function() { var that = this; setTimeout(function () { that.hide() }, 250); }; $('#product_search').typeahead({ source: function(query, process) { return ["Deluxe Bicycle", "Super Deluxe Trampoline", "Super Duper Scooter"]; } }); }) </script> </body> </html>
注意,咱們提供了一個 source 函數來提供數據,這個函數接收兩個參數,第一個參數 query 表示用戶的輸入,第二個參數是 process 函數,這個 process 函數是 typeahead 提供的,用來處理咱們的數據。bootstrap
若是你但願經過 Ajax 調用從服務器端獲取匹配的數據,那麼,在異步完成的處理函數中,你須要獲取一個匹配的字符串數組,而後,將這個數組做爲參數,調用 process 函數。數組
說了半天,數據都是從本地獲取的,到底如何從服務器端獲取數據呢?服務器
其實很簡單,在 source 函數中,本身調用 Ajax 方法來獲取數據,主要注意的是,在獲取數據以後,調用 typeahead 的 process 函數處理便可。dom
$('#product_search').typeahead({ source: function (query, process) { var parameter = {query: query}; $.post('@Url.Action("AjaxService")', parameter, function (data) { process(data); }); } });
固然了,在服務器上,你須要建立一個服務來提供數據,這裏,咱們演示使用隨機數來生成一組隨機數據的方法。異步
public ActionResult AjaxService(string query) { System.Collections.ArrayList list = new System.Collections.ArrayList(); System.Random random = new Random(); for (int i = 0; i < 20; i++) { string item = string.Format("{0}{1}", query, random.Next(10000)); list.Add(item); } return this.Json(list); }
除了使用 source 函數以外,還可使用 highlighter 函數來特別處理匹配項目的顯示,使用 updater 函數,在選擇了某個匹配項以後,作出一些後繼的處理。ide
默認的 highlighter 是這樣實現的,item 是匹配的項目,找到匹配的部分以後,使用 <strong> 加粗了。函數
highlighter: function (item) { var query = this.query.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, '\\$&') return item.replace(new RegExp('(' + query + ')', 'ig'), function ($1, match) { return '<strong>' + match + '</strong>' }) }
而 updater 的默認實現就更加簡單了。
updater: function (item) {
return item
}
咱們能夠重寫這兩個函數,來實現自定義的處理。
<html> <head> <link href="bootstrap.min.css" rel="stylesheet" type="text/css" /> </head> <body> <div style="margin: 50px 50px"> <label for="product_search">Product Search: </label> <input id="product_search" type="text" data-provide="typeahead"> </div> <script src="js/jquery-1.8.3.min.js"></script> <script src="js/bootstrap-typeahead.js"></script> <script> $(document).ready(function($) { // Workaround for bug in mouse item selection $.fn.typeahead.Constructor.prototype.blur = function() { var that = this; setTimeout(function () { that.hide() }, 250); }; $('#product_search').typeahead({ source: function(query, process) { return ["Deluxe Bicycle", "Super Deluxe Trampoline", "Super Duper Scooter"]; }, highlighter: function(item) { return "==>" + item + "<=="; }, updater: function(item) { console.log("'" + item + "' selected."); return item; } }); }) </script> </body> </html>
實際上,你的數據多是一組對象而不是一個字符串數組,下面的例子中,咱們使用一個產品對象的數組來講明,每一個產品對象有一個 id 編號,還有名稱 name 和價格 price .
<html> <head> <link href="~/Content/dist/css/bootstrap.min.css" rel="stylesheet" /> </head> <body> <div style="margin: 50px 50px"> <label for="product_search">Product Search: </label> <input id="product_search" type="text" data-provide="typeahead"> </div> <script src="~/Content/dist/js/jquery.js"></script> <script src="~/Content/dist/js/bootstrap-typeahead.js"></script> <script src="~/Content/dist/js/underscore-min.js"></script> <script> $(document).ready(function ($) { // Workaround for bug in mouse item selection $.fn.typeahead.Constructor.prototype.blur = function () { var that = this; setTimeout(function () { that.hide() }, 250); }; var products = [ { id: 0, name: "Deluxe Bicycle", price: 499.98 }, { id: 1, name: "Super Deluxe Trampoline", price: 134.99 }, { id: 2, name: "Super Duper Scooter", price: 49.95 } ]; $('#product_search').typeahead({ source: function (query, process) { var results = _.map(products, function (product) { return product.name; }); process(results); }, highlighter: function (item) { return "==>" + item + "<=="; }, updater: function (item) { console.log("'" + item + "' selected."); return item; } }); }) </script> </body> </html>
咱們但願可以在提示中顯示產品的更加詳細的信息。
首先,修改咱們的 source 函數,原來這個函數返回一個字符串的數組,如今咱們返回一個產品 id 的數組,可是,process 函數指望獲得一個字符串數組的參數,因此,咱們將每一個 id 都轉換爲字符串類型。
而後,typeahead 組件就會調用 matcher 函數來檢查用戶的輸入是否與某個項目匹配,你可使用產品的 id 在產品列表中獲取產品對象,而後檢查產品的名稱與用戶的輸入是否匹配。
默認的 matcher 直接使用用戶的輸入來匹配,咱們若是使用 id 的話,顯然不能匹配,咱們須要重寫 matcher 函數。
matcher 接收一個當前項目的字符串,用戶當前的輸入爲 this.query,匹配返回 true, 不然返回 false. 默認的 matcher 以下:
, matcher: function (item) { return ~item.toLowerCase().indexOf(this.query.toLowerCase()) }
將它重寫爲永遠匹配,直接返回 true。而在 highlighter 中將顯示結果替換爲但願的產品名稱和價格組合。在下一步的 highlighter 中,咱們使用 Underscore 組件中的 find 方法,經過產品的 id 在產品列表中獲取產品對象,而後,顯示產品名稱和價格的組合。
highlighter: function (id) { var product = _.find(products, function (p) { return p.id == id; }); return product.name + " ($" + product.price + ")"; }
默認的 updater 直接返回當前匹配的內容,咱們這裏是一個 id, 須要重寫。
updater: function (item) { return item }
在用戶選擇以後,typeahead 將會調用 updater 函數,咱們經過產品的 id 在產品列表中獲取產品對象,而後
最後,updater 函數返回一個產品名稱的字符串,爲輸入框提供內容。setSelectedProduct 是咱們的一個自定義函數。
updater: function (id) { var product = _.find(products, function (p) { return p.id == id; }); that.setSelectedProduct(product); return product.name; }
下面是所有的代碼。
<html> <head> <link href="~/Content/dist/css/bootstrap.min.css" rel="stylesheet" /> </head> <body> <div style="margin: 50px 50px"> <label for="product_search">Product Search: </label> <input id="product_search" type="text" data-provide="typeahead"> <div id="product" style="border-width: 1; padding: 5px; border-style: solid"></div> </div> <script src="~/Content/dist/js/jquery.js"></script> <script src="~/Content/dist/js/bootstrap-typeahead.js"></script> <script src="~/Content/dist/js/underscore-min.js"></script> <script> $(document).ready(function ($) { // Workaround for bug in mouse item selection $.fn.typeahead.Constructor.prototype.blur = function () { var that = this; setTimeout(function () { that.hide() }, 250); }; var products = [ { id: 0, name: "Deluxe Bicycle", price: 499.98 }, { id: 1, name: "Super Deluxe Trampoline", price: 134.99 }, { id: 2, name: "Super Duper Scooter", price: 49.95 } ]; var that = this; $('#product_search').typeahead({ source: function (query, process) { $('#product').hide(); var results = _.map(products, function (product) { return product.id + ""; }); process(results); }, matcher: function (item) { return true; }, highlighter: function (id) { var product = _.find(products, function (p) { return p.id == id; }); return product.name + " ($" + product.price + ")"; }, updater: function (id) { var product = _.find(products, function (p) { return p.id == id; }); that.setSelectedProduct(product); return product.name; } }); $('#product').hide(); this.setSelectedProduct = function (product) { $('#product').html("Purchase: <strong>" + product.name + " ($" + product.price + ")</strong>").show(); } }) </script> </body> </html>