快速入門:將搜尋新增到應用程式 (HTML)
[ 本文的目標對象是撰寫 Windows 執行階段 App 的 Windows 8.x 和 Windows Phone 8.x 開發人員。如果您正在開發適用於 Windows 10 的 App,請參閱 最新文件 ]
大部分使用者都依賴搜尋來找尋他們所要的物件。例如,假設您的應用程式會播放媒體檔案,那麼使用者會希望能夠搜尋特定歌曲或影片;如果您的應用程式是烹飪應用程式,則使用者會希望能夠搜尋特定食譜或食材。
只需稍微規劃,為您的應用程式新增搜尋並不難。以下是您所需的內容:
- 要搜尋的資料來源。您需要使用者想要搜尋的某種目錄或項目的詳細目錄。您對這份詳細目錄描述得越詳盡,搜尋結果就越精確。
- 用於輸入搜尋查詢的控制項。Windows 提供的 SearchBox 控制項可讓您的應用程式使用。SearchBox 提供用來輸入查詢的輸入區域、用來執行搜尋的搜尋按鈕,以及用來處理搜尋查詢的事件。它甚至能夠自動提供一些搜尋建議。
- 用來顯示搜尋結果的頁面。Microsoft Visual Studio 提供 [搜尋結果頁] 範本,可建立您在處理搜尋查詢和顯示結果時所需的大量程式碼。
這個快速入門說明如何使用這些項目為您的應用程式新增搜尋功能。
如需了解此功能的運作情形,請參閱應用程式功能,從開始到完成系列: Windows 市集應用程式 UI,從開始到完成
先決條件
- 我們假設您可以使用 JavaScript 在基本的 Windows 市集應用程式上新增控制項。如需新增控制項的相關指示,請參閱快速入門:新增控制項和處理事件和快速入門:新增 WinJS 控制項與樣式。
- 您應該熟悉如何使用資料來源與資料繫結。如需相關指示,請參閱如何自訂 Visual Studio 範本資料。
設定資料
使用者輸入搜尋查詢時,您的應用程式就會搜尋使用者想要尋找的項目。您應用程式搜尋的資料可能有數種形式:XML 檔案、JavaScript 物件標記法 (JSON) 資料、資料庫、Web 服務,或檔案系統中的檔案。
這個快速入門中的範例會使用您在 Visual Studio 建立新專案時,Microsoft Visual Studio 產生的範例資料。
當您使用 Visual Studio 建立新的 [格線應用程式]、[中樞應用程式]**** 或 [分割應用程式] 時,會在您的應用程式 js 資料夾中建立名為 data.js 的檔案。這個檔案包含可取代成您自己資料的靜態資料。例如,如果您的應用程式發出取得 RSS 或 JSON 資料的 xhr 要求,您可能需要將自己的程式碼新增到 data.js。在該處包含程式碼可讓您易於使用自己的資料,而不用變更 [搜尋結果頁] 所用的資料模型。
以下的範例是範例資料看起來的樣子:
function generateSampleData() {
// . . .
var sampleGroups = [
{ key: "group1", title: "Group Title: 1", // . . .
// . . .
];
var sampleItems = [
{ group: sampleGroups[0], title: "Item Title: 1", // . . .
// . . .
];
return sampleItems;
}
如果要讓檔案存取此資料,data.js
檔案會定義公開這些成員的 Data
命名空間:
items
:包含資料項目的 WinJS.Binding.List。這是一個 List 群組。groups
:包含資料項目所屬群組的 WinJS.Binding.List(您也可以透過呼叫 items.groups 取得群組)。- getItemReference:抓取包含群組索引鍵和指定項目標題的物件。
- getItemsFromGroup:抓取 FilteredListProjection,其中包含屬於群組的項目以及指定索引鍵。
- resolveGroupReference:抓取代表含指定索引鍵之群組的物件。
- resolveItemReference:這個方法會使用包含兩個字串、一個群組索引鍵和標題的陣列。這個方法會抓取含有指定群組索引鍵和標題的項目。
您不需要使用此命名空間或這些成員來包含您的資料,但這樣做可以讓使用 [搜尋結果頁] 範本更加簡單
(如需使用範本產生之資料的詳細資訊,請參閱如何自訂 Visual Studio 範本資料)。
新增搜尋結果頁
[搜尋結果頁]**** 會處理搜尋查詢並顯示結果。現在為您的專案新增一個搜尋結果頁。(這些指示假設您從中樞、格線或分割範本建立專案)
新增搜尋結果頁項目
在 [方案總管] 的 [頁面]**** 專案資料夾中,新增名為搜尋的新資料夾。
開啟 [搜尋] 資料夾的捷徑功能表,然後選擇 [加入]**** > [新增項目]。
在 [加入新項目]**** 對話方塊的中央窗格,選擇 [搜尋結果頁]。針對這個範例,保留 [名稱]**** 方塊中顯示的預設名稱 searchResults.html。
選擇 [加入]。
Visual Studio 會將 searchResults.html、searchResults.css 以及 searchResults.js 新增到新 [搜尋]**** 資料夾中的專案。
新增 SearchBox
我們還要對搜尋結果頁進行一些處理,但現在先將 SearchBox 新增到我們的應用程式。 使用 SearchBox 比較容易在實作搜尋結果頁時予以測試。
SearchBox 可讓使用輸入查詢。它也可以顯示建議。只需將這個標記新增到 HTML 頁面,即可將 SearchBox 新增至您的應用程式:
<div class="searchBox"
data-win-control="WinJS.UI.SearchBox"
data-win-options="{placeholderText: 'Search'}">
</div>
(您還需要登錄 onquerysubmitted 事件;我們將在之後的步驟中說明)。
您應該將搜尋方塊放置在哪裡?建議您在應用程式的每個頁面放置搜尋方塊,讓使用者能夠隨時輕鬆搜尋。如果空間有限,您可以將搜尋方塊放在頂端應用程式列。
將 SearchBox 新增至頁面
我們將 SearchBox 新增到您的其中一個應用程式頁面。這些指示適用於以 Page 控制項為基礎的任何頁面。
SearchBox 的最佳擺放位置通常是頁面右上角。從 Visual Studio 範本建立的大多數頁面 (例如 [頁面控制項] 範本) 都有一個包含頁面標題和返回按鈕的 header 元素:
<header aria-label="Header content" role="banner"> <button data-win-control="WinJS.UI.BackButton"></button> <h1 class="titlearea win-type-ellipsis"> <span class="pagetitle"></span> </h1> </header>
<header aria-label="Header content" role="banner"> <button data-win-control="WinJS.UI.BackButton"></button> <h1 class="titlearea win-type-ellipsis"> <span class="pagetitle">Welcome to basicPage</span> </h1> <div class="searchBox" data-win-control="WinJS.UI.SearchBox" data-win-options="{placeholderText: 'Search'}"> </div> </header>
(建議選項) 您應該讓您的使用者只要開始使用鍵盤輸入,就能夠搜尋應用程式中的內容。
許多人都將使用鍵盤與 Windows 8 互動。讓使用者透過輸入進行搜尋可以有效使用鍵盤互動,並讓您的應用程式搜尋經驗與 [開始] 畫面一致。
將 SearchBox 控制項的 focusOnKeyboardInput 屬性設定為 true,讓搜尋方塊在使用者輸入項目時收到輸入。
<div class="searchBox" data-win-control="WinJS.UI.SearchBox" data-win-options="{placeholderText: 'Search', focusOnKeyboardInput: true }"> </div>
Visual Studio 為您建立的 default.css 樣式表提供標頭元素一個 -ms-grid 配置。若要將 SearchBox 放在頁面的右上角,只要將這個樣式新增到您頁面的階層式樣式表 (CSS) 檔案:
.searchBox { -ms-grid-column: 4; margin-top: 57px; margin-right: 29px; }
處理 onquerysubmitted 事件
您的應用程式很可能會有多個 SearchBox 控制項。我們來定義這些控制項都能使用的單一 onquerysubmitted 事件處理常式。
開啟您應用程式的 default.js 檔案。
建立名為 "querySubmittedHandler" 的 onquerysubmitted 事件處理常式,它使用一個名為 "args" 的引數(您可以將這個方法定義放在包裝現有 default.js 程式碼之匿名函式的任何位置)。
function querySubmittedHandler(args) { }
呼叫 WinJS.Navigation.navigate 使用事件處理常式瀏覽至新的搜尋結果頁。
args.details
屬性包含的物件可提供搜尋結果頁所需之事件的相關資訊,因此當您呼叫 WinJS.Navigation.navigate 時會傳送這個物件。function querySubmittedHandler(args) { WinJS.Navigation.navigate('/pages/search/searchResults.html', args.detail); }
警告 如果使用 [空白應用程式] 範本建立應用程式,則需要在應用程式新增瀏覽支援,才能讓搜尋正常運作。 您可以在應用程式新增名為
PageControlNavigator
的自訂控制項,以便使用與格線、分割及瀏覽應用程式範本相同的方式支援瀏覽。您可以在快速入門:使用單頁瀏覽中,了解這個自訂控制項支援瀏覽的方式。如果您不要使用自訂控制項支援瀏覽,則需要撰寫自己的程式碼,以接聽和回應瀏覽事件,例如 WinJS.Navigation.navigated。您可以在瀏覽和瀏覽歷程記錄範例查看範例,以了解如何不使用自訂控制項 (例如PageControlNavigator
) 來支援瀏覽。我們現在需要定義命名空間並將處理常式設為成員,以公開發佈這個事件處理常式。我們將這個命名空間稱為 "SearchUtils"。我們還需要使用 WinJS.UI.eventHandler 方法,以宣告的方式設定事件處理常式 (如需此操作如何運作的詳細資訊,請參閱如何以宣告方式設定事件處理常式)。
WinJS.Namespace.define("SearchUtils", { querySubmittedHandler: WinJS.UI.eventHandler(querySubmittedHandler) } );
開啟包含您 SearchBox 的 HTML 頁面。使用 data-win-options 屬性將 onquerysubmitted 事件設成
SampleUtils.querySubmittedHandler
。<div class="searchBox" data-win-control="WinJS.UI.SearchBox" data-win-options="{placeholderText: 'Search', focusOnKeyboardInput: true, onquerysubmitted: SearchUtils.querySubmittedHandler}"> </div>
讓我們來試試看。執行應用程式,並在 SearchBox 中輸入測試查詢,然後按 Enter 鍵。如果您使用的是 Visual Studio 提供的範例資料,試著使用 "1" 作為您的測試查詢。
您編寫的 onquerysubmitted 事件處理常式會瀏覽至搜尋結果頁,並傳遞您輸入的查詢。
如果您使用範例資料,應該會看到符合測試查詢的項目。如果使用自己的資料,您可能還不能取得任何結果,我們需要先更新搜尋結果頁。我們將在之後的步驟加以說明。
搜尋您的資料
現在請回到搜尋結果頁。 當您的應用程式瀏覽到搜尋結果頁時,第一個會呼叫的方法是 _handleQuery
方法。 _handleQuery
會呼叫多個我們需要修改的方法:
_generateFilters
產生篩選清單,使用者按一下即可篩選結果。
_searchData
搜尋您的資料是否有相符的項目,並將它們儲存在名為
originalResults
的 List。_populateFilterBar
在我們的篩選清單顯示篩選。
我們來更新這些方法,針對您的資料加以自訂。
更新篩選
_generateFilters
方法會產生篩選清單,使用者按一下即可篩選結果。範本產生的方法會建立三個篩選:"All" 篩選可顯示所有結果、顯示群組 1 項目的篩選,以及顯示其他項目的篩選。我們將範例產生的程式碼取代為可動態產生篩選清單的程式碼。如此一來,如果您變更範例資料,您的新篩選就會顯示在頁面上。我們將會更新 _generateFilters
程式碼,並建立兩個 Helper 方法。但首先,我們需要更新 data.js 檔案以存取群組清單;我們要使用這些群組定義篩選。
更新 _generateFilters 方法
在 searchResults.js 中,找尋
_generateFilters
方法並刪除其中所含的程式碼。初始化
_filters
陣列 (_filters
陣列是搜尋結果頁定義的成員變數)。_generateFilters: function () { this._filters = [];
現在來建立篩選。篩選是含有三個屬性的物件:
results
:要顯示的項目 List。我們目前將它設定為 null。text
:篩選的顯示文字。predicate
:使用項目的函式。如果項目符合篩選條件 (選取此篩選後應該顯示的項目),此函式會傳回 true;否則,傳回 false。
首先,我們來建立 "All" 篩選。全部篩選一定會顯示項目,因此它的
predicate
一定會傳回 true。this._filters.push({ results: null, text: "All", predicate: function (item) { return true; } });
現在,我們為資料中的每個群組建立篩選。我們的群組會儲存成名為
Data.groups
的 List。使用 forEach 方法逐一處理 List 中的每個群組。forEach 方法使用函式作為參數;這個函式會針對清單中的每個項目進行呼叫。我們將名為_createFiltersForGroups
的成員函式傳送給它;我們將在下個步驟建立函式。if (window.Data) { Data.groups.forEach(this._createFiltersForGroups.bind(this)); } },
現在,讓我們來建立
_createFiltersForGroups
函式。建立一個名為
_createFiltersForGroups
的成員函式,這個函式可接受三個參數:element、index 及 array。_createFiltersForGroups: function (element, index, array){
element 參數包含我們的群組物件。 建立一個新篩選物件並使用 push 方法將它新增到
_filters
陣列。將篩選的results
屬性設定為 null、將它的text
屬性設定為 element.title
,並將它的predicate
屬性設定為名為_filterPredicate
的函式。您將在下個步驟中定義_filterPredicate
方法。this._filters.push( { results: null, text: element.title, predicate: this._filterPredicate.bind(element)} ); },
建立一個名為
_filterPredicate
的成員函式,這個函式可接受一個名為 item 的參數。如果 item 參數的group
屬性等於目前的群組物件,便傳回 true。_filterPredicate: function (item) { return item.group === this; },
下列為我們剛建立之三個方法的完整程式碼:
_generateFilters: function () {
this._filters = [];
this._filters.push({ results: null, text: "All", predicate: function (item) { return true; } });
if (window.Data) {
Data.groups.forEach(this._createFiltersForGroups.bind(this));
}
},
_createFiltersForGroups: function (element, index, array){
this._filters.push(
{ results: null, text: element.title, predicate: this._filterPredicate.bind(element)}
);
},
_filterPredicate: function (item) {
return item.group === this;
},
執行應用程式並進行搜尋,您應該會在篩選列中看到您的新篩選。
如果您使用的是範本產生的範例資料,您可能會發現有些群組遭到裁剪。您可以在搜尋結果頁的 CSS 檔案中進行一些調整來修正這個問題。
更新搜尋結果頁的 CSS
開啟 searchResults.css。
尋找
.searchResults section[role=main]
樣式並將 -ms-grid-rows 屬性的值變更成 "auto 1fr"。.searchResults section[role=main] { /* Define a grid with rows for the filters and results */ -ms-grid-columns: 1fr; -ms-grid-rows: auto 1fr; -ms-grid-row: 1; -ms-grid-row-span: 2; display: -ms-grid; }
尋找
.searchResults section[role=main] .filterbar
樣式,並將 word-wrap 屬性的值變更成 "normal",然後將 margin-bottom 設為 "20px"。.searchResults section[role=main] .filterbar { -ms-font-feature-settings: "case" 1; -ms-grid-row: 1; list-style-type: none; margin-left: 60px; margin-right: 60px; margin-top: 133px; max-width: calc(100% - 120px); position: relative; white-space: normal; z-index: 1; margin-bottom: 20px; }
尋找
.searchResults section[role=main] .filterbar li
樣式並將 display 屬性的值變更成 "inline-block"。.searchResults section[role=main] .filterbar li { display: inline-block; margin-left: 20px; margin-right: 20px; margin-top: 5px; opacity: 0.6; }
尋找
.searchResults section[role=main] .resultslist
樣式,並將 -ms-grid-row 屬性的值變更成 "2",然後將 -ms-grid-row-span 設為 "1"。.searchResults section[role=main] .resultslist { -ms-grid-row: 2; -ms-grid-row-span: 1; height: 100%; position: relative; width: 100%; z-index: 0; }
執行應用程式並進行另一個搜尋。您現在應該會看到所有篩選。
更新搜尋演算法
_searchData
方法會搜尋符合搜尋查詢的項目資料。範本產生的程式碼會搜尋每個項目的標題、副標題及描述。我們來撰寫自己的搜尋程式碼,依相關性排序結果。
更新 _searchData 方法
開啟 searchResults.js,尋找
_searchData
方法,並刪除其中所含的程式碼。建立名為
originalResults
的變數;這會是我們的傳回值。// This function populates a WinJS.Binding.List with search results for the // provided query. _searchData: function (queryText) { // Create a variable for the results list. var originalResults;
將查詢文字和我們看到的文字轉換成小寫,讓我們的搜尋變成區分大小寫。我們先將查詢轉換成小寫,並將它儲存成名為
lowercaseQueryText
的變數。// Convert the query to lowercase. var lowercaseQueryText = queryText.toLocaleLowerCase();
嘗試存取資料前,先確定資料已經存在。
if (window.Data) {
如果您使用 data.js 提供的範例資料,則我們的項目會儲存在
Data.items
,這是 WinJS.Binding.List 物件。使用 createFiltered 方法篩選出不符合搜尋查詢的項目。createFiltered 方法使用篩選函式作為參數。這個篩選函式使用一個參數 item。List 會在清單中的每個項目呼叫此函式,以判斷它是否應該在篩選後的清單中。 如果應該包含項目,函式就會傳回 true,如果應該略過項目,則會傳回 false。
originalResults = Data.items.createFiltered( function (item) {
在 JavaScript 中,您可以在現有物件附加新的屬性。將
ranking
屬性新增到 item,並將它的值設為 "-1"。// A ranking < 0 means that a match wasn't found. item.ranking = -1;
首先,我們來看看項目標題是否包含查詢文字。如果有,給項目 10 點。
if (item.title.toLocaleLowerCase().indexOf(lowercaseQueryText) >= 0) { item.ranking += 10; }
接著,在副標題欄位檢查相符的項目。如果找到相符的項目,給項目 5 點。
if (item.subtitle.toLocaleLowerCase().indexOf(lowercaseQueryText) >= 0) { item.ranking += 5; }
最後,檢查描述欄位。如果找到相符的項目,給項目 1 點。
if (item.description.toLocaleLowerCase().indexOf(lowercaseQueryText) >= 0) { item.ranking += 1; }
如果項目的點數為 -1,表示不符合我們的搜尋查詢。針對傳回值,如果項目的點數等級大於或等於 0,則傳回 true。
return (item.ranking >= 0); } );
目前為止,我們已將清單縮小為只符合搜尋查詢的項目,並新增了點數等級資訊。現在,我們使用 createSorted 方法排序結果清單,將最多點數的項目排在第一個。
// Sort the results by the ranking info we added. originalResults = originalResults.createSorted(function (firstItem, secondItem){ if (firstItem.ranking == secondItem.ranking) { return 0; } else if (firstItem.ranking < secondItem.ranking) return 1; else return -1; }); }
如果我們的資料遺失,請建立一個空的清單。
else { // For some reason, the Data namespace is null, so we // create an empty list to return. originalResults = new WinJS.Binding.List(); }
最後,傳回結果。
return originalResults; }
下列為更新的 _searchData
方法的完整程式碼。
_searchData: function (queryText) {
// Create a variable for the results list.
var originalResults;
// Convert the query to lowercase.
var lowercaseQueryText = queryText.toLocaleLowerCase();
if (window.Data)
{
originalResults = Data.items.createFiltered(
function (item) {
// A ranking < 0 means that a match wasn't found.
item.ranking = -1;
if (item.title.toLocaleLowerCase().indexOf(lowercaseQueryText) >= 0) {
item.ranking += 10;
}
if (item.subtitle.toLocaleLowerCase().indexOf(lowercaseQueryText) >= 0) {
item.ranking += 5;
}
if (item.description.toLocaleLowerCase().indexOf(lowercaseQueryText) >= 0) {
item.ranking += 1;
}
return (item.ranking >= 0);
}
);
// Sort the results by the ranking info we added.
originalResults = originalResults.createSorted(function (firstItem, secondItem){
if (firstItem.ranking == secondItem.ranking) {
return 0;
}
else if (firstItem.ranking < secondItem.ranking)
return 1;
else
return -1;
});
}
else {
// For some reason, the Data namespace is null, so we
// create an empty list to return.
originalResults = new WinJS.Binding.List();
}
return originalResults;
}
提供瀏覽到搜尋傳回的項目
當您執行應用程式並進行搜尋時,搜尋結果頁會將結果顯示在 ListView 控制項中。 現在,按一下其中一個搜尋結果項目並不會有任何反應。我們新增一些程式碼,在使用者按一下時顯示項目。
當使用者按一下 ListView 中的項目時,ListView 會觸發 oniteminvoked 事件。搜尋結果頁的範例產生程式碼會定義名為 _itemInvoked
的 oniteminvoked 事件處理常式。更新程式碼以瀏覽到叫用的項目。
新增項目瀏覽
開啟 searchResults.js,然後將程式碼新增至
_itemInvoked
函式以瀏覽到正確頁面。注意 這裡顯示的 URI 是針對「中樞」範本。對於「格線」範本,URI 必須是:/pages/itemDetail/itemDetail.html。對於「分割」範本,URL 必須是:/pages/items/items.html。_itemInvoked: function (args) { args.detail.itemPromise.done(function itemInvoked(item) { // TODO: Navigate to the item that was invoked. var itemData = [item.groupKey, item.data.title]; WinJS.Navigation.navigate("/pages/item/item.html", { item: itemData }); }); },
(選用) 更新 ListView 控制項的 itemTemplate
範本產生的搜尋結果頁會定義 itemTemplate,這是設計與 Visual Studio 為您建立的範例資料來源搭配使用;它會預期每個資料項目都有下列欄位:"影像"、"標題"、"副標題"及"描述"。
如果資料項目具備不同欄位,您就必須修改 itemTemplate。如需相關指示,請參閱快速入門:新增 ListView。
(選用) 新增搜尋建議
搜尋建議會顯示在搜尋窗格的搜尋方塊下方。建議非常重要,因為這樣可以節省使用者的時間,並為使用者提供搜尋您應用程式內容時的重要提示。
您可以從數個來源得到建議:
- 您可以自行定義建議。例如,您可以建立汽車製造商清單。
- 如果您的應用程式搜尋本機檔案,則可以從 Windows 得到建議。
- 您可以從 Web 服務或伺服器得到建議。
如需有關顯示建議的使用者經驗指導方針,請參閱搜尋的指導方針和檢查清單。
如果使用 LocalContentSuggestionSettings,只要透過幾行程式碼,就可以根據 Windows 的本機檔案新增建議。此外,您也可以登錄搜尋方塊控制項的 onsuggestionsrequested 事件並建立自己的建議清單,其中包括您從其他來源 (例如本機定義的清單或 Web 服務) 所擷取的建議。這個快速入門說明如何處理 onsuggestionsrequested 事件。
如需示範如何新增搜尋建議的其他程式碼範例,請下載 SearchBox 控制項範例。範例會示範如何使用這三種可能來源新增搜尋建議,以及如何使用輸入法 (IME) 產生的查詢文字替代形式來新增東亞語言的建議 (如果應用程式將由日文或中文使用者使用,建議您使用替代查詢文字)。
處理 SuggestionsRequested 事件
您的應用程式可能會有多個 SearchBox 控制項;讓我們在您的 default.js 檔案中定義單一事件處理常式,讓這些控制項都能使用。在您之前步驟中建立的
querySubmittedHandler
方法後面新增此程式碼。function suggestionsRequestedHandler(args) {
將 SearchBox 查詢文字轉換為小寫。
var query = args.detail.queryText.toLocaleLowerCase();
系統會自動提供一些搜尋建議,例如使用者執行過的搜尋。讓我們將搜尋建議新增至系統提供的搜尋建議中。
// Retrieve the system-supplied suggestions. var suggestionCollection = args.detail.searchSuggestionCollection;
確定查詢至少包含一個字元,且我們可以存取自己的資料。
if (query.length > 0 && window.Data) {
逐一查看資料中的每個項目,並檢查是否有相符項目。尋找相符項目時,可將相符項目的標題附加至搜尋建議集合。
Data.items.forEach( function (element, index, array) { if (element.title.substr(0, query.length).toLocaleLowerCase() === query) { suggestionCollection.appendQuerySuggestion(element.title); } });
args.detail.linguisticDetails.queryTextAlternatives
屬性會針對以 IME 輸入文字的使用者提供其他建議。使用這些建議可改善東亞語言使用者的搜尋經驗。讓我們檢查替代查詢文字是否有字串包含原始查詢,並將其新增至我們的搜尋建議清單。args.detail.linguisticDetails.queryTextAlternatives.forEach( function (element, index, array) { if (element.substr(0, query.length).toLocaleLowerCase() === query) { suggestionCollection.appendQuerySuggestion(element); } }); } }
這就是我們的搜尋建議事件處理常式所需的程式碼。下列是完整的
suggestionsRequestedHandler
方法:function suggestionsRequestedHandler(args) { var query = args.detail.queryText.toLocaleLowerCase(); // Retrieve the system-supplied suggestions. var suggestionCollection = args.detail.searchSuggestionCollection; if (query.length > 0 && window.Data) { Data.items.forEach( function (element, index, array) { if (element.title.substr(0, query.length).toLocaleLowerCase() === query) { suggestionCollection.appendQuerySuggestion(element.title); } }); args.detail.linguisticDetails.queryTextAlternatives.forEach( function (element, index, array) { if (element.substr(0, query.length).toLocaleLowerCase() === query) { suggestionCollection.appendQuerySuggestion(element); } }); } }
注意 如果您的資料來源非同步,必須將更新包裝在 Promise 中的搜尋建議集合。範例程式碼使用 List,這是同步的資料來源,如果 List 是非同步資料來源,方法看起來會像這樣。
function suggestionsRequestedHandler(args) { var query = args.detail.queryText.toLocaleLowerCase(); // Retrieve the system-supplied suggestions. var suggestionCollection = args.detail.searchSuggestionCollection; if (query.length > 0 && window.Data) { args.detail.setPromise(WinJS.Promise.then(null, function () { Data.items.forEach( function (element, index, array) { if (element.title.substr(0, query.length).toLocaleLowerCase() === query) { suggestionCollection.appendQuerySuggestion(element.title); } }); args.detail.linguisticDetails.queryTextAlternatives.forEach( function (element, index, array) { if (element.substr(0, query.length).toLocaleLowerCase() === query) { suggestionCollection.appendQuerySuggestion(element); } }); }) ); } }
這就是我們的搜尋建議事件處理常式所需的程式碼。透過在之前步驟定義的
SearchUtils
命名空間公開這些程式碼,讓這些程式碼可供公開存取。WinJS.Namespace.define("SearchUtils", { querySubmittedHandler: WinJS.UI.eventHandler(querySubmittedHandler), suggestionsRequestedHandler: WinJS.UI.eventHandler(suggestionsRequestedHandler) } );
現在向我們的 SearchBox 登錄事件。開啟包含您 SearchBox 的 HTML 頁面,將 onsuggestionsrequested 事件設為
SearchUtils.suggestionsRequestedHandler
。<div class="searchBox" data-win-control="WinJS.UI.SearchBox" data-win-options="{placeholderText: 'Search', focusOnKeyboardInput: true, onquerysubmitted: SearchUtils.querySubmittedHandler, onsuggestionsrequested: SearchUtils.suggestionsRequestedHandler}"> </div>
實作搜尋協定 (針對舊版 Windows)
在 Windows 8.1 之前,應用程式使用搜尋常用鍵提供應用程式內搜尋。開發人員實作搜尋協定和使用 SearchPane API 來處理查詢以及取得建議和結果。
雖然我們繼續完全支援 Windows 8 搜尋協定與 SearchPane API,但是從 Windows 8.1 開始,我們建議使用 SearchBox 控制項而非 SearchPane。 使用 SearchBox 的應用程式不需要實作搜尋協定。
應用程式到底該不該使用 SearchPane 與搜尋協定?如果您認為使用者不會經常搜尋您的應用程式,則可使用 SearchPane 與搜尋協定。建議您在應用程式中使用含有搜尋字符 (Segoe UI Symbol 0xE0094,15pt) 的按鈕時,讓使用者按一下就能啟用搜尋窗格。若要查看用來實作 SearchPane 與搜尋協定的程式碼,請參閱搜尋協定範例。
摘要與後續步驟
您使用了 SearchBox 控制項與 [搜尋結果頁],將搜尋新增到應用程式。
如需可協助您為使用者設計和建立出色搜尋體驗的指導方針,請參閱搜尋的指導方針和檢查清單。