Démarrage rapide : ajout d’une fonctionnalité de recherche à une application (HTML)

[ Cet article est destiné aux développeurs de Windows 8.x et Windows Phone 8.x qui créent des applications Windows Runtime. Si vous développez une application pour Windows 10, voir la Documentation ]

La plupart des utilisateurs comptent sur la fonctionnalité de recherche pour trouver ce dont ils ont besoin. Par exemple, si votre application lit des fichiers multimédias, les utilisateurs souhaitent pouvoir être en mesure de rechercher une chanson ou une vidéo spécifique. De même, si vous proposez une application de cuisine, ils s’attendent à pouvoir rechercher des recettes ou des ingrédients spécifiques.

Moyennant quelques efforts de planification, l’ajout d’une fonctionnalité de recherche à votre application n’est pas une tâche si difficile que cela. Voici ce dont vous avez besoin :

  • Une source de données dans laquelle les recherches seront effectuées. Vous avez besoin d’une sorte de catalogue ou d’inventaire d’éléments que les utilisateurs pourront interroger. Plus cet inventaire est descriptif, plus les résultats de la recherche seront précis.
  • Un contrôle pour entrer les requêtes de recherche. Windows fournit un contrôle SearchBox que votre application peut utiliser. Le contrôle SearchBox fournit une zone de saisie pour entrer des requêtes, un bouton de recherche pour lancer la recherche, ainsi que des événements pour traiter les requêtes de recherche. Il fournit même automatiquement des suggestions de recherche.
  • Une page pour afficher les résultats de la recherche. Microsoft Visual Studio fournit le modèle Page des résultats de recherche qui crée une bonne partie du code dont vous avez besoin pour traiter les requêtes de recherche et afficher les résultats.

Ce démarrage rapide vous explique comment utiliser ces éléments pour ajouter une fonctionnalité de recherche à votre application.

Voir cette fonctionnalité appliquée dans notre série Fonctionnalités d’application de A à Z: Interface utilisateur des applications du Windows Store de A à Z

Prérequis

Configurer vos données

Lorsque l’utilisateur entre une requête de recherche, votre application recherche les éléments contenus dans la requête de l’utilisateur. Les données qui font l’objet d’une recherche peuvent se présenter sous plusieurs formes : un fichier XML, des données JSON (JavaScript Object Notation), une base de données, un service Web ou encore des fichiers dans le système de fichiers.

Les exemples fournis dans ce démarrage rapide utilisent les exemples de données générés par Microsoft Visual Studio lorsque vous créez un projet dans Microsoft Visual Studio.

Lorsque vous utilisez Visual Studio pour créer une application grille, une application de concentrateur ou une application fractionnée, il crée un fichier nommé data.js dans le dossier js de votre application. Ce fichier contient des données statiques que vous pouvez remplacer par vos propres données Par exemple, si votre application effectue une seule demande xhr pour obtenir des données RSS ou JSON, vous voudrez peut-être ajouter votre code dans le fichier data.js. Vous pourrez ainsi facilement utiliser vos propres données sans modifier le modèle de données utilisé par la Page des résultats de recherche.

Voici à quoi ressemble l’exemple de données :

