экранирование значения селектора jQuery
у меня есть выпадающий список, который содержит ряд вариантов:
<select id=SomeDropdown>
<option value="a'b]<p>">a'b]<p></option>
<option value="easy">easy</option>
<select>
обратите внимание, что значение параметра / текст содержит некоторые неприятные вещи:
- одинарные кавычки
- закрывающая квадратная скобка
- Escape html
мне нужно удалить опцию a'B]
, но мне не повезло написать селектор. Ни то, ни другое:
$("#SomeDropdown >option[value='a''b]<p>']");
или
$("#SomeDropdown >option[value='a'b]<p>']");
возвращаемся вариант.
что такое правильный способ экранирования значений при использовании селектора " value="?
8 ответов:
Я не думаю, что вы можете. Это должны быть:
#SomeDropdown >option[value='a\'b]<p>']и это действительно работает как селектор CSS (в современных браузерах). Выраженный в строковом литерале JavaScript, вам, естественно, понадобится еще один раунд экранирования:
$("#SomeDropdown >option[value='a\'b]<p>']")но это не работает в jQuery, потому что его селекторный парсер не полностью соответствует стандартам. Он использует это регулярное выражение для разбора
valueчасть[attr=value]состояние:(['"]*)(.*?)|)\s*\]\3 - группа, содержащая начальные котировки, которые, как ни странно, могут быть несколькими начальными котировками или вообще не открывать котировки. Этот.* ? тогда можно разобрать любой символ,включая кавычки пока он не попадет в первый символ‘]', заканчивая матч. Для специальных символов CSS с обратной косой чертой не предусмотрено, поэтому вы не можете сопоставить произвольное строковое значение в jQuery.
(опять же, Парсеры регулярных выражений проигрывают.)
но хорошая новость заключается в том, что вам не нужно полагаться на селекторы jQuery; там отлично подходят методы DOM, которые вы можете использовать, в частности HTMLSelectElement.опции:
var select= document.getElementById('SomeDropdown'); for (var i= select.options.length; i-->0;) { if (select.options[i].value=="a'b]<p>") { // do something with option } }это во много раз проще и быстрее, чем просить jQuery тщательно проанализировать и реализовать ваш селектор, и вы можете использовать любую строку значений, которую вам нравится, не беспокоясь о том, чтобы избежать специальных символов.
Я использую эту функцию, чтобы избежать селекторов jquery. Он избегает в основном всего сомнительного, но может быть слишком агрессивным.
function escapeStr(str) { if (str) return str.replace(/([ #;?%&,.+*~\':"!^$[\]()=>|\/@])/g,'\'); return str; }
использовать
.filter()с пользовательской функции.txtдолжен содержать вашу неприятную строку, или вы можете просто заменитьindexOfС любой другой функцией, которую вы выберете.$("#SomeDropdown option") .filter(function(i){ return $(this).attr("value").indexOf(txt) != -1; }) .remove();
Я считаю, что вы можете использовать \ \ чтобы избежать селекторов. Подумайте об этом как об одном \ для регулярного выражения и о том, чтобы убежать от регулярного выражения.
пример:
$(this).find('input[name=user\[1\]\[name\]]').val();
если вы пытаетесь сделать экранирование программно, вам нужен только один набор косых. Это не сработает:
var key = 'user[1][name]'; $(this).find('select[name=' + key + ']');а это:
var key = 'user\[1\]\[name\]'; $(this).find('select[name=' + key + ']');и вот это:
$(this).find('select[name=user\[1\]\[name\]]');вы можете использовать этот javascript для построения правильно экранированного селектора:
if(key.indexOf('[') !== -1) { key = key.replace(/([\[\]])/g, "\"); }вот Скрипка JS, которая показывает некоторые из странного поведения:
проблема связана с сущностями HTML;"
<" рассматривается браузером как "<".то же самое можно сказать для примера, предоставленного bobince; обратите внимание, что следующее не работает с jQuery 1.32 на 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'); } }однако изменение сущности на литерал действительно найдет желаемое значение:
var select= document.getElementById('SomeDropdown'); for (var i= select.options.length; i-->0;) { if (select.options[i].value=="a'b]<p>") { alert('found it'); } }конечно, здесь есть проблема, так как значение, которое вы задаете это не точное значение, которое вы ищете. Это также может быть исправлено с добавлением вспомогательной функции:
function html_entity_decode(str) { var decoder = document.createElement('textarea'); decoder.innerHTML = str; return decoder.value; }теперь все вместе:
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'); } }теперь входное значение, которое вы ищете, точно соответствует значению элемента select.
это также может быть написано с помощью методов jQuery:
var srcValue = html_entity_decode("a'b]<p>"); $($('#SomeDropdown').attr('options')).each(function() { if (this.value == srcValue) { $(this).remove(); } });и, наконец, как плагин, так как они так легко сделать:
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>");
форум jQuery имеет хорошее решение для этого:
эта слегка измененная версия того, что они предлагают, также является nullsafe.
function jqid (id) { return (!id) ? null : '#' + id.replace(/(:|\.|\[|\]|,)/g, '\'); }
безопасное экранирование строки CSS - это не легко и может быть сделано с помощью простого регулярного выражения.
можно использовать
CSS.escape().это поддерживается не всеми браузерами, но полифилл существует.
Comments