BloggerAds

2011年8月29日 星期一

ASP.NET的WebService + autocomplete + tagit 合體

在使用Google+、Facebook時,會常常看到Tag這個東西,這東西在使用上,很方便,而且長的還蠻好看的,我很喜歡這操作很直覺的東西,所以上網找了些plugin,並拿來實作,而我找了 tagit 這個plugin,還算簡單使用(而且我認為這是我找的 plugin 當中最漂亮的...)。


一般的使用很簡單,照著 tagit 的 example就可以用了,但是一般的tag通常都會加上自動完成(AutoComplete)功能,所以不加個AutoComplete感覺就很弱,下面就提供個範例是用C#的WebService來實作AutoComplete功能(PHP很簡單,下面會提到一點):


1.在WebService部份,我們用DataTable來傳回傳,所以可以在asmx.cs這樣寫:
[WebMethod]
public DataTable GetList(string prefixText) {  
        DataTable dt = new DataTable();
        //從資料庫查詢資料的語法,請自發揮...     
        // ......略
        return dt;    //最後return一個DataTable
}
2.在aspx部份,用一個TextBox:
<asp:TextBox ID="txtTag"  runat="server" autocomplete="off"  />
3.再來就是JavaScript的實作了,通常是在document.ready時實作
$(document).ready(function() {
    $("#<% =txtTag.ClientID %>").tagit({
        allowSpaces: true,
        tagSource: function(request, response) {
            $.ajax({
                url: "/GetList.asmx/GetList", //步驟1的WebService網址及Function名稱
                data: { prefixText: request.term }, //要傳入WebService Function的變數,這裡是用來抓user所輸入的內容
                dataType: "xml",  //dataType設成Xml,php直接用json,再搭配json_encode來產生資料就可以了
                type: "POST",
                contentType: "application/x-www-form-urlencoded; charset=utf-8",    //這裡很重要,要把contentType改成WebService預設回傳的application/x-www-form-urlencoded
                dataFilter: function(data) { return data; },
                success: function(data) {    //成功抓到資料後,要執行的動作
                    response($.map($(data).find("[欄位名稱]"), function(item) {  //因為是XML所以用這個方式來取資料,[欄位名稱]請記得更改成DataTable的欄位名稱
                        return { value: $(item).text() }
                    }));
                },
                error: function(XMLHttpRequest, textStatus, errorThrown) {
                    alert(textStatus + ":" + errorThrown);  //Debug用
                }
            });
        }         
    });
4.AutoComplete的部份完成!


5.如果要再龜毛點,限制使用者必須輸入DataTable中的內容的話,就在JavaScript中先加入這一段:
$.expr[':'].textEquals = function(a, i, m) {
        return $(a).text().match("^" + m[3] + "$");
};
6.再來改一下document.ready中tagit的部份,加入onTagAdded 的事件。


7.最後還要為tagit所產生的text加入change事件。


6+7後的JavaScript如下:
$(document).ready(function() {
    $("#<%=txtTag.ClientID %>").tagit({
        allowSpaces: true,
        tagSource: function(request, response) {
            $.ajax({
                url: "/GetList.asmx/GetList",
                data: { prefixText: request.term },
                dataType: "xml",
                type: "POST",
                contentType: "application/x-www-form-urlencoded; charset=utf-8",
                dataFilter: function(data) { return data; },
                success: function(data) {
                    response($.map($(data).find("[欄位名稱]"), function(item) {
                        return { value: $(item).text() }
                    }));
                },
                error: function(XMLHttpRequest, textStatus, errorThrown) {
                    alert(textStatus + ":" + errorThrown);
                }
            });
        },
        onTagAdded: function(event, tag) {  
            //注意!別在這alert東西,不然會執行兩次
            //.ui-autocomplete、tagit-label 是tagit執行後預設的class
            if ($(".ui-autocomplete li:textEquals('" + tag.find(".tagit-label").text() + "')").size() == 0) {
                that.removeTag(tag);    //若輸入的內容不在資料庫中,則移除tag
            }
        }
    });


    $(".tagit input").change(function() {
        if ($(".tagit li:textEquals('" + $(this).val() + "')").size() == 0) {
            $(this).val('');  //若輸入的內容不在資料庫中,則清空TextBox的內容
        }
    });
});
8. 再次大功告成


參考資料:
http://stackoverflow.com/questions/2587378/how-to-implement-mustmatch-and-selectfirst-in-jquery-ui-autocomplete
https://github.com/aehlke/tag-it
http://jqueryui.com/demos/autocomplete/

沒有留言:

張貼留言