function generateSampleData() {
    // . . .
    var sampleGroups = [
        { key: "group1", title: "Group Title: 1", // . . .
        // . . .
    ];

    var sampleItems = [
        { group: sampleGroups[0], title: "Item Title: 1", // . . .
        // . . .
    ];

    return sampleItems;
}

Pour rendre ces données accessibles à vos fichiers, le fichier data.js définit un espace de noms Data qui expose les membres suivants :

  • items : un objet WinJS.Binding.List qui contient les éléments de données. Il s’agit d’un objet List groupé.
  • groups : un objet WinJS.Binding.List qui contient les groupes auxquels les éléments de données appartiennent. (Vous pouvez également obtenir ces groupes en appelant items.groups.)
  • getItemReference : récupère un objet qui contient la clé du groupe et le titre de l’élément spécifié.
  • getItemsFromGroup : récupère un objet FilteredListProjection qui contient les éléments appartenant au groupe avec la clé spécifiée.
  • resolveGroupReference : récupère un objet qui représente le groupe ayant la clé spécifiée.
  • resolveItemReference : cette méthode utilise un tableau contenant deux chaînes, à savoir une clé de groupe et un titre. Elle récupère l’élément ayant le clé de groupe et le titre spécifiés.

Vous n’êtes pas obligé d’utiliser cet espace de noms ou ces membres pour spécifier vos données, mais cela facilite l’utilisation du modèle Page des résultats de recherche.

(Pour plus d’informations sur l’utilisation des données générées par le modèle, voir Comment personnaliser des données de modèle Visual Studio.)

Ajouter une page Résultats de la recherche

La page Résultats de la recherche traite les requêtes de recherche et affiche le résultat. Ajoutons-en une à votre projet. (Ces instructions partent du principe que votre projet a été créé à partir du modèle Hub, Grille ou Fractionner. )

Hh465238.wedge(fr-fr,WIN.10).gifAjouter l’élément Page Résultats de la recherche

  1. Dans le dossier de projet pages de l’Explorateur de solutions, ajoutez un nouveau dossier nommé search.

  2. Ouvrez le menu contextuel du dossier search, puis choisissez Ajouter > Nouvel élément.

  3. Dans le volet central de la boîte de dialogue Ajouter un nouvel élément, choisissez Page Résultats de la recherche. Pour cet exemple, conservez le nom par défaut, searchResults.html, qui apparaît dans la zone Nom.

  4. Choisissez Ajouter.

    Visual Studio ajoute searchResults.html, searchResults.css et searchResults.js au projet dans le nouveau dossier search.

Nous avons encore du travail à faire sur la page des résultats de recherche, mais avant de continuer, nous allons ajouter un contrôle SearchBox à notre application. Le fait d’avoir un contrôle SearchBox nous permet de tester plus facilement notre page des résultats de recherche au fur et à mesure de son implémentation.

Un contrôle SearchBox permet aux utilisateurs d’entrer des requêtes. Il peut également afficher des suggestions. Pour ajouter un contrôle SearchBox à votre application, il suffit d’ajouter ce balisage à une page HTML :

<div class="searchBox"
    data-win-control="WinJS.UI.SearchBox"
    data-win-options="{placeholderText: 'Search'}">
</div>

(Vous devez également vous inscrire à l’événementonquerysubmitted. Nous le ferons plus loin.)

Où placer votre zone de recherche ? Nous vous recommandons de placer une zone de recherche dans chaque page de votre application afin que les utilisateurs puissent facilement lancer une recherche quand bon leur semble. Si vous manquez d’espace, vous pouvez positionner la zone de recherche dans une barre d’applications en haut de l’écran.

Hh465238.wedge(fr-fr,WIN.10).gifAjouter un contrôle SearchBox à votre page

  1. Nous allons ajouter un contrôle SearchBox à l’une des pages de votre application. Ces instructions vaudront pour toute page reposant sur un contrôle Page.

    Dans l’idéal, placez le contrôle SearchBox dans le coin supérieur droit de la page. La plupart des pages que vous créez à partir d’un modèle Visual Studio (comme le modèle Contrôle de page) possèdent un élément header contenant le titre de la page et un bouton Précédent :

            <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>
    

    Ajoutez tout simplement votre contrôle SearchBox après l’élément 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>
    
  2. (Recommandé) Vous devez permettre à vos utilisateurs de rechercher du contenu dans votre application à l’aide d’une simple saisie au clavier qui lance automatiquement la recherche.

    De nombreuses personnes passent par le clavier pour interagir avec Windows 8. Leur offrir la possibilité de rechercher en tapant permet un usage effectif de l’interaction au clavier et rend l’expérience de recherche de votre application cohérente avec celle que l’on retrouve dans l’écran d’accueil.

    Affectez à la propriété focusOnKeyboardInput du contrôle SearchBox la valeur true pour que la zone de recherche reçoive en entrée la saisie de l’utilisateur.

                <div class="searchBox"
                     data-win-control="WinJS.UI.SearchBox"
                     data-win-options="{placeholderText: 'Search',
                     focusOnKeyboardInput: true }">
                </div>
    
  3. La feuille de style default.css créée pour vous par Visual Studio applique la disposition -ms-grid aux éléments d’en-tête. Pour placer le contrôle SearchBox dans l’angle supérieur droit de la page, ajoutez simplement ce style au fichier CSS (Cascading Style Sheets) de votre page :

    .searchBox {
        -ms-grid-column: 4;
        margin-top: 57px;
        margin-right: 29px;
    }
    

Hh465238.wedge(fr-fr,WIN.10).gifGérer l’événement onquerysubmitted

  1. Il est probable que votre application contiendra plusieurs contrôles SearchBox. Nous devons donc définir un gestionnaire d’événements onquerysubmitted unique que tous pourront utiliser.

    Ouvrez le fichier default.js de votre application.

  2. Créez un gestionnaire d’événements onquerysubmitted nommé "querySubmittedHandler" qui prend un argument unique nommé "args". (Vous pouvez placer cette définition de méthode n’importe où à l’intérieur de la fonction anonyme qui inclut le code default.js existant.)

        function querySubmittedHandler(args) {
    
        }
    
  3. Utilisez le gestionnaire d’événements pour naviguer vers votre nouvelle page des résultats de recherche en appelant WinJS.Navigation.navigate La propriété args.details contient un objet qui fournit des informations sur l’événement dont notre page des résultats de recherche aura besoin. Cet objet doit donc être passé lorsque vous appelez WinJS.Navigation.navigate.

        function querySubmittedHandler(args) {
            WinJS.Navigation.navigate('/pages/search/searchResults.html', args.detail);
        }
    

    Avertissement  Si vous avez créé votre application à l’aide du modèle Application vide, vous devez ajouter la prise en charge de la navigation à votre application pour que la recherche puisse fonctionner. Vous pouvez prendre en charge la navigation de la même manière que dans les modèles Grille, Fractionner et Application de navigation, en ajoutant un contrôle personnalisé nommé PageControlNavigator à votre application. Pour savoir comment ce contrôle personnalisé prend en charge la navigation, voir Démarrage rapide : utilisation de la navigation sur une seule page. Si vous préférez prendre en charge la navigation sans utiliser de contrôle personnalisé, vous devez écrire votre propre code, lequel écoute les événements de navigation comme WinJS.Navigation.navigated et y répond. Vous pouvez voir un exemple de prise en charge de la navigation sans utiliser de contrôle personnalisé comme PageControlNavigator dans l’exemple de navigation et d’historique de navigation.

     

  4. Nous devons maintenant exposer publiquement ce gestionnaire d’événements en définissant un espace de noms dont le gestionnaire sera un membre. Commençons par appeler l’espace de noms "SearchUtils". Nous devons également utiliser la méthode WinJS.UI.eventHandler pour définir le gestionnaire d’événements de façon déclarative (pour plus d’informations, voir Comment définir des gestionnaires d’événements de façon déclarative).

        WinJS.Namespace.define("SearchUtils",
        {
            querySubmittedHandler: WinJS.UI.eventHandler(querySubmittedHandler)
        }
        );
    
  5. Ouvrez la page HTML contenant votre contrôle SearchBox. Utilisez la propriété data-win-options pour définir l’événement onquerysubmitted sur SampleUtils.querySubmittedHandler.

                <div class="searchBox"
                     data-win-control="WinJS.UI.SearchBox"
                     data-win-options="{placeholderText: 'Search',
                     focusOnKeyboardInput: true,
                     onquerysubmitted: SearchUtils.querySubmittedHandler}">
                </div>
    

