экранирование значения селектора jQuery



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



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


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




  • одинарные кавычки

  • закрывающая квадратная скобка

  • Escape html


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


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



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


или



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


возвращаемся вариант.



что такое правильный способ экранирования значений при использовании селектора " value="?

722   8  

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, которая показывает некоторые из странного поведения:

http://jsfiddle.net/dH3cV/

проблема связана с сущностями HTML;"&lt;" рассматривается браузером как "<".

то же самое можно сказать для примера, предоставленного 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]&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>");

форум 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/

эта слегка измененная версия того, что они предлагают, также является nullsafe.

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

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

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

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

Comments

    Ничего не найдено.