2012-12-11 10 views
1

J'utilise un menu déroulant (select/object html one), qui est généré dynamiquement en prenant des données d'un DB, en utilisant une page jsp.Modification en temps réel du menu html coulissant

J'ai également un champ de texte d'entrée, où je peux rechercher des choses du menu coulissant. Je veux écrire la racine d'un mot qui est contenu dans mon menu, et mon menu doit "redimensionner" montrant tous les éléments avec la racine que j'ai écrite, et seulement ceux-là.

Je ne peux pas utiliser les opérations côté serveur (comme l'envoi de données par la poste) mais j'ai besoin de résoudre ce côté client (parce que j'ai besoin de ce résultat immédiatement).

J'ai effectivement résolu ce problème en utilisant javascript, mais j'ai quelques problèmes de performance avec cette solution, parce que je dois utiliser IE 8.

est-il une solution similaire en utilisant JQuery ou Ajax?

Voici quelque chose de similaire à mon code:

HTML:

<select multiple id="testSelect"> 
    <option>test</option> 
    <option>temp</option> 
    <option>cast</option> 
    <option>dest</option> 
    <option>inst</option> 
</select> 

<input type="text" value="" onkeyup="searhSelect(this)" />​ 

fonction searhSelect sera appelée à chaque pression de touche (lorsque l'utilisateur relâchez une touche en fait) et filtrera objet #testSelect.

JS:

var optionsList; 
function searhSelect(el) { 
    var select = document.getElementById('testSelect'); 
    if(!optionsList) {   
     optionsList = select.cloneNode(true); //copy select to a variable for future use  
    } 
    select.innerHTML = "";//remove all options. 

    for(var i =0; i < optionsList.options.length; i++) { 
     var opt = optionsList.options[i]; 
     if(opt.innerHTML.indexOf(el.value) != -1) { 
      select.appendChild(opt.cloneNode(true)); 
     } 
    } 
} 
+0

Combien d'éléments avez-vous? Dans cet élément DOM cloné searchSelect est utilisé. Peut-être stocker des éléments dans le tableau JS régulière aidera. –

+0

Je suppose que plus de 10k éléments. Quand je commence à taper, il faut 20 secondes pour terminer la tâche. Comment puis-je stocker mes éléments dans un tableau JS normal? Malheureusement, je ne suis pas si "intelligent" sur JS ... – abierto

+0

Hm ... 10k éléments? C'est beaucoup. Ne pensez pas que même JS array aidera réellement ... AJAX peut vous aider, mais une fois que vous essayerez de montrer une grande quantité d'éléments - il sera lent quand même (à cause de la mise à jour lente de dom). –

Répondre

1

code Essayez comme ceci:

var optionsList = []; 
function searhSelect(el) { 
    var select = document.getElementById('testSelect'); 

    if(optionsList.length == 0) {   
     for(var i = 0; i < select.options.length; i++) 
      optionsList[i] = {key:select.options[i].value,value:select.options[i].innerHTML}; //copy select to a variable for future use  
    } 
    //if(el.value.length > 2) { 
     var tmp = "<select id=\"testSelect\" mulitple=\"multiple\" size=\"4\">"; 
     for(var i =0; i < optionsList.length; i++) { 
      var opt = optionsList[i]; 
      if(opt.value.indexOf(el.value) != -1) {     
       tmp += ' <option value="' + opt.key + '" >' + opt.value + '</option> ';       
      }   
     } 
     document.getElementById('test').innerHTML = tmp + "</select>"; 
    //} 

} 

HTML:

<div id="test"> 
    <select multiple id="testSelect"> 
     <option>test</option> 
     <option>temp</option> 
     <option>cast</option> 
     <option>dest</option> 
     <option>inst</option> 
     <!-- in my test same options you see above were copy/pasted many times. I had little more than 10k options-> 
    </select> 
</div> 

J'ai enlevé tout clone/appendChild, pusshed tous les éléments tableau int avec un objet contenant des champs de valeur et de texte et, ce qui est le plus important, les options sont maintenant créées avec innerHTML. Notez également que select est maintenant encapsulé avec un autre div. Et au lieu d'utiliser innerHTML de select et en définissant simplement les options HTML, une chaîne avec tout HTML de sélection est créée (var tmp = "<select id=\"testSelect\" mulitple=\"multiple\" size=\"4\">";). Cela est nécessaire comme une solution de contournement pour IE this bug.

Dans votre implémentation actuelle, chaque option est ajoutée une fois qu'elle est trouvée, une par une. De cette façon, IE rendra l'élément chaque fois qu'une nouvelle option est ajoutée(). Mais le code ci-dessus forcera le rendu une seule fois - lorsque toutes les options sont définies. Malheureusement, cela aide seulement partiellement. Il fonctionne plus vite que le code de la question, mais il faut environ 10s (comparé à 20-30s avec l'ancien code) pour rendre le nouvel élément select (document.getElementById('test').innerHTML = tmp + "</select>"; - à ce stade, il gèle le navigateur pendant 10s)

Je ne pense pas vous pouvez le rendre plus rapide sans apporter de modifications globales (sélection multiple personnalisée avec cases à cocher pour sélectionner un élément, par exemple, et éléments affichés/masqués avec display: block/none). Solution possible - mettre à jour l'élément uniquement lorsqu'il y aura une quantité relativement faible d'éléments filtrés. Par exemple - lorsque la longueur de la valeur à rechercher est supérieure à 2 caractères (voir commenté //if(el.value.length > 2) {). Mais pour l'utiliser, la mise en œuvre actuelle nécessite un codage supplémentaire (au moins, la liste complète doit être affichée à nouveau une fois que l'utilisateur a supprimé certains caractères du champ de saisie).

+0

Merci pour votre réponse fonctionnelle et détaillée. J'ai essayé votre code, mais cela prend au moins le même temps que le mien (environ 10 secondes). Dommage, je suppose que nous devrions "traiter" avec la performance IE8 ... – abierto

+0

Vous pouvez essayer de construire votre propre "select". Juste un div avec la liste des autres divs de l'intérieur. Item div contient une case à cocher (vous pouvez donc soumettre les éléments sélectionnés) et du texte En fait, vous pouvez masquer la case à cocher et imiter complètement le comportement select (gérer les clics sur le texte et cocher les cases cochées/non cochées). Et modifiez le code pour afficher/masquer les éléments avec la propriété style.display. Cela devrait être plus rapide, je pense. –

0

Je suppose que vous essayez de faire quelque chose comme autocomplete. Avez-vous essayé http://api.jqueryui.com/autocomplete? Ou voulez-vous simplement que les options SELECT soient filtrées? Ensuite, je suppose qu'il est plus facile de les cacher/les désactiver au lieu de les cloner.

+0

Je ne veux pas d'autocomplétion. Lorsque j'écris dans la zone de texte, ma liste sera automatiquement "redimensionnée" avec seulement les valeurs qui contiennent mon texte tapé. Et quand je supprime du texte, ma liste redimensionne automatiquement à la longueur d'origine. – abierto