Faisons un essai. Exécutez l’application, tapez une requête test dans le contrôle SearchBox et appuyez sur Entrée. Si vous utilisez l’exemple de données fourni par Visual Studio, tapez "1" comme requête test.

Requête test

Le gestionnaire d’événements onquerysubmitted que vous avez écrit navigue vers la page des résultats de recherche en passant la requête que vous avez entrée.

Résultats de la requête test

Si vous utilisez l’exemple de données, votre requête test doit trouver des correspondances. Si vous utilisez vos propres données, il est possible que vous n’obteniez pas de résultats. Nous devrons alors commencer par mettre à jour la page des résultats de recherche. Nous verrons cela plus loin.

Rechercher vos données

Il est temps de revenir à notre page des résultats de recherche. Lorsque votre application navigue vers la page des résultats de recherche, l’une des premières méthodes qu’elle appelle est la méthode _handleQuery. _handleQuery appelle plusieurs méthodes que nous devons modifier :

  1. _generateFilters

    Génère la liste des filtres que l’utilisateur peut appliquer pour filtrer les résultats.

  2. _searchData

    Recherche des éléments correspondants dans vos données et les stocke dans un objet List nommé originalResults.

  3. _populateFilterBar

    Affiche les filtres de notre liste de filtres.

Nous allons maintenant personnaliser ces méthodes pour vos données.

