[jquery] Recherche dynamique en javascript

Il arrive souvent quand nous développons un site internet que nous ayons à faire une recherche dynamique dans une page ou dans une liste. Nous allons voir, ici, comment mettre en place un tel comportement à l’aide de JQuery.

Objectif

Nous allons utiliser pour les besoins de cet article une page HTML simple : une zone de texte, qui nous permettra de faire une recherche, et une liste d’éléments. Voici donc notre page HTML.

<!DOCTYPE HTML>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>DropDown List example</title>
  <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
  <script src="main.js"></script>
</head>
<body>
  <p>
	Please select an item <input id="fruit-selector" type="text" placeholder="What are you looking for ?" />
  </p>
  <ul>
    <li>Apple</li>
    <li>Orange</li>
    <li>Banana</li>
    <li>Kiwi</li>
    <li>Mango</li>
    <li>Strawberry</li>
    <li>Fig</li>
    <li>Blackberry</li>
    <li>Currant</li>
    <li>Pear</li>
  </ul>
</body>
</html>

Nous ajoutons le chargement de deux fichiers javascript :

  • La bibliothèque JQuery
  • Un fichier main.js qui contiendra notre code Javascript

Notre but est qu’à la modification du contenu de notre champ texte nous affichions seulement les éléments de notre liste correspondants. Par exemple, en entrant ‘rry‘ dans le champ texte nous devrions avoir dans la liste d’élément seulement Strawberry et Blackberry d’affichés.
Un clic sur un élément de la liste modifiera le contenu dans notre champ texte par le texte correspondant.

Réalisation

Le clic

Commençons par le clic sur un élément. Nous allons sélectionner les éléments de notre liste via un sélecteur CSS (qui sera interprété par JQuery) et appliquer des traitements lors de l’évènement : click. Pour cela nous utiliserons le code JavaScript suivant

    $('li').click(function () {
        ...
    });

Le comportement voulu est de modifier le contenu de notre zone de texte par le contenu de notre élément. (Cliquer sur Apple affichera Apple dans le champs texte). Nous allons donc récupérer le contenu de l’élément sélectionner et l’afficher dans le champ de recherche.

$('#fruit-selector').val($(this).html());

Le code $(this) nous permet de selectionner l’élément cliqué. Nous récupérons son contenu via la méthode .html(). Nous modifions ensuite la valeur du champ texte ayant l’identifiant fruit-selector par ce contenu.

Ceci nous donne donc le code javascript suivant.

    $('li').click(function () {
        $('#fruit-selector').val($(this).html());
    });

La recherche

La recherche est un peu plus compliquée. Tout d’abord concentrons nous sur l’évènement déclencheur.
Nous souhaitons que l’ensemble des éléments de notre liste se réduisent en fonction des termes recherchés. Cette recherche s’effectue via la zone de texte. Il est donc normal d’effectuer cette action (de réduction) quand l’utilisateur saisit du texte. Il semblerait évident de choisir d’utiliser la méthode ‘change‘ de JQuery. Il se trouve que cette méthode souffre d’un inconvénient pour notre cas d’utilisation. Elle est exécutée quand l’utilisateur change le contenu de notre champ mais seulement quand celui-ci en sort (Le champ perd le focus). Nous souhaitons que le traitement soit effectué à chaque fois que l’utilisateur saisit un caractère, c’est à dire à chaque fois qu’une touche est pressée. Nous utiliserons donc la méthode ‘keyup‘.

    $('#fruit-selector').keyup(function () {
    ...
    });

Le traitement à réaliser est de n’afficher que les éléments de notre liste contenant le terme recherché. Pour cela les sélecteurs JQuery propose le filtre/sélecteur :contains(). Celui-ci nous permettra de filtrer les éléments contenant une chaîne de caractère.
Nous sélectionnerons donc l’ensemble des éléments de notre liste ne contenant pas la chaîne recherchée et les cacherons.

input_content = $(this).val();
$('ul>li').not(':contains(' + input_content + ')').hide();

Nous devons aussi à chaque nouvelle entrée re-afficher l’ensemble de notre liste, sans quoi si nous supprimons des caractères dans le champ de recherche, les éléments précédemment supprimés ne re-apparaîtrons pas.

input_content = $(this).val();
$('ul>li').show().not(':contains(' + input_content + ')').hide();

Deux problèmes perdurent :
1. Si nous recherchons une chaîne vide aucun élément ne sera sélectionner. Nous aurons une liste vide. Nous ne devons donc pas appliquer le filtre.
2. Si nous ajoutons des espaces en début ou en fin de recherche ceux-ci sont recherchés et nous n’obtenons pas le résultat souhaité. Nous devons donc supprimer ces espaces à l’aide de la méthode trim de JQuery.

Voici donc ce à quoi ressemblera notre action.

    $('#fruit-selector').change(function () {
        var input_content = $.trim($(this).val());
        if (!input_content) {
            $('ul>li').show();
        } else {
            $('ul>li').show().not(':contains(' + input_content  + ')').hide();
        }
    });

Au final

Au final le code javascript permettant de faire une recherche est assez court et ressemble à ceci.

$(document).ready(function () {
    "use strict";
    // Click on li item will change input text value
    $('li').click(function () {
        $('#fruit-selector').val($(this).html());
    });

    // Type some text into input will hide some fruit !
    $('#fruit-selector').change(function () {
        var input_content = $.trim($(this).val());
        if (!input_content) {
            $('ul>li').show();
        } else {
            $('ul>li').show().not(':contains(' + input_content  + ')').hide();
        }
    });
});

Notre recherche est donc terminée et ne tient qu’une quinzaine de lignes dont 4 de traitement réel. A vous d’imaginer et d’adapter cet exemple à vos besoins !

Si vous avez apprécié cet article, pensé à laissé un commentaire ou vous abonner au flux RSS feed.

5 thoughts on “[jquery] Recherche dynamique en javascript

  1. Bonjour,
    Votre code m’a fourni exactement ce que je recherchais, j’ai réussi à l’adapter à mon site mais malheureusement je n’arrive pas à rentrer cette fichue insensibilité à la casse, y aurait-il moyen de le terminer svp? =D

    (PS: Très bon tuto, très bonnes techniques)

  2. Bonjour,

    voici une comment j’ai personnellement procédé pour que le script soit insensible à la casse.

    J’ai remplacé:

    $('ul>li').show().not(':contains(' + input_content  + ')').hide();

    par

    $('ul>li').each(function(){
            if($(this).html().toLowerCase().search(new RegExp(input_content.toLowerCase())) !== -1)
                    $(this).show();
            else
                    $(this).hide();
    });
    • Allez encore mieux, voici une fonction grâce à laquelle on pourra appliquer notre filtre en comparant deux expressions en minuscules et nettoyées de leurs accents:

       function noAccents(s){
          var r = s.toLowerCase();
          non_asciis = {'a': '[àáâãäå]', 'ae': 'æ', 'c': 'ç', 'e': '[èéêë]', 'i': '[ìíîï]', 'n': 'ñ', 'o': '[òóôõö]', 'oe': 'œ', 'u': '[ùúûűü]', 'y': '[ýÿ]', ' ': &quot;[-']&quot;};
          for (i in non_asciis) { r = r.replace(new RegExp(non_asciis[i], 'g'), i); }
          return r;
      }; 

      Du coup le code proposé précédemment devient:

      $('ul&gt;li').each(function(){
              if(noAccents ($(this).html()).search(new RegExp(noAccents (input_content))) !== -1)
                      $(this).show();
              else
                      $(this).hide();
      });

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *