Выделение селектора jQuery
У меня есть раскрывающийся список, содержащий ряд опций:
<select id=SomeDropdown>
<option value="a'b]<p>">a'b]<p></option>
<option value="easy">easy</option>
<select>
Обратите внимание, что значение параметра/текст содержит некоторые неприятные вещи:
- одинарные кавычки
- закрывающая квадратная скобка
- escaped html
Мне нужно удалить параметр a'b] <p> но мне не повезло записать селектор. Ни:
$("#SomeDropdown >option[value='a''b]<p>']");
или
$("#SomeDropdown >option[value='a\'b]<p>']");
возвращает параметр.
Каков правильный способ избежать значений при использовании селектора "value ="?
Ответы
Ответ 1
Я не думаю, что ты можешь. Это должно быть:
#SomeDropdown >option[value='a\'b]<p>']
И это работает как селектор CSS (в современных браузерах). Выраженный в строковой литературе JavaScript, вам, естественно, потребуется еще один раунд экранирования:
$("#SomeDropdown >option[value='a\\'b]<p>']")
Но это не работает в jQuery, потому что его селекторный парсер не полностью совместим со стандартами. Он использует это регулярное выражение для анализа части value
условия [attr=value]
:
(['"]*)(.*?)\3|)\s*\]
\ 3 - это группа, содержащая открывающие кавычки, которые, как правило, допускаются несколькими открывающимися кавычками или вообще не содержат кавычек.. *? затем может анализировать любой символ, включая кавычки, пока он не попадет в первый символ], заканчивая совпадение. Не существует резервных копий специальных символов CSS с обратным слэшем, поэтому вы не можете сопоставить произвольное строковое значение в jQuery.
(И снова парсеры регулярных выражений теряются.)
Но хорошая новость заключается в том, что вам не нужно полагаться на селектора jQuery; есть отличные методы DOM, которые вы можете использовать, в частности HTMLSelectElement.options:
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 для тщательного анализа и реализации селектора, и вы можете использовать любую строку значений, которая вам нравится, не беспокоясь об экранировании специальных символов.
Ответ 2
Я использую эту функцию для переключения селекторов jquery. Он избегает в основном всего сомнительного, но может быть слишком агрессивным.
function escapeStr(str)
{
if (str)
return str.replace(/([ #;?%&,.+*~\':"!^$[\]()=>|\/@])/g,'\\$1');
return str;
}
Ответ 3
используйте .filter()
с пользовательской функцией. txt
должен содержать вашу неприятную строку, или вы можете просто заменить indexOf
на любую другую функцию, которую вы выберете.
$("#SomeDropdown option")
.filter(function(i){
return $(this).attr("value").indexOf(txt) != -1;
})
.remove();
Ответ 4
Я нахожу, что вы можете использовать \\ для выбора селекторов. Подумайте об этом как о\для регулярного выражения и о том, чтобы выйти из регулярного выражения.
Пример:
$(this).find('input[name=user\\[1\\]\\[name\\]]').val();
Ответ 5
Если вы пытаетесь выполнить экранирование программно, вам нужен только один набор косой черты. Это не сработает:
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, "\\$1");
}
Здесь JS Fiddle, который показывает некоторые странные поведения:
http://jsfiddle.net/dH3cV/
Ответ 6
Проблема связана с объектами 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>");
Ответ 7
Форум jQuery имеет хорошее решение для этого:
https://learn.jquery.com/using-jquery-core/faq/how-do-i-select-an-element-by-an-id-that-has-characters-used-in-css-notation/
Эта слегка измененная версия того, что они предлагают, также небезопасна.
function jqid (id) {
return (!id) ? null : '#' + id.replace(/(:|\.|\[|\]|,)/g, '\\$1');
}
Ответ 8
Безопасное экранирование строки CSS непросто и не может быть выполнено с простым регулярным выражением.
Вы можете использовать CSS.escape()
.
это не поддерживается всеми браузерами, но a polyfill существует.