Mettre à jour les filtres

La méthode _generateFilters génère la liste des filtres que l’utilisateur peut appliquer pour filtrer les résultats. La méthode générée par le modèle crée trois filtres : un filtre « Tous » qui affiche tous les résultats, un filtre qui affiche les éléments dans le groupe 1 et un filtre affichant tout le reste. Remplaçons le code généré par le modèle par un code qui génère la liste de filtres de façon dynamique. De cette manière, si vous changez l’exemple de données, vos nouveaux filtres apparaîtront sur la page. Nous allons mettre à jour le code _generateFilters et créer deux méthodes d’assistance. Mais avant, nous devons mettre à jour notre fichier data.js pour pouvoir accéder à la liste des groupes. Nous utilisons ces groupes pour définir nos filtres.

Hh465238.wedge(fr-fr,WIN.10).gifMettre à jour la méthode _generateFilters.

  1. Dans searchResults.js, recherchez la méthode _generateFilters et supprimez le code qu’elle contient.

  2. Initialisez le tableau _filters. (Le tableau _filters est une variable membre définie par la page des résultats de recherche.)

    
            _generateFilters: function () {
                this._filters = [];
    
  3. Nous allons maintenant créer un filtre. Un filtre est un objet ayant trois propriétés :

    • results : une List des éléments à afficher. Nous allons pour le moment la définir sur null.
    • text : texte d’affichage du filtre.
    • predicate : une fonction qui prend un élément. Si l’élément répond aux critères de filtre (autrement dit, s’il doit être affiché lorsque ce filtre est sélectionné), cette fonction renvoie la valeur true ; sinon, elle renvoie la valeur false.

    Commençons par créer le filtre « Tous ». Ce filtre affiche toujours des éléments, sa fonction predicate renvoie dont toujours la valeur true.

    
                this._filters.push({ results: null, text: "All", predicate: function (item) { return true; } });
    
  4. Créons maintenant un filtre pour chaque groupe présent dans nos données. Nos groupes sont stockés sous la forme d’une List nommée Data.groups. Utilisez la méthode forEach pour itérer au sein de chaque groupe de la List. La méthode forEach prend une fonction comme paramètre. Cette fonction est appelée pour chaque élément de la liste. Nous allons maintenant lui passer une fonction membre appelée _createFiltersForGroups. Nous créerons cette fonction à l’étape suivante.

                if (window.Data) {
                    Data.groups.forEach(this._createFiltersForGroups.bind(this));
                }
            },
    
  5. Créons maintenant la fonction _createFiltersForGroups.

    1. Créez une fonction membre nommée _createFiltersForGroups qui accepte trois paramètres : element, index et array.

              _createFiltersForGroups: function (element, index, array){
      
      
    2. Le paramètre element contient notre objet de groupe. Créez un objet filtre et ajoutez-le au tableau _filters à l’aide de la méthode Push. Affectez la valeur null à la propriété results du filtre, la valeur element.title à sa propriété text et une fonction nommée _filterPredicate à sa propriété predicate. Vous allez définir la méthode _filterPredicate à l’étape suivante.

                  this._filters.push(
                      { results: null, text: element.title, predicate: this._filterPredicate.bind(element)}
                      );
              },
      
    3. Créez une fonction membre nommée _filterPredicate qui accepte un seul paramètre nommé item. Retournez la valeur true si la propriété group du paramètre item est égale à l’objet de groupe actuel.

              _filterPredicate: function (item) {
      
                  return item.group === this;          
              },
      

