4 votes

Se concentrer sur un résultat de l'autocomplétion jQuery (pas nécessairement le premier)

Je m'efforce d'étendre la fonction d'autocomplétion de jQuery de manière à ce qu'un élément particulier ait le focus par défaut. La fonctionnalité prête à l'emploi fonctionne assez bien, mais elle n'est pas parfaite. En utilisant la fonction autoFocus je peux me concentrer automatiquement sur le premier élément.

$( "#input" ).autocomplete({
    source: "autocomplete.php",
    minLength: 1,
    autoFocus: true
});

Cependant, j'aimerais avoir plus de contrôle sur l'élément qui est mis en avant. Si l'utilisateur tape "eng" et que les éléments pertinents que ma source renvoie sont :

  • Anglais américain
  • Anglais britannique
  • Anglais
  • Anglais écossais

Je voudrais le troisième point, Anglais doit être mis en évidence par défaut (c'est-à-dire l'élément qui commence réellement par la saisie de l'utilisateur, même si j'aimerais afficher les autres résultats). Idéalement, ma source - autocomplete.php - devrait être en mesure d'indiquer quel élément doit être mis en avant par défaut.

Des idées ? Je ne sais même pas par où commencer.

4voto

Andrew Whitaker Points 58588

Il existe un moyen simple d'y parvenir, en tirant parti de la fonction open événement. Vous pouvez demander au code côté client de gérer le choix de l'élément par défaut ou d'envoyer une propriété supplémentaire avec l'élément que vous souhaitez sélectionner. Je vais passer en revue les deux options :

Orientation de la suggestion commençant par le terme, sélectionnée sur le client :

$("input").autocomplete({
    source: /* ... */,
    open: function (event, ui) {
        var menu = $(this).data("uiAutocomplete").menu
            , i = 0
            , $items = $('li', menu.element)
            , item
            , text
            , startsWith = new RegExp("^" + this.value, "i");

        for (; i < $items.length && !item; i++) {
            text = $items.eq(i).text();
            if (startsWith.test(text)) {
                item = $items.eq(i);
            }
        }

        if (item) {
            menu.focus(null, item);
        }
    }
});

En gros, l'idée est de faire ce qui suit lorsque le menu de l'autocomplétion est ouvert :

  • Créez une expression régulière pour rechercher les mots commençant par le terme recherché.
  • Nous parcourons chaque élément du menu et testons son texte par rapport à l'expression régulière. Si une correspondance est trouvée, l'itération s'arrête et la valeur est enregistrée.
  • Si nous avons récupéré une valeur, utilisez la fonction focus sur le menu pour mettre l'élément en surbrillance.

Ejemplo: http://jsfiddle.net/J5rVP/40/ (Essayez de rechercher E nglais ou S cots English)

Le code utilise une source de données locale, mais il devrait fonctionner tout aussi bien avec une source distante.


Thème de la suggestion commençant par un terme, sélectionné sur le serveur

Dans le prolongement de l'exemple ci-dessus, vous pouvez modifier la façon dont vous envoyez les données, de sorte qu'à chaque recherche, votre code côté serveur décide de l'élément à sélectionner. Pour ce faire, il vous suffit de spécifier une propriété supplémentaire sur l'élément que vous souhaitez sélectionner. Par exemple, votre réponse JSON pourrait ressembler à ceci :

[{"label":"American English","select":true},{"label":"British English"},{"label":"English"},{"label":"Scots English"}]

Notez que les select sur "American English". Cela indique à la saisie semi-automatique que nous souhaitons sélectionner cet élément par défaut.

Ensuite, vous devez mettre à jour le code d'initialisation de votre widget afin d'utiliser la fonction open comme ci-dessus. Cette fois-ci, nous recherchons simplement un élément à l'aide de l'attribut select propriété :

$("input").autocomplete({
    source: "autocomplete.php",
    open: function (event, ui) {
        var menu = $(this).data("uiAutocomplete").menu,
            i = 0,
            $items = $('li', menu.element),
            item,
            data;

        for (; i < $items.length && !item; i++) {
            data = $items.eq(i).data("ui-autocomplete-item");
            if (data.select) {
                item = $items.eq(i);
            }
        }

        if (item) {
            menu.focus(null, item);
        }
    }
});

Ejemplo: http://jsfiddle.net/J5rVP/42/

Notez que dans l'exemple ci-dessus Anglais américain est toujours sélectionnée. Étant donné que l'autocomplétion émet une nouvelle requête à chaque fois que l'utilisateur tape, votre serveur répondrait avec des données de suggestion différentes et donc un élément sélectionné différent.

Par ailleurs, je ne connais pas le langage PHP et je ne peux donc pas vous dire comment vous pourriez ajouter l'élément select à la propriété JSON. Cela semble pourtant assez simple et pourrait même ressembler au code JavaScript du premier exemple qui utilise une expression régulière.

2voto

charlietfl Points 41873

Je suggère que vous examiniez différemment la cartographie des données afin que les éléments les plus prioritaires soient affichés en premier, tels que les mots commençant par le terme de recherche.

Vous pouvez ensuite suivre la démo AutoComplete/catégories pour séparer vos résultats. Ce sera beaucoup plus facile que d'essayer de créer du code pour modifier les résultats de l'enquête. autoFocus Les plus hauts gradés se trouveraient en haut de l'échelle et c'est là que l'on commencerait à se concentrer.

http://jqueryui.com/autocomplete/#categories

Voici un concept que vous pourriez utiliser pour classer les résultats :

function rankResult($str, $term){
     /* 0 is first letters, 1 is in first word, 2 is starts another word, 3 is in word not first word*/
     $words=explode(' ', $str); 
     if(stripos($words[0],$term) !==false){
        return stripos($words[0],$term)==0 ? 0 : 1;
     }else{
        $rank=3;
        for( $i=1; $i< count( $words); $i++){
            if(stripos($words[$i],$term)===0){
                $rank=2;
            }
        }
        return $rank;
     }      
}

 $rank = rankResult('English', 'eng'); /*=> 0 */

Boucle sur :

  array('American English','British English','English','Scots English','HasEngInIt');

Renvoyé :

Array
(
    [0] => Array
        (
            [label] => American English
            [rank] => 2
        )

    [1] => Array
        (
            [label] => British English
            [rank] => 2
        )

    [2] => Array
        (
            [label] => English
            [rank] => 0
        )

    [3] => Array
        (
            [label] => Scots English
            [rank] => 2
        )

    [4] => Array
        (
            [label] => HasEngInIt
            [rank] => 1
        )

)

Il faudrait faire un peu de tri pour que les données soient regroupées par rang avant d'être envoyées à la saisie semi-automatique.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X