Inicio rápido: agregar búsqueda a una aplicación (HTML)
[ Este artículo está destinado a desarrolladores de Windows 8.x y Windows Phone 8.x que escriben aplicaciones de Windows en tiempo de ejecución. Si estás desarrollando para Windows 10, consulta la documentación más reciente
La mayoría de los usuarios recurre a las búsquedas para encontrar lo que necesitan. Por ejemplo, si la aplicación reproduce archivos multimedia, los usuarios confiarán en poder buscar una canción o un vídeo en particular; si la aplicación es sobre cocina, los usuarios confiarán en buscar recetas o ingredientes determinados.
Con un poco de planeación, no resulta tan difícil agregar la función de búsqueda a la aplicación. Esto es lo que necesitas:
- Un origen de datos en el que realizar la búsqueda. Necesitas una especie de catálogo o inventario de elementos que los usuarios puedan estar interesados en buscar. Cuanto más descriptivo consigas que sea el inventario, mejores serán los resultados.
- Un control para escribir las consultas de búsqueda. Windows proporciona un control SearchBox que puede utilizar la aplicación. El SearchBox proporciona un área de entrada para escribir consultas, un botón de búsqueda para ejecutar la búsqueda y eventos para controlar las consultas de búsqueda. Proporciona incluso sugerencias de búsqueda automáticamente.
- Una página que muestre los resultados de la búsqueda. Microsoft Visual Studio proporciona la plantilla Página de resultados de búsqueda, que crea gran parte del código necesario para controlar las consultas de búsqueda y mostrar los resultados.
Esta guía de inicio rápido explica cómo usar estos elementos para agregar la funcionalidad de búsqueda a tu aplicación.
Consulta esta característica como parte de nuestra serie Características de aplicaciones, de principio a fin: Interfaz de usuario de aplicaciones de la Tienda Windows, de principio a fin
Requisitos previos
- Damos por hecho que sabes agregar controles a una aplicación de la Tienda Windows básica con JavaScript. Para obtener instrucciones sobre cómo agregar controles, consulta Inicio rápido: Agregar controles y administrar eventos e Inicio rápido: Agregar controles y estilos de WinJS.
- Debes estar familiarizado con los orígenes de datos y el enlace de datos. Si necesitas instrucciones, consulta Cómo personalizar los datos de la plantilla de Visual Studio.
Configurar los datos
Cuando el usuario especifica una consulta de búsqueda, la aplicación busca elementos que dicho usuario podría querer encontrar. Los datos que busca la aplicación podrían estar en diferentes formatos: podría ser un archivo XML, datos de notación de objetos JavaScript (JSON), una base de datos, un servicio web o archivos del sistema de archivos.
En los ejemplos de este inicio rápido se usan los datos de muestra que Microsoft Visual Studio genera al crear un proyecto en Visual Studio.
Cuando se usa Visual Studio para crear una Aplicación de cuadrícula, una Aplicación Hub o una Aplicación dividida, se crea un archivo denominado data.js en la carpeta js de la aplicación. Este archivo contiene datos estáticos que puedes reemplazar por tus propios datos. Por ejemplo, si tu aplicación realiza una sola solicitud xhr para obtener datos RSS o JSON, puede que te convenga agregar tu código a data.js. Si incluyes el código aquí, podrás usar fácilmente tus propios datos sin cambiar el modelo de datos usado en la plantilla Página de resultados de la búsqueda.
Este es un ejemplo del aspecto que tienen los datos de muestra:
function generateSampleData() {
// . . .
var sampleGroups = [
{ key: "group1", title: "Group Title: 1", // . . .
// . . .
];
var sampleItems = [
{ group: sampleGroups[0], title: "Item Title: 1", // . . .
// . . .
];
return sampleItems;
}
Para que estos datos estén accesibles para los archivos, el archivo data.js
define un espacio de nombres Data
que expone los siguientes miembros:
items
: una WinJS.Binding.List donde figuran los elementos de datos. Se trata de una List agrupada.groups
: una WinJS.Binding.List donde figuran los grupos a los que los elementos de datos pertenecen (los grupos también se pueden obtener llamando a items.groups).- getItemReference: recupera un objeto que contiene la clave de grupo y el título del elemento especificado.
- getItemsFromGroup: recupera una FilteredListProjection que contiene los elementos que pertenecen al grupo con la clave especificada.
- resolveGroupReference: recupera un objeto que representa al grupo con la clave especificada.
- resolveItemReference: este método toma una matriz que contiene dos cadenas, a saber, una clave de grupo y un título. Con este método se recupera el elemento que tiene la clave de grupo y título especificados.
No es necesario que uses este espacio de nombres o estos miembros para contener tus datos pero, si lo haces, será más fácil usar la plantilla Página de resultados de la búsqueda.
(Para más información sobre cómo trabajar con los datos generados mediante plantilla, consulta Cómo personalizar los datos de la plantilla de Visual Studio).
Agregar una página de resultados de búsqueda
La plantilla Página de resultados de búsqueda procesa consultas de búsqueda y muestra el resultado. Vamos a agregar una al proyecto (en estas instrucciones se da por hecho que el proyecto se ha creado a partir de las plantillas Aplicación Hub, Aplicación de cuadrícula o Aplicación dividida ).
Agregar el elemento Página de resultados de búsqueda
En la carpeta de proyecto pages del Explorador de soluciones, agrega una nueva carpeta con el nombre search.
Abre el menú contextual para la carpeta search y elige Agregar > Nuevo elemento.
En el panel central del cuadro de diálogo Agregar nuevo elemento, elige Página de resultados de búsqueda. Para este ejemplo, mantén el nombre predeterminado, searchResults.html, que aparece en el cuadro Nombre.
Haz clic en Agregar.
Visual Studio agrega searchResults.html, searchResults.css, y searchResults.js al proyecto en la nueva carpeta search.
Agregar un SearchBox
Todavía tenemos trabajo por hacer en la página de resultados de búsqueda, pero antes agregaremos SearchBox a nuestra aplicación. Si tenemos un SearchBox nos resultará más fácil probar nuestra página de resultados de búsqueda cuando la implementemos.
Un SearchBox permite al usuario escribir consultas. También se pueden mostrar sugerencias. Para agregar un SearchBox a la aplicación, simplemente agrega este marcado a una página HTML:
<div class="searchBox"
data-win-control="WinJS.UI.SearchBox"
data-win-options="{placeholderText: 'Search'}">
</div>
(Deberás registrarte también para el evento onquerysubmitted, cosa que haremos en un paso posterior).
¿Dónde debe ir el cuadro de búsqueda? Recomendamos poner un cuadro de búsqueda en cada página de la aplicación, de modo que los usuarios puedan realizar una búsqueda fácilmente siempre que lo deseen. Si tienes problemas de espacio, puedes colocar el cuadro de búsqueda en una barra de la aplicación en la parte superior.
Agregar un SearchBox a la página
Vamos a agregar un SearchBox a una de las páginas de tu aplicación. Estas instrucciones son igualmente válidas para cualquier página que se base en un control Page.
Normalmente, la mejor ubicación para colocar el SearchBox es la esquina superior derecha de la página. La mayoría de las páginas que crees a partir de una plantilla de Visual Studio (como, por ejemplo, la plantilla Control de página) tiene un elemento header que contiene el título de la página y un botón para retroceder:
<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>
Sencillamente, agrega el SearchBox después del elemento h1:
<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>
(Recomendado) Debes ofrecer al usuario la posibilidad de buscar contenido en tu aplicación simplemente al comenzar a escribir con el teclado.
Muchas personas usarán un teclado para interactuar con Windows 8. Permitirle al usuario buscar al escribir proporciona un uso eficiente de la interacción de teclado y hace que la experiencia de buscar en tu aplicación sea coherente con la pantalla Inicio.
Establece la propiedad focusOnKeyboardInput del control SearchBox en true para que el cuadro de búsqueda reciba la entrada cuando un usuario escriba.
<div class="searchBox" data-win-control="WinJS.UI.SearchBox" data-win-options="{placeholderText: 'Search', focusOnKeyboardInput: true }"> </div>
En la hoja de estilos default.css que Visual Studio crea automáticamente encontrarás elementos de encabezado y un diseño -ms-grid. Para poner el SearchBox en la esquina superior derecha de la página, basta con agregar este estilo al archivo de Hojas de estilo CSS de la página:
.searchBox { -ms-grid-column: 4; margin-top: 57px; margin-right: 29px; }
Controlar el evento onquerysubmitted
Es probable que la aplicación tenga varios controles SearchBox. Vamos a definir un único controlador de eventos onquerysubmitted que puedan usar todos.
Abre el archivo default.js de tu aplicación.
Crea un controlador de eventos onquerysubmitted denominado "querySubmittedHandler" que tome un único argumento: "args". (Esta definición de método se puede poner en cualquier parte de la función anónima que ajusta el código default.js existente).
function querySubmittedHandler(args) { }
Usa el controlador de eventos para navegar a la nueva página de resultados de búsqueda llamando a WinJS.Navigation.navigate. La propiedad
args.details
contiene un objeto que suministra información sobre el evento que nuestra página de resultados de búsqueda va a necesitar, así que pasa este objeto cuando llames a WinJS.Navigation.navigate.function querySubmittedHandler(args) { WinJS.Navigation.navigate('/pages/search/searchResults.html', args.detail); }
Advertencia Si has creado tu aplicación con la plantilla Aplicación vacía, deberás agregar compatibilidad de navegación a tu aplicación para que la búsqueda funcione. Para dar cabida a la navegación de la misma forma que lo hacen las plantillas Aplicación de cuadrícula, Aplicación dividida y Aplicación de navegación, puedes agregar a tu aplicación un control personalizado llamado
PageControlNavigator
. Puedes ver de qué manera el control personalizado admite la navegación en el tema Inicio rápido: usar la navegación de una página. Si prefieres admitir la navegación sin usar un control personalizado, debes escribir tu propio código que escuche y responda a los eventos de navegación como WinJS.Navigation.navigated. Puedes ver un ejemplo de cómo admitir la navegación sin usar un control personalizado comoPageControlNavigator
en la muestra de navegación e historial de navegación.Ahora tenemos que exponer públicamente este controlador de eventos; para ello, definiremos un espacio de nombres y convertiremos a este controlador en uno de sus miembros. Vamos a llamar al espacio de nombres "SearchUtils". También necesitamos usar el método WinJS.UI.eventHandler para poder establecer el controlador de eventos mediante declaración (si necesitas más información sobre esto, consulta Cómo establecer controladores de eventos de manera declarativa).
WinJS.Namespace.define("SearchUtils", { querySubmittedHandler: WinJS.UI.eventHandler(querySubmittedHandler) } );
Abre la página HTML que contiene el SearchBox. Usa la propiedad data-win-options para establecer el evento onquerysubmitted en
SampleUtils.querySubmittedHandler
.<div class="searchBox" data-win-control="WinJS.UI.SearchBox" data-win-options="{placeholderText: 'Search', focusOnKeyboardInput: true, onquerysubmitted: SearchUtils.querySubmittedHandler}"> </div>
Vamos a probar. Ejecuta la aplicación, escribe una consulta de prueba en el SearchBox y presiona Entrar. Si usas los datos de muestras provistos por Visual Studio, prueba a usar "1" como consulta de prueba.
El controlador de eventos onquerysubmitted que has escrito navega a la página de resultados de búsqueda y pasa la consulta que has escrito.
Si has usado los datos de muestra, deberán aparecer coincidencias en la consulta de prueba. Si has usado tus propios datos, puede que aún no haya resultados. Necesitaremos actualizar antes la página de resultados de la búsqueda, cosa que haremos en un paso posterior.
Buscar en los datos
Ha llegado el momento de volver a la página de resultados de búsqueda. Cuando tu aplicación navega a la página de resultados de búsqueda, uno de los primeros métodos a los que llama es a _handleQuery
. _handleQuery
llama a varios métodos que debemos modificar:
_generateFilters
Genera la lista de filtros que el usuario puede seleccionar para filtrar los resultados.
_searchData
Busca en los datos para encontrar elementos que coincidan y los almacena en una List denominada
originalResults
._populateFilterBar
Muestra los filtros de nuestra lista de filtros.
Pasemos a actualizar estos métodos para personalizarlos acordes a tus datos.
Actualizar los filtros
El método _generateFilters
genera la lista de filtros que el usuario puede seleccionar para filtrar los resultados. El método generado mediante plantilla crea tres filtros: un filtro "All" para mostrar todos los resultados, un filtro para mostrar los elementos del grupo 1 y un filtro para mostrar todo lo demás. Vamos a reemplazar el código generado por la plantilla por el código que genera la lista de filtros dinámicamente. De esa forma, si se cambian los datos de muestra, los nuevos filtros aparecerán en la página. Actualizaremos el código de _generateFilters
y crearemos dos métodos auxiliares. Pero antes, es preciso que actualicemos nuestro archivo data.js para poder acceder a la lista de grupos. Usaremos estos grupos para definir nuestros filtros.
Actualizar el método _generateFilters
En searchResults.js, busca el método
_generateFilters
y elimina el código que contiene.Inicializa la matriz
_filters
(la matriz_filters
es una variable miembro definida por la página de resultados de búsqueda)._generateFilters: function () { this._filters = [];
Ahora, crea un filtro. Un filtro es un objeto que tiene tres propiedades:
results
: una List de los elementos que se van a mostrar. Por el momento, la estableceremos en null.text
: el texto para mostrar del filtro.predicate
: una función que toma un elemento. Si el elemento reúne los criterios del filtro (es decir, si se debe mostrar cuando este filtro se selecciona), esta función devuelve true; si no, devuelve false.
Vamos a crear el filtro "All" antes de nada. El filtro All muestra siempre los elementos, por lo que su
predicate
siempre devuelve true.this._filters.push({ results: null, text: "All", predicate: function (item) { return true; } });
Ahora, vamos a crear un filtro por cada grupo en nuestros datos. Nuestros grupos se almacenan como una List llamada
Data.groups
. Usa el método forEach para iterar por cada grupo de la List. El método forEach toma una función como parámetro. Se llamará a esta función por cada elemento de la lista. Vamos a pasar una función miembro llamada_createFiltersForGroups
. Crearemos la función en el siguiente paso.if (window.Data) { Data.groups.forEach(this._createFiltersForGroups.bind(this)); } },
Ahora vamos a crear la función
_createFiltersForGroups
.Crea una función miembro llamada
_createFiltersForGroups
que toma tres parámetros: element, index y array._createFiltersForGroups: function (element, index, array){
El parámetro element contiene un objeto de grupo. Crea un nuevo objeto de filtro y usa el método de inserción para agregarlo a la matriz
_filters
. Establece la propiedadresults
del filtro en null, su propiedadtext
en element.title
y su propiedadpredicate
en una función llamada_filterPredicate
. Definirás el método_filterPredicate
en el siguiente paso.this._filters.push( { results: null, text: element.title, predicate: this._filterPredicate.bind(element)} ); },
Crea una función miembro llamada
_filterPredicate
que toma un único parámetro llamado item. Devuelve true si la propiedadgroup
del parámetro item es igual que el objeto de grupo actual._filterPredicate: function (item) { return item.group === this; },
Este es el código completo de los tres métodos que acabamos de crear:
_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;
},
Ejecuta la aplicación y haz una búsqueda: los nuevos filtros deberían aparecer en la barra de filtros.
Si usas los datos de muestra generados mediante plantilla, puede que veas que algunos grupos están recortados. Esto se puede solucionar con unos pocos ajustes en el archivo CSS de la página de resultados de búsqueda.
Actualizar el archivo CSS de la página de resultados de búsqueda
Abre searchResults.css.
Busca el estilo
.searchResults section[role=main]
y cambia el valor de la propiedad -ms-grid-rows a "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; }
Busca el estilo
.searchResults section[role=main] .filterbar
, cambia el valor de la propiedad word-wrap a "normal" y establece margin-bottom en "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; }
Busca el estilo
.searchResults section[role=main] .filterbar li
y cambia el valor de la propiedad display a "inline-block"..searchResults section[role=main] .filterbar li { display: inline-block; margin-left: 20px; margin-right: 20px; margin-top: 5px; opacity: 0.6; }
Busca el estilo
.searchResults section[role=main] .resultslist
, cambia el valor de la propiedad -ms-grid-row a "2" y establece -ms-grid-row-span en "1"..searchResults section[role=main] .resultslist { -ms-grid-row: 2; -ms-grid-row-span: 1; height: 100%; position: relative; width: 100%; z-index: 0; }
Ejecuta la aplicación y haz otra búsqueda. Ahora deberías ver todos los elementos.
Actualizar el algoritmo de búsqueda
Con el método _searchData
se busca en los datos aquellos elementos que coincidan con la consulta de búsqueda. El código generado por la plantilla busca el título, subtítulo y descripción de cada elemento. Vamos a escribir nuestro propio código de búsqueda, con el que los resultados se ordenarán por relevancia.
Actualizar el método _searchData
Abre searchResults.js, busca el método
_searchData
y elimina el código que contiene.Crea una variable llamada
originalResults
. Será nuestro valor devuelto.// 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;
En nuestra búsqueda no se distinguirá entre mayúsculas y minúsculas; para ello, pasaremos a minúsculas tanto el texto de la consulta como el texto que vamos a buscar. Empecemos pasando la consulta a minúsculas y almacenándola como una variable llamada
lowercaseQueryText
.// Convert the query to lowercase. var lowercaseQueryText = queryText.toLocaleLowerCase();
Vamos a asegurarnos de que nuestros datos existen antes de intentar acceder a ellos.
if (window.Data) {
Si usas los datos de muestra incluidos en data.js, nuestros elementos se almacenan en
Data.items
, un objeto WinJS.Binding.List. Usa el método createFiltered para filtrar los elementos que no satisfagan la consulta de búsqueda.El método createFiltered toma como parámetro una función de filtrado. Esta función de filtrado toma un único parámetro, item. List llama a esta función en cada elemento de la lista para saber si debe incluirse en la lista filtrada. La función devuelve true si el elemento debe incluirse y false si hay que omitirlo.
originalResults = Data.items.createFiltered( function (item) {
En JavaScript, puedes adjuntar nuevas propiedades a los objetos existentes. Agrega una propiedad
ranking
a item y establece su valor en "-1".// A ranking < 0 means that a match wasn't found. item.ranking = -1;
Primero, vamos a comprobar si el título del elemento contiene el texto de consulta. Si así es, asigna 10 puntos al elemento.
if (item.title.toLocaleLowerCase().indexOf(lowercaseQueryText) >= 0) { item.ranking += 10; }
Tras esto, vamos a ver si hay resultados en el campo de subtítulo. Si encontramos un elemento, le daremos 5 puntos.
if (item.subtitle.toLocaleLowerCase().indexOf(lowercaseQueryText) >= 0) { item.ranking += 5; }
Por último, fijémonos en el campo de descripción. Si hay alguna coincidencia, le daremos 1 punto.
if (item.description.toLocaleLowerCase().indexOf(lowercaseQueryText) >= 0) { item.ranking += 1; }
Si el elemento se ha clasificado con un -1, significa que no ha coincidido con nuestra consulta de búsqueda. Para nuestro valor devuelto, devuelve true si el elemento se ha clasificado como 0 o superior.
return (item.ranking >= 0); } );
Hasta el momento, hemos filtrado la lista a exclusivamente los elementos que coinciden con la consulta de búsqueda y hemos incluido información de clasificación. Ahora, pasemos a usar el método createSorted para ordenar nuestra lista de resultados de forma que los elementos con mayor puntuación aparezcan en primer lugar.
// 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; }); }
Si faltan nuestros datos, crea una lista vacía.
else { // For some reason, the Data namespace is null, so we // create an empty list to return. originalResults = new WinJS.Binding.List(); }
Por último, devuelve los resultados.
return originalResults; }
Este es el código completo del método _searchData
actualizado.
_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;
}
Proporcionar navegación a los elementos devueltos por la búsqueda
Cuando ejecutas tu aplicación y haces una búsqueda, la página de resultados de búsqueda refleja los resultados en un control ListView. Ahora mismo, si hacemos clic en los elementos de resultado de la búsqueda, no pasará nada. Vamos a agregar código para que los elementos se muestren cuando se haga clic en ellos.
Cuando se hace clic en un elemento de una ListView, ListView genera el evento oniteminvoked. El código generado por la plantilla de nuestra página de resultados de búsqueda define un controlador de eventos oniteminvoked denominado _itemInvoked
. Vamos a actualizar este código para navegar al elemento invocado.
Para agregar navegación a los elementos
Abre searchResults.js y agrega código a la función
_itemInvoked
para navegar a la página correcta. Precaución El URI que se muestra aquí corresponde a la plantilla Hub. Para la plantilla Grid, el URI debe ser: /pages/itemDetail/itemDetail.html. Para la plantilla Split, la URL debe ser: /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 }); }); },
(Opcional) Actualizar el elemento itemTemplate del control ListView
La página de resultados de búsqueda generada por la plantilla define una itemTemplate que está diseñada para funcionar con el origen de datos de muestra que Visual Studio crea automáticamente. Esta página espera encontrar los siguientes campos en cada elemento de datos: "image", "title", "subtitle" y "description".
Si los elementos de datos tienen otros campos, deberás modificar el elemento itemTemplate. Para obtener instrucciones, consulta Inicio rápido: Agregar ListView.
(Opcional) Agregar sugerencias de búsqueda
Las sugerencias de búsqueda se muestran en el cuadro de búsqueda, en el panel de búsqueda. Las sugerencias son importantes porque permiten que los usuarios ahorren tiempo y, además, les ofrecen pistas importantes sobre el tipo de cosas que pueden buscar en tu aplicación.
Puedes obtener sugerencias de distintos orígenes:
- Puedes definirlas tú mismo. Por ejemplo, podrías crear una lista de fabricantes de automóviles.
- Puedes obtenerlas de Windows si tu aplicación busca en archivos locales.
- Puedes obtenerlas de un servidor o servicio web.
Para obtener directrices sobre la experiencia del usuario para mostrar sugerencias, consulta Directrices y lista de comprobación de búsqueda.
También puedes usar LocalContentSuggestionSettings para agregar sugerencias (basadas en los archivos locales de Windows) en unas pocas líneas de código. Otra opción consiste en registrarse en el evento onsuggestionsrequested del control de cuadro de búsqueda y crear tu propia lista de sugerencias, compuesta por sugerencias que recuperaste de otro origen (por ejemplo, una lista definida localmente o un servicio web). Esta guía de inicio rápido te muestra cómo controlar el evento onsuggestionsrequested.
Para ver más ejemplos de código que muestran cómo agregar sugerencias de búsqueda, descarga la muestra del control SearchBox. La muestra ilustra cómo agregar sugerencias de búsqueda mediante los tres orígenes posibles y cómo agregar sugerencias para idiomas de Asia oriental con formatos alternativos del texto de la consulta generado por un editor de métodos de entrada (IME). (Recomendamos el uso de alternativas de texto si la aplicación la van a utilizar usuarios japoneses o chinos).
Controlar el evento SuggestionsRequested
Es probable que tu aplicación tenga varios controles SearchBox; vamos a definir un único controlador de eventos en el archivo default.js que puedan usar todos. Agrega este código después del método
querySubmittedHandler
que creaste en uno de los pasos anteriores.function suggestionsRequestedHandler(args) {
Pasa el texto de consulta de SearchBox a minúsculas.
var query = args.detail.queryText.toLocaleLowerCase();
El sistema ofrece automáticamente algunas sugerencias, como, por ejemplo, búsquedas anteriores que ha realizado el usuario. Vamos a agregar nuestras sugerencias de búsqueda a lo que proporcione el sistema.
// Retrieve the system-supplied suggestions. var suggestionCollection = args.detail.searchSuggestionCollection;
Comprueba que la consulta contiene como mínimo un carácter y que tenemos acceso a nuestros datos.
if (query.length > 0 && window.Data) {
Procesa una iteración en cada elemento de los datos para buscar coincidencias. Cuando encontremos una coincidencia, asocia el título del elemento coincidente a la colección de sugerencias de búsqueda.
Data.items.forEach( function (element, index, array) { if (element.title.substr(0, query.length).toLocaleLowerCase() === query) { suggestionCollection.appendQuerySuggestion(element.title); } });
La propiedad
args.detail.linguisticDetails.queryTextAlternatives
proporciona sugerencias adicionales para usuarios que escriben texto en un IME. El uso de estas sugerencias mejora la experiencia de búsqueda para los usuarios de idiomas de Asia oriental. Vamos a comprobar las alternativas de texto de consulta para cadenas que contienen la consulta original y agregarlas a nuestra lista de sugerencias de búsqueda.args.detail.linguisticDetails.queryTextAlternatives.forEach( function (element, index, array) { if (element.substr(0, query.length).toLocaleLowerCase() === query) { suggestionCollection.appendQuerySuggestion(element); } }); } }
Ese es todo el código que necesitamos para nuestro controlador de eventos de sugerencias de búsqueda. Este es el método
suggestionsRequestedHandler
completo: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); } }); } }
Nota Si el origen de datos es asincrónico, debes encapsular actualizaciones en la colección de sugerencias de búsqueda en una Promise. En el ejemplo de código se usa una List, que es un origen de datos sincrónico, pero así sería el método si List fuera un origen de datos asincrónico.
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); } }); }) ); } }
Ese es todo el código que necesitamos para nuestro controlador de eventos de sugerencias de búsqueda. Vamos a hacer que sea accesible públicamente; para ello, lo expondremos por medio del espacio de nombres
SearchUtils
que definimos en uno de los pasos anteriores:WinJS.Namespace.define("SearchUtils", { querySubmittedHandler: WinJS.UI.eventHandler(querySubmittedHandler), suggestionsRequestedHandler: WinJS.UI.eventHandler(suggestionsRequestedHandler) } );
Ahora vamos a registrar el evento con nuestro SearchBox. Abre la página HTML que contiene el SearchBox y establece el evento onsuggestionsrequested en
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>
Implementar el contrato de Buscar (para versiones anteriores de Windows)
Antes de la aparición de Windows 8.1, las aplicaciones hacían uso del acceso a Buscar para proporcionar la función de búsqueda en la aplicación. Los desarrolladores implementaban el contrato de Buscar y usaban la API SearchPane para controlar las consultas y obtener sugerencias y resultados.
Si bien el contrato de Buscar de Windows 8 y la API de SearchPane siguen siendo plenamente compatibles, desde la aparición de Windows 8.1 recomendamos usar el control SearchBox del SearchPane. Las aplicaciones que usan el SearchBox no tienen la necesidad de implementar el contrato de Buscar.
¿Debe usar alguna vez una aplicación el SearchPane y el contrato de Buscar? Si no esperas que los usuarios realicen muchas búsquedas en tu aplicación, puedes usar el SearchPane y el contrato de Buscar. Te recomendamos usar un botón con el glifo de búsqueda (Segoe UI Symbol 0xE0094 en 15 pt) en la aplicación, en el cual pueden hacer clic los usuarios para activar el panel de búsqueda. Para ver código que implementa el SearchPane y el contrato de Buscar, consulta la Muestra del contrato de Buscar.
Resumen y siguientes pasos
Has usado el control SearchBox y la Página de resultados de búsqueda para agregar la búsqueda a tu aplicación.
Para consultar las directrices que te ayudarán a diseñar y crear una buena experiencia de búsqueda para los usuarios, consulta Directrices y lista de comprobación de búsqueda.