Voici le code complet des trois méthodes que nous venons de créer :

        _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;          
        },

Exécutez l’application et effectuez une recherche. Vous devez voir vos nouveaux filtres dans la barre de filtre.

La liste des filtres mise à jour

Si vous utilisez l’exemple de données généré par le modèle, vous pouvez noter que certains groupes sont tronqués. Vous pouvez résoudre ce problème en apportant quelques modifications au fichier CSS de votre page des résultats de recherche.

Hh465238.wedge(fr-fr,WIN.10).gifMettre à jour le fichier CSS de la page des résultats de recherche

  1. Ouvrez searchResults.css.

  2. Recherchez le style .searchResults section[role=main] et remplacez la valeur de la propriété -ms-grid-rows par "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;
    }
    
  3. Recherchez le style .searchResults section[role=main] .filterbar et remplacez la valeur de la propriété word-wrap par "normal". Définissez la propriété margin-bottomsur "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; 
        }
    
  4. Recherchez le style .searchResults section[role=main] .filterbar li et remplacez la valeur de la propriété display par "inline-block".

            .searchResults section[role=main] .filterbar li {
                display: inline-block; 
                margin-left: 20px;
                margin-right: 20px;
                margin-top: 5px;
                opacity: 0.6;
            }
    

    .

  5. Recherchez le style .searchResults section[role=main] .resultslist et remplacez la valeur de la propriété -ms-grid-row par "2". Définissez la propriété -ms-grid-row-spansur "1".

        .searchResults section[role=main] .resultslist {
            -ms-grid-row: 2;
            -ms-grid-row-span: 1;
            height: 100%;
            position: relative;
            width: 100%;
            z-index: 0;
        }
    

Exécutez l’application et effectuez une autre recherche. Vous devez désormais voir tous les filtres.

La liste des filtres mise à jour

Mettre à jour l’algorithme de recherche

La méthode _searchData recherche dans les données les éléments répondant à la requête de recherche. Le code généré par le modèle effectue la recherche dans le titre, le sous-titre et la description de chaque élément. Nous allons écrire notre propre code qui classe les résultats par pertinence.

Hh465238.wedge(fr-fr,WIN.10).gifMettre à jour la méthode _searchData.

  1. Ouvrez le fichier searchResults.js, recherchez la méthode _searchData et supprimez le code qu’elle contient.

  2. Créez une variable nommée originalResults. Il s’agira de notre valeur de retour.

            // 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;
    
  3. Rendons notre recherche insensible à la casse en convertissant le texte de la requête et le texte affiché en minuscules. Commençons par convertir la requête en minuscules et la stocker sous la forme d’une variable nommée lowercaseQueryText.

                // Convert the query to lowercase. 
                var lowercaseQueryText = queryText.toLocaleLowerCase();
    
  4. Avant d’essayer d’accéder à nos données, vérifions qu’elles existent.

                if (window.Data)
                {
    
  5. Si vous utilisez l’exemple de données fourni dans data.js, nos éléments sont alors stockés dans Data.items, un objet WinJS.Binding.List. Utilisez la méthode createFiltered pour filtrer les éléments qui ne répondent pas à la requête de recherche.

    La méthode createFiltered prend comme paramètre une fonction de filtrage. Cette fonction ne prend qu’un paramètre, item. La List appelle cette fonction sur chaque élément de la liste pour déterminer s’il doit figurer dans la liste filtrée. La fonction renvoie true si l’élément doit être inclus et false s’il doit être ignoré.

                    originalResults = Data.items.createFiltered(
    
                        function (item) {
    
  6. Dans JavaScript, vous pouvez attacher de nouvelles propriétés à des objets existants. Ajoutez une propriété ranking à item et affectez-lui la valeur "-1".

                            // A ranking < 0 means that a match wasn't found. 
                            item.ranking = -1;
    
  7. Vérifions d’abord si le titre de l’élément contient le texte de la requête. Si c’est le cas, attribuons 10 points à cet élément.

                            if (item.title.toLocaleLowerCase().indexOf(lowercaseQueryText) >= 0) {
    
                                item.ranking += 10;
                            }
    
  8. Faisons ensuite la même chose dans le sous-titre. S’il y a correspondance, attribuons 5 points à cet élément.

                            if (item.subtitle.toLocaleLowerCase().indexOf(lowercaseQueryText) >= 0) {
                                item.ranking += 5;
                            }
    
  9. Enfin, vérifions le champ de description. En cas de correspondance, attribuons 1 points à cet élément.

                            if (item.description.toLocaleLowerCase().indexOf(lowercaseQueryText) >= 0) {
                                item.ranking += 1;
                            }
    
  10. Si l’élément a un classement de -1, cela signifie qu’il ne correspondait pas à notre requête de recherche. Pour notre valeur de retour, renvoyez true si l’élément à un classement supérieur ou égal à 0.

                            return (item.ranking >= 0);
                        }
                     );
    
  11. Jusque-là, nous avons réduit la liste aux seuls éléments qui correspondaient à la requête de recherche et nous avons ajouté des informations de classement. Nous allons maintenant utiliser la méthode createSorted pour trier notre liste de résultats afin que les éléments totalisant le plus de points apparaissent en premier.

                    // 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;
                        });
    
                }
    
  12. Si nos données sont manquantes, créez une liste vide.

                else {
    
                    // For some reason, the Data namespace is null, so we 
                    // create an empty list to return. 
                    originalResults = new WinJS.Binding.List();
    
                }
    
  13. Enfin, renvoyez les résultats.

                return originalResults;
            }
    

Voici le code complet de la méthode _searchData mise à jour :

        _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;
        }

Fournir la navigation aux éléments renvoyés par la recherche

Lorsque vous exécutez votre application et effectuez une recherche, la page des résultats de recherche affiche les résultats dans un contrôle ListView. Pour le moment, rien ne se passe lorsque vous cliquez sur un élément des résultats de recherche. Nous allons ajouter du code permettant d’afficher l’élément lorsque l’utilisateur clique dessus.

Lorsque l’utilisateur clique sur un élément dans un contrôle ListView, ListView déclenche l’événement oniteminvoked. Le code généré par le modèle pour notre page des résultats de recherche définit un gestionnaire d’événements oniteminvoked nommé _itemInvoked. Nous allons mettre jour le code de manière à naviguer vers l’élément appelé.

Hh465238.wedge(fr-fr,WIN.10).gifPour ajouter la navigation vers des éléments

  • Ouvrez searchResults.js et ajoutez du code à la fonction _itemInvoked pour naviguer vers la page adéquate. Attention  L’URI indiqué ici correspond au modèle Hub. Pour le modèle Grille, l’URI doit être : /pages/itemDetail/itemDetail.html. Pour le modèle Fractionner, l’URI doit être : /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 });
                });
            },
    

(Facultatif) Mettre à jour la propriété itemTemplate du contrôle ListView

La page des résultats de recherche générée par le modèle définit une propriété itemTemplate qui est conçue pour fonctionner avec l’exemple de source de données créé pour vous par Visual Studio. Les champs suivants sont attendus dans chaque élément de données : "image", "title", "subtitle" et "description".

Si vos éléments de données ont des champs différents, vous devez modifier la propriété itemTemplate. Pour obtenir des instructions, voir Démarrage rapide : ajout d’un contrôle ListView.

(Facultatif) Ajouter des suggestions de recherche

Les suggestions de recherche sont affichées sous la zone de recherche dans le volet de recherche. Les suggestions s’avèrent importantes, car elles permettent aux utilisateurs de gagner du temps. En outre, elles leur fournissent des indications utiles sur la nature des recherches que les utilisateurs peuvent effectuer dans votre application.

Il est possible d’obtenir des suggestions depuis plusieurs sources :

  • vous pouvez les définir vous-même. Par exemple, vous pouvez créer une liste de constructeurs de voitures.
  • Vous avez la possibilité de les obtenir depuis Windows si votre application recherche parmi des fichiers en local.
  • Il vous est possible de les tirer d’un service Web ou d’un serveur.

Pour obtenir des recommandations en matière d’expérience utilisateur sur l’affichage de suggestions, voir Recommandations et liste de vérification sur la recherche.

Vous pouvez utiliser LocalContentSuggestionSettings pour ajouter des suggestions basées sur les fichiers locaux de Windows, en quelques lignes de code seulement. Vous pouvez également inscrire l’événement onsuggestionsrequested du contrôle zone de recherche et créer votre propre liste de suggestions. Il s’agit des suggestions que vous avez récupérées à partir d’une autre source, par exemple une liste définie localement ou un service Web. Ce démarrage rapide montre comment gérer l’événement onsuggestionsrequested.

Pour obtenir des exemples de code qui vous montrent comment ajouter des suggestions de recherche, téléchargez l’exemple de contrôle SearchBox. Il montre comment ajouter des suggestions de recherche à l’aide des trois sources possibles. Il montre également comment ajouter des suggestions pour les langues asiatiques en utilisant d’autres formes du texte de requête générées par un Éditeur de méthode d’entrée (IME). (Nous vous recommandons d’utiliser d’autres formes du texte de requête si votre application sera utilisée par des utilisateurs japonais ou chinois.)

Hh465238.wedge(fr-fr,WIN.10).gifGérer l’événement SuggestionsRequested

  1. Il est probable que votre application possède plusieurs contrôles SearchBox. Nous allons donc définir un gestionnaire d’événements unique dans votre fichier default.js qu’ils peuvent tous utiliser. Ajoutez ce code à la suite de la méthode querySubmittedHandler que vous avez créée à l’étape précédente.

        function suggestionsRequestedHandler(args) {
    
  2. Convertissez le texte de requête du contrôle SearchBox en minuscules.

            var query = args.detail.queryText.toLocaleLowerCase();
    
  3. Le système fournit automatiquement des suggestions de recherche, notamment les recherches précédentes effectuées par l’utilisateur. Ajoutons nos suggestions de recherche aux éléments fournis par le système.

            // Retrieve the system-supplied suggestions.
            var suggestionCollection = args.detail.searchSuggestionCollection;
    
  4. Vérifiez que la requête contient au moins un caractère et que nous avons accès à nos données.

            if (query.length > 0 && window.Data) {
    
  5. Itérez au sein de chaque élément de vos données et vérifiez la présence de correspondances. Lorsque nous trouvons une correspondance, ajoutez le titre de l’élément correspondant à la collection de suggestions de la recherche.

                Data.items.forEach(
                    function (element, index, array) {
                        if (element.title.substr(0, query.length).toLocaleLowerCase() === query) {
                            suggestionCollection.appendQuerySuggestion(element.title);
                        }
    
                    });
    
  6. La propriété args.detail.linguisticDetails.queryTextAlternatives fournit des suggestions supplémentaires pour les utilisateurs qui entrent du texte dans un IME. L’utilisation de ces suggestions améliore l’expérience de recherche pour les utilisateurs parlant des langues d’Asie orientale. Vérifions dans les autres formes du texte de requête la présence de chaînes qui contiennent la requête d’origine et ajoutons-les à notre liste de suggestions de recherche.

                args.detail.linguisticDetails.queryTextAlternatives.forEach(
                    function (element, index, array) {
                        if (element.substr(0, query.length).toLocaleLowerCase() === query) {
                            suggestionCollection.appendQuerySuggestion(element);
                        }
    
                    });
            }
        }
    

    Voilà à quoi se résume le code dont nous avons besoin pour notre gestionnaire d’événements de suggestions de recherche. Voici la méthode suggestionsRequestedHandler dans son intégralité :

        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);
                        }
    
                    });
    
            }
        }
    

    Remarque  Si votre source de données est asynchrone, vous devez insérer les mises à jour apportées à la collection de suggestions de recherche dans un objet Promise. L’exemple de code utilise un objet List, qui est une source de données synchrone, mais voici ce à quoi ressemblerait la méthode si List était une source de données asynchrone.

     

        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);
                                }
    
                            });
    
                    })
                 );
            }
        }
    
  7. Voilà à quoi se résume le code dont nous avons besoin pour notre gestionnaire d’événements de suggestions de recherche. Nous allons maintenant le rendre publiquement accessible en l’exposant via l’espace de noms SearchUtils que nous avons défini précédemment :

        WinJS.Namespace.define("SearchUtils",
        {
            querySubmittedHandler: WinJS.UI.eventHandler(querySubmittedHandler),
            suggestionsRequestedHandler: WinJS.UI.eventHandler(suggestionsRequestedHandler)
        }
        );
    
  8. Nous allons à présent enregistrer l’événement avec notre contrôle SearchBox. Ouvrez la page HTML contenant votre contrôle SearchBox et définissez l’événement onsuggestionsrequestedsur 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>
    

Implémentation du contrat de recherche (pour les versions précédentes de Windows)

Dans les versions antérieures à Windows 8.1, les applications utilisaient l’icône Rechercher pour fournir une recherche dans l’application. Les développeurs ont implémenté le contrat de recherche et utilisé l’API SearchPane pour gérer les requêtes et obtenir des suggestions et des résultats.

Même si nous continuons à prendre totalement en charge le contrat de recherche Windows 8 et l’API SearchPane, à compter de Windows 8.1, il est recommandé d’utiliser le contrôle SearchBox à la place de la classe SearchPane. Les applications qui utilisent le contrôle SearchBox n’ont pas besoin d’implémenter le contrat de recherche.

Dans quels cas une application peut-elle utiliser la classe SearchPane et le contrat de recherche ? Si vous prévoyez que les utilisateurs n’utiliseront pas beaucoup la fonctionnalité de recherche dans votre application, vous pouvez utiliser la classe SearchPane et le contrat de recherche. Nous vous recommandons d’utiliser dans votre application un bouton avec le glyphe Rechercher (Segoe UI Symbol 0xE0094, 15pt) sur lequel les utilisateurs peuvent cliquer pour activer le volet de recherche. Pour examiner le code qui implémente la classe SearchPane et le contrat de recherche, voir l’Exemple de contrat de recherche.

Récapitulatif et étapes suivantes

Vous avez utilisé le contrôle SearchBox et la page des résultats de recherche pour ajouter une fonctionnalité de recherche à votre application.

Pour obtenir des recommandations sur la conception et la création d’une expérience utilisateur réussie en matière de recherche, voir Recommandations et liste de vérification sur la recherche.

Rubriques associées

Exemple de contrôle SearchBox

Recommandations et liste de vérification sur la recherche