使用 Bootstrap Typeahead 組件

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 函數。數組

第三,支持 Ajax 獲取數據

說了半天,數據都是從本地獲取的,到底如何從服務器端獲取數據呢?服務器

其實很簡單,在 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);
}

第四,使用 highlighter 和 updater

除了使用 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>

 參考資料

Twitter Boostrap Typeahead Tutorial

typeahead 下載地址

underscore 下載地址

相關文章
相關標籤/搜索