Valeur du sélecteur jQuery échappant

J’ai une liste déroulante contenant une série d’options:

 ">a'b]<p> easy  

Notez que l’option value / text contient des éléments désagréables:

  • Guillemets simples
  • crochet de fermeture
  • échappé html

Je dois supprimer l’option a’b]

mais je n’ai pas de chance d’écrire le sélecteur. Ni:

 $("#SomeDropdown >option[value='a''b]<p>']"); 

ou

 $("#SomeDropdown >option[value='a\'b]<p>']"); 

renvoient l’option.

Quelle est la manière correcte d’échapper les valeurs lorsque vous utilisez le sélecteur “value =”?

Je ne pense pas que tu peux. Ce devrait être:

 #SomeDropdown >option[value='a\'b]

']

Et cela fonctionne comme un sélecteur CSS (dans les navigateurs modernes). Exprimé dans une chaîne de caractères JavaScript, vous auriez naturellement besoin d’un autre tour de contrôle:

 $("#SomeDropdown >option[value='a\\'b]

']")

Mais cela ne fonctionne pas dans jQuery car son parsingur de sélecteur n’est pas complètement conforme aux normes. Il utilise cette regex pour parsingr la partie value d’une condition [attr=value] :

 (['"]*)(.*?)\3|)\s*\] 

\ 3 étant le groupe contenant les guillemets, qui sont étrangement autorisés à contenir plusieurs guillemets, ou pas de guillemets. Le .*? puis peut parsingr n’importe quel caractère, y compris les guillemets jusqu’à ce qu’il touche le premier caractère “], mettant ainsi fin à la correspondance. Il n’y a pas de disposition pour les caractères spéciaux CSS qui échappent à la barre oblique inverse, vous ne pouvez donc pas faire correspondre une valeur de chaîne arbitraire dans jQuery.

(Encore une fois, les parsingurs de regex perdent.)

Mais la bonne nouvelle est que vous n’avez pas à vous fier aux sélecteurs jQuery; il existe parfaitement des méthodes DOM que vous pouvez utiliser, en particulier HTMLSelectElement.options:

 var select= document.getElementById('SomeDropdown'); for (var i= select.options.length; i-->0;) { if (select.options[i].value=="a'b]

") { // do something with option } }

C’est beaucoup plus simple et rapide que de demander à jQuery d’parsingr et d’implémenter votre sélecteur de manière laborieuse, et vous pouvez utiliser n’importe quelle chaîne de valeur sans avoir à vous soucier d’échapper des caractères spéciaux.

J’utilise cette fonction pour échapper aux sélecteurs jquery. Il échappe fondamentalement à tout ce qui est douteux mais peut être trop agressif.

 fonction escapeStr (str) 
 {
     si (str)
         return str.replace (/ ([#;?% &,. + * ~ \ ': "! ^ $ [\] () => | \ / @]) / g,' \\ $ 1 ');      

     retourne str;
 }

utilisez .filter() avec une fonction personnalisée. txt devrait contenir votre mauvaise chaîne, ou vous pourriez simplement remplacer indexOf avec toute autre fonction que vous choisissez.

 $("#SomeDropdown option") .filter(function(i){ return $(this).attr("value").indexOf(txt) != -1; }) .remove(); 

Je trouve que vous pouvez utiliser \ \ pour échapper aux sélecteurs. Pensez-y comme un \ pour le regex et un pour échapper au regex.

Exemple:

 $(this).find('input[name=user\\[1\\]\\[name\\]]').val(); 

Si vous essayez d’effectuer l’évasion par programme, vous n’avez besoin que d’un seul jeu de barres obliques. Cela ne marchera pas:

 var key = 'user[1][name]'; $(this).find('select[name=' + key + ']'); 

Mais cela va:

 var key = 'user\[1\]\[name\]'; $(this).find('select[name=' + key + ']'); 

Et ainsi:

 $(this).find('select[name=user\\[1\\]\\[name\\]]'); 

Vous pouvez utiliser ce javascript pour créer un sélecteur correctement échappé:

 if(key.indexOf('[') !== -1) { key = key.replace(/([\[\]])/g, "\\$1"); } 

Voici un violon de JS qui montre un comportement étrange:

http://jsfiddle.net/dH3cV/

Le problème est dû aux entités HTML; le ” < ” est vu par le navigateur comme ” < ".

On pourrait dire la même chose pour l'exemple fourni par Bobince; Veuillez noter que les éléments suivants ne fonctionnent pas avec jQuery 1.32 sous Win + FF3:

 var select= document.getElementById('SomeDropdown'); for (var i= select.options.length; i-->0;) { if (select.options[i].value=="a'b]<p>") { alert('found it'); } } 

Cependant, changer l'entité en littéral trouvera la valeur souhaitée:

 var select= document.getElementById('SomeDropdown'); for (var i= select.options.length; i-->0;) { if (select.options[i].value=="a'b]

") { alert('found it'); } }

Bien sûr, il y a un problème ici, car la valeur que vous spécifiez n'est pas la valeur exacte que vous recherchez. Cela peut également être corrigé avec l'ajout d'une fonction d'assistance:

 function html_entity_decode(str) { var decoder = document.createElement('textarea'); decoder.innerHTML = str; return decoder.value; } 

Tous ensemble maintenant:

 var srcValue = html_entity_decode("a'b]<p>"); var select= document.getElementById('SomeDropdown'); for (var i= select.options.length; i-->0;) { if (select.options[i].value == srcValue) { alert('found it'); } } 

À tout moment, la valeur d'entrée que vous recherchez correspond exactement à la valeur de l'élément select.

Cela peut aussi être écrit en utilisant les méthodes jQuery:

 var srcValue = html_entity_decode("a'b]<p>"); $($('#SomeDropdown').attr('options')).each(function() { if (this.value == srcValue) { $(this).remove(); } }); 

Et enfin, en tant que plug-in car ils sont si faciles à faire:

 jQuery.fn.removeByValue = function( val ) { var decoder = document.createElement('textarea'); decoder.innerHTML = val; var srcValue = decoder.value; $( $(this)[0].options ).each(function() { if (this.value == srcValue) { $(this).remove(); } }); return this; }; $('#SomeDropdown').removeByValue("a'b]<p>"); 

Le forum de jQuery a une bonne solution pour cela:

https://learn.jquery.com/using-jquery-core/faq/how-do-i-select-an-element-by-an-id-that-has-characters-used-in-css-notation/

Cette version légèrement modifiée de ce qu’ils suggèrent est également nullsafe.

 function jqid (id) { return (!id) ? null : '#' + id.replace(/(:|\.|\[|\]|,)/g, '\\$1'); } 

Échapper en toute sécurité à la chaîne CSS n’est pas facile et ne peut pas être fait avec une simple expression régulière.

Vous pouvez utiliser CSS.escape() .

Ceci n’est pas supporté par tous les navigateurs mais un polyfill existe .