中年IT男的日常 – 整合jQuery UI AutoComplete Widget(自動完成小工具)使用Ajax取得伺服器資料

哥在2012年(馬英九以6,891,139票當選連任的那一年)分享了JQuery教學資源看到Auto-Complete Field with jQuery, JSON & PHP文章就讓人很興奮,那時是用PHP來做的,朋友們現在可以參考[鐵人賽Day30]使用PHP&MySQL配合jQuery UI Autocomplete實作自動完成功能,幾年之後開始用ASP.NET組件搭配C#語言來,並且用了公費花了一萬六千多去恆逸教育訓練中心上過《使用jQuery UI整合ASP.NET Web Form網站開發》,今天現學現賣就來分享一下整合jQuery UI AutoComplete Widget(自動完成小工具)使用Ajax取得伺服器資料這個部份,如果不想用jQuery UI,只想用 jQuery處理自動完成的功能,可以參考jQuery自動完成懶人包,如果你想獨力使用Javascript來做自動完成功能,那就可以考慮How to create an autocomplete input with plain Javascript

如果你對哥所說的Javascript完全搞不懂,那就先上上JavaScript 程式設計新手村課程,不懂什麼是jQuery UI,先看看jQuery UI使用者介面設計

對自動完成最有feel的應該就是Google 自動完成了,這個功能的正式名稱為「自動完成 Autocomplete」,所提供的搜尋建議是由系統基於各種演算法條件(包含搜尋字詞的熱門程度、使用者的搜尋記錄等)演算而來。基本上,Google 認為使用者會傾向於搜尋與多數人(尤其是具同樣搜尋偏好或在同一地理位置的人)相同的字詞,有關這個功能的開發故事,見Google 搜尋「自動完成」的開發故事

[ads2]

圖 1:Google首頁。

像哥在Google首頁的文字方塊中,輸入『工作達』這樣的查詢關鍵字,文字方塊底下,馬上幫哥在背後偷偷下一個查詢,從遠端伺服器,下載符合查詢條件的提示字串,自動地顯示在文字方塊下方,供我做選擇,如上圖所示。

可惜就算哥選了工作達人後,還是找不到哥的工作達人(https://job.achi.idv.tw)了。

圖 1-1:Google首頁。

前面兩頁幾乎被鈴木典丈的工作達人系列套書站滿了版面,哥的部落格只能慢慢等他的訊息冷了,再看看能不能重歸Google首頁。

jQuery UI是一個建立在jQuery JavaScript函式庫上的小工具跟互動式函式庫(參考JQuery UI入門),可以說是jQuery的外掛(plug-ins),非常容易使用,新手很快就可以設計出具高互動性的網站應用程式,並搭配多種網站開發程式使用,像是微軟的ASP.NET。

jQuery UI有一個Autocomplete Widget可以設計出類似Google首頁這樣的效果。不過要設計這樣的網頁,除了jQuery UI套件之外,我們還需要撰寫一個伺服端的程式碼,每當使用者在網頁文字方塊輸入關鍵字時,私下裡在用戶端利用jQuery下查詢,叫用伺服端的程式,將滿足篩選條件的資料回傳,再透過jQuery UI,將資料動態呈現在文字方塊下方。

要設計伺服器端的程式有許多的選項可供選擇,有常用的PHP程式跟很夯的Python…,但是今天哥只會介紹如何分別使用Web Form、ASP.NET Web Service(ASMX),至於WCF服務、ASP.NET Web API及MVC Action Method等技術下次有機會再分享,來整合jQuery UI Autocomplete Widget實作自動完成功能。

使用Web Form設計伺服端程式

使用開發工具:Microsoft Visual Studio Professional 2017

[ads2]

版本:.NET Framework 4.7.2

接下來我們會分享兩種建置專案的方式,來測試這個jQuery UI Autocomplete Widget的使用:

第一種是Web Site Project(WSP)的方式

這種方式是常在資策會、恆逸這種貴的要命的補習班中教師會用的方式,後面大部分的程式範例也會使用此種專案方式來分享。我們先從使用Web Form(附檔名為aspx的檔案)當做伺服端程式開始說起。接下來的步驟將使用Visual Studio 2017的Web Site的方式來建立網站。啟動Visual Studio 2017開發環境,從 Visual Studio 2017的主選單點選「檔案(F)」-「新增(N)」-「新增專案(P)」選項,接著會開啟「新增專案」對話窗,選取Visual C# – Web – 先前的版本的「ASP.NET 空白網站」,設定名稱為autodemo,位置自己選,方案名稱為autodemo,請參考下圖所示:

圖 2:新增專案。

題外話:在架構(F)沒看到.NET Framework 4.7.2,可以參考下面文件安裝

[Visual Studio] 如何為 Visual Studio 2017 增加 .NET Framework 4.7.2 開發套件

https://devmanna.blogspot.com/2018/05/visual-studio-2017-install-net-framework-4.7.2-sdk.html

從Visual Studio 2017的「網站(S)」選單,選取「加入新項目(W)」項目,新增一個ASP.NET Web Form (ASPX)網頁,請參考下圖所示:

圖 3:新增一個ASP.NET Web Form 網頁(ASPX)。

在「加入新項目(W)」對話盒中,選取「Web 表單」,設定名稱「GetRemoteData.aspx」,然後按下「新增」按鈕,新增一個網頁,請參考下圖所示:

圖 4:新增一個ASPX網頁。

點「設計」,雙擊游標處那邊的畫面空白處,進入程式設計視窗,Visual Studio 會自動產生一個Page_Load方法,刪除所有的HTML標籤,在其中加入以下程式碼:


圖 5:新增方法。

<%@ Page Language = "C#" %>
<script runat = "server">
     protected void Page_Load( object sender , EventArgs e ) {
         Response.ContentType = "application/json";
        var term = Request.Params[ "term" ];
        string[ ] data = { "Job" , "Japan" , "Korea", "Hong Kong" , "China" , "Singapore" , "Vietnam" };
        var results = ( from d in data where d.ToUpper( ).StartsWith( term.ToUpper( ) ) select d ).ToList( );
        System.Web.Script.Serialization.JavaScriptSerializer ser = new System.Web.Script.Serialization.JavaScriptSerializer( );
        Response.Write( ser.Serialize( results ) );
 
    }
</script>

被廣泛的應用於WEB應用開發的JSON交換資料格式,範例中利用Response物件將ContentType 設定為「application/json」表示要送回JSON格式資料,然後將符合查詢條件的資料(即文字字串是以某個字母開頭的),利用JavaScriptSerializer 物件序列化成JSON格式回傳。

從「方案總管」視窗,選取「GetRemoteData.aspx」,按滑鼠右鍵,從快捷選單中選取「在瀏覽器中檢視(內部Web瀏覽器)(B)」選項,執行網頁,以查詢字串輸入查詢關鍵字,將J開頭的所有字串回傳:

http://localhost:55738/GetRemoteData.aspx?term=J

執行結果參考如下:

下圖是將「S」開頭的所有字串回傳之執行結果:

※注意:選這個先前的版本來用,會有一些像是URL及埠號無法修改的情形。

下載「jQuery」3.4.1版函式庫

用戶端的程式需要使用到jQuery與jQuery UI函式庫,在Visual Studio 2017開發工具中,可以使用Nuget套件管理員下載它們。在「方案總管」視窗選取專案名稱。從Visual Studio 2017開發工具「工具(T)」-「NuGet套件管理員(N)」-「套件管理器主控台(O)」開啟「套件管理器主控台」視窗,然後在提示字元中輸入install-package指令,並使用「-version」指定安裝jQuery 3.4.1版本:

[ads2]

圖 6:使用Nuget套件管理員。

Install-Package jQuery -Version 3.4.1

如果不知道版本,可以輸入Install-Package jQuery,應該可以找到jQuery最新的版本。

得到的執行結果如下圖所示:

圖 7:下載「jQuery」3.4.1版函式庫。

下載「jQuery UI (Combined Library)」1.12.1版函式庫

下一步,使用Nuget套件管理員下載「jQuery UI (Combined Library)」1.12.1版函式庫。在「方案總管」視窗選取專案名稱。從Visual Studio 2017開發工具「工具(T)」-「NuGet套件管理員(N)」-「套件管理器主控台(O)」開啟「套件管理器主控台」視窗,然後在提示字元中輸入install-package指令,並使用「-version」指定安裝jQuery UI (Combined Library) 1.12.1版本或是不指定版本:

Install-Package jQuery.UI.Combined -Version 1.12.1

Install-Package jQuery.UI.Combined

得到的執行結果如下圖所示:

[ads2]

圖 8:下載「jQuery UI (Combined Library)」1.12.1版函式庫。

使用GET方法回傳JSON格式資料

用戶端的程式可以是Web Form(ASPX)網頁或HTML。我們就以HTML為例子。在Visual Studio 2017「專案」-「加入新項目」對話盒中,選取「HTML 頁面」,設定名稱,然後按下「新增」按鈕,新增一個網頁,網頁程式碼參考如下:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title></title>
    <link href="Content/themes/base/all.css" rel="stylesheet" />
</head>
<body>
    <input type="text" name="myInput" id="myInput" />
    <script src="Scripts/jquery-3.4.1.js"></script>
    <script src="Scripts/jquery-ui-1.12.1.js"></script>
    <script>
        $(function () {
            $("#myInput").autocomplete({
                source: function (request, callback) {
                    var data = { term: request.term };
                    $.ajax({
                        url: "GetRemoteData.aspx",
                        type: "GET",
                        data: data,
                        async: false,
                        complete: function (xhr, result) {
                            var lists = JSON.parse(xhr.responseText);
                            callback(lists);
                        }
                    });
                }
            })
        });
    </script>
</body>
</html>

網頁的設計重點如下:

  • 在<head>標籤之中,加入以下引用jQuery UI 樣式表語法。
  • 在<body>的<div>標籤之中加入一個HTML – input標籤。
  • 在</body>標籤之上引用jQuery以及jQuery UI函式庫。
  • 加入<script>區塊,於jQuery的ready事件撰寫程式碼,叫用ajax方法取回資料,使用HTTP GET方法呼叫ASPX檔案,將執行結果指定給jQuery UI Autocomplete Widget的source屬性。在source的callback函式中,可以利用request.term取得文字方塊中,使用者輸入的關鍵字。

現在可以來測試網頁的執行結果了。從「方案總管」視窗- 切換「解決方案與資料夾」下的HTML網頁,按CTRL+F5執行網頁,執行結果參考如下:

圖 9:自動完成功能。

第二種是Web Application Project(WAP)的方式

啟動Visual Studio 2017開發環境,從 Visual Studio 2017的主選單點選「檔案(F)」-「新增(N)」-「新增專案(P)」選項,接著會開啟「新增專案」對話窗,選取「Visual C#」 – 「Web」分類中,選取  「ASP.NET Web 應用程式(.NET Framework)」,設定名稱為autodemo1,位置自己選,方案名稱為autodemo1,請參考下圖所示:

圖 10:新增專案。

在「新增ASP.NET Web應用程式」對話盒中選取「空白」,勾選下方的「Web Form」項目,然後按下「確定」按鈕建立專案。

圖 11:新增應用程式。

從Visual Studio 2017的「專案(P)」選單,選取「加入新項目(W)」項目,新增一個ASP.NET Web Form (ASPX)網頁,請參考下圖所示:

圖 12:新增一個ASP.NET Web Form 網頁(ASPX)。

在「加入新項目(W)」對話盒中,選取「Web 表單」,設定名稱「GetRemoteData.aspx」,然後按下「新增」按鈕,新增一個網頁,請參考下圖所示:

圖 13:新增一個ASPX網頁。

注意這裡所開啟的GetRemoteData.aspx,會另外產生GetRemoteData.aspx.cs及其他相關檔案,為了避免不易操作,可以直接複製上面的範例程式到這個專案中,方便測試應用。

從「方案總管」視窗,選取「GetRemoteData.aspx」,按滑鼠右鍵,從快捷選單中選取「在瀏覽器中檢視(內部Web瀏覽器)(B)」選項,執行網頁,以查詢字串輸入查詢關鍵字,將J開頭的所有字串回傳:

http://localhost:61132/GetRemoteData.aspx?term=J

※如果不喜歡61132這個埠號,可以在「方案總管」視窗,選取「autodemo1」,按滑鼠右鍵選擇「屬性」,進行下一個步驟。

圖 14:屬性。

選取「Web」,在「專案 URL(J)」欄位從5000—65535輸入想要的埠號,彈出視窗按「是(Y)」就完成了。

圖 15:專案URL。

圖 15:建立虛擬目錄。

如果你選錯了埠號,就會出現這個視窗~

圖 16:屬性頁變更。

執行結果參考如下:

下圖是將「S」開頭的所有字串回傳之執行結果:

ASP.NET Web Service(ASMX)

接著,讓我們使用ASP.NET Web Service(ASMX)當做伺服端程式。延續前面的專案,加入一個ASP.NET Web Service(ASMX)。從Visual Studio 2017開發工具-「方案總管」視窗- 專案名稱上方按滑鼠右鍵,從快捷選單選擇「加入」- 「加入新項目(W)」,開啟「加入新項目」對話盒,從右上方文字方塊輸入「asmx」搜尋,選取「Web 服務 (ASMX)」,設定名稱為「WebService.asmx」,清除勾選右下方的「將程式碼置於個別檔案中(P)」,然後按下「新增(A)」按鈕,建立新服務,請參考下圖所示:

[ads2]

圖 17:加入ASP.NET Web Service(ASMX)。

修改工具產生的程式碼,將類別上方 [System.Web.Script.Services.ScriptService] 這行程式的註解拿掉,以開放透過ASP.NET AJAX方式叫用,再撰寫一個GetData方法,上方標示「WebMethod」Attribute,開放外部程式做呼叫,GetData方法會根據傳入的term關鍵字,篩選回傳符合條件的資料(以某個字開頭的字串):

<%@ WebService Language="C#" Class="WebService" %>

using System;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Linq;  

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
// 若要允許使用 ASP.NET AJAX 從指令碼呼叫此 Web 服務,請取消註解下列一行。
[System.Web.Script.Services.ScriptService]
public class WebService  : System.Web.Services.WebService {

    [WebMethod]
    public string[ ] GetData( string term ) { 
    	string[ ] data = { "Microsoft" , "apple" , "Linux" , "Cisco" , "Oracle" , "Sun" , "Misc" };
    	var result = ( from d in data where d.ToUpper( ).StartsWith( term.ToUpper( ) ) select d ).ToArray( );
    	return result;
    }
}

你不需要在程式中指定要回傳JSON或XML格式的資料,Web Service會自動根據需求決定。測試一下服務是否能正常執行。從「方案總管」視窗- 選取WebService.asmx檔案,按CTRL+F5執行,執行結果參考如下,你將看到一個Web服務測試頁面,點選瀏覽器上的「GetData」超連結:

圖 18:Web服務測試頁面。

進入Web服務測試畫面,輸入term為「J」,按下「叫用」按鈕,請參考下圖所示:

圖 19:叫用服務。

得到的執行結果如下圖所示,資料預設以XML方式回傳:

圖 20:取回XML格式資料

使用POST方法回傳 JSON格式資料

若想要Web服務(ASMX)回傳 JSON格式資料,需要以POST方式呼叫服務,並設定contentType為「”application/json; charset=utf-8″」,term參數要序列化成為json格式傳遞,程式參考如下:

[ads2]

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title></title>
    <link href="Content/themes/base/all.css" rel="stylesheet" />
</head>
<body>
    <input type="text" name="myInput" id="myInput" />
    <script src="Scripts/jquery-3.4.1.js"></script>
    <script src="Scripts/jquery-ui-1.12.1.js"></script>
    <script>

        $(function () {
            $("#myInput").autocomplete({
                source: function (request, callback) {
                    var data = { term: request.term };
                    $.ajax({
                        type: "POST",
                        contentType: "application/json; charset=utf-8",
                        url: "WebService.asmx/GetData",
                        dataType: "json",
                        data: JSON.stringify(data), //必需要序列化為json
                        async: false,
                        success: function (data) {
                            console.log(data);
                            callback(data.d);
                        }
                    });
                }
            })
        });
    </script>
</body>
</html>

使用POST方法回傳 XML格式資料

若想要Web服務(ASMX)回傳 XML格式資料,則不用設定contentType,資料也不需序列化為JSON格式,取回XML格式的資料之後,再透過jQuery解析XML文件內容,程式參考如下:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title></title>
    <link href="Content/themes/base/all.css" rel="stylesheet" />
</head>
<body>
    <input type="text" name="myInput" id="myInput" />
    <script src="Scripts/jquery-3.4.1.js"></script>
    <script src="Scripts/jquery-ui-1.12.1.js"></script>
    <script>

        $(function () {
            $("#myInput").autocomplete({
                source: function (request, callback) {
                    var data = { term: request.term };
                    $.ajax({
                        url: "WebService.asmx/GetData",
                        type: "POST",
                        data: data,
                        async: false,
                        success: function (xml) {
                            console.log(xml);

                            var lists = [];
                            $(xml).find("string").each(function () {
                                lists.push($(this).text());
                            });
                            callback(lists);
                        }
                    });
                }
            })
        });
    </script>
</body>
</html>

使用GET方法回傳 XML格式資料

預設為了安全性考量,Web服務並不允許使用HTTP GET方式呼叫,若需要使用GET方式叫用服務,則需要在網站根目錄下的Web.config檔案之中,加入以下設定,以啟用HttpGET:

<?xml version="1.0" encoding="utf-8"?>

<!--
  如需如何設定 ASP.NET 應用程式的詳細資訊,請前往
  https://go.microsoft.com/fwlink/?LinkId=169433
  -->

<configuration>

    <system.web>
      <compilation debug="true" targetFramework="4.7.2"/>
      <httpRuntime targetFramework="4.7.2"/>
      <webServices>
        <protocols>
          <add name="HttpSoap"/>
          <add name="HttpPost"/>
          <add name="HttpGet"/>
        </protocols>
      </webServices>
    </system.web>
    <system.codedom>
        <compilers>
            <compiler language="c#;cs;csharp" extension=".cs"
                type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
                warningLevel="4" compilerOptions="/langversion:default /nowarn:1659;1699;1701"/>
            <compiler language="vb;vbs;visualbasic;vbscript" extension=".vb"
                type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.VBCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
                warningLevel="4" compilerOptions="/langversion:default /nowarn:41008 /define:_MYTYPE=&quot;Web&quot; /optionInfer+"/>
        </compilers>
    </system.codedom>

</configuration>

接著就可以在網頁之中使用HTTP GET來叫用服務:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title></title>
    <link href="Content/themes/base/all.css" rel="stylesheet" />
</head>
<body>
    <input type="text" name="myInput" id="myInput" />
    <script src="Scripts/jquery-3.4.1.js"></script>
    <script src="Scripts/jquery-ui-1.12.1.js"></script>
    <script>

        $(function () {
            $("#myInput").autocomplete({
                source: function (request, callback) {
                    var data = { term: request.term };
                    $.ajax({
                        url: "WebService.asmx/GetData",
                        type: "get",
                        data: data,
                        async: false,
                        success: function (xml) {
                            console.log(xml);
                            var lists = [];
                            $(xml).find("string").each(function () {
                                lists.push($(this).text());
                            });
                            callback(lists);
                        }
                    });
                }
            })
        });
    </script>
</body>
</html>

小結

下次有機會再分享如何叫用WCF服務、如何利用Web API和MVC的Action Method來回傳符合篩選條件的資料。

感謝你看到這裡,很快就可以離開了,但最好的獎勵行動就是按一下幫我分享或留言,感恩喔~

點我分享到Facebook

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *