JQuery селектор значения экранирования - PullRequest
54 голосов
/ 11 апреля 2009

У меня есть выпадающий список, который содержит ряд параметров:

<select id=SomeDropdown>
  <option value="a'b]&lt;p>">a'b]&lt;p></option>
  <option value="easy">easy</option>
<select>

Обратите внимание, что значение параметра / текст содержит некоторые неприятные вещи:

  • одинарные кавычки
  • закрывающая квадратная скобка
  • избежал html

Мне нужно удалить опцию a'b]

, но мне не повезло в написании селектора. Ни:

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

или

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

возвращают опцию.

Как правильно экранировать значения при использовании селектора «value =»?

Ответы [ 8 ]

51 голосов
/ 25 июня 2010

Я использую эту функцию, чтобы избежать селекторов jquery. Он избегает в основном всего сомнительного, но может быть слишком агрессивным.

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

    return str;
}
38 голосов
/ 11 апреля 2009

Не думаю, что ты можешь. Это должно быть:

#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 кропотливого анализа и реализации вашего селектора, и вы можете использовать любую строку значений, которую вам нравятся, не беспокоясь о экранировании специальных символов.

9 голосов
/ 10 июня 2012

используйте .filter() с пользовательской функцией. txt должен содержать вашу неприятную строку, или вы можете просто заменить indexOf на любую другую функцию, которую вы выберете.

$("#SomeDropdown option")
   .filter(function(i){
       return $(this).attr("value").indexOf(txt) != -1;
   })
   .remove();
5 голосов
/ 23 ноября 2012

Я считаю, что вы можете использовать \ \, чтобы избежать селекторов. Думайте об этом как об одном \ для регулярного выражения и одном, чтобы сбежать от регулярного выражения

Пример:

$(this).find('input[name=user\\[1\\]\\[name\\]]').val();
3 голосов
/ 19 марта 2013

Если вы пытаетесь выполнить экранирование программным способом, вам нужен только один набор слешей. Это не сработает:

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/

2 голосов
/ 12 апреля 2009

Проблема связана с сущностями HTML; «&lt;» обозреватель видит как «<».

То же самое можно сказать о примере, представленном Бобинсом; обратите внимание, что следующее не работает с 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]&lt;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]&lt;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]&lt;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]&lt;p>");
1 голос
/ 09 марта 2016

Безопасно экранирование строки CSS не просто и не может быть сделано с помощью простого регулярного выражения.

Вы можете использовать CSS.escape().

это поддерживается не всеми браузерами, но полифильт существует .

1 голос
/ 11 декабря 2015

На форуме 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');
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...