jQuery选择器值转义

时间:2009-04-11 07:40:44

标签: jquery jquery-selectors escaping

我有一个包含一系列选项的下拉列表:

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

请注意,选项值/文本包含一些讨厌的东西:

  • 单引号
  • 关闭方括号
  • 转义html

我需要删除a'b]&lt; p&gt;选项,但我没有运气写选择器。既不:

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

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

正在返回选项。

使用“value =”选择器时,转义值的正确方法是什么?

9 个答案:

答案 0 :(得分:51)

我使用此函数来转义jquery选择器。它基本上逃脱了一切可疑但可能过于激进。

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

    return str;
}

答案 1 :(得分:38)

我认为你不能。 应该

#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 :(得分:9)

.filter()与自定义函数一起使用。 txt应该包含令人讨厌的字符串,或者您可以将indexOf替换为您选择的任何其他函数。

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

答案 3 :(得分:5)

我发现你可以使用\ \来逃避选择器。可以把它想象成正则表达式,一个逃离正则表达式。

示例:

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

答案 4 :(得分:3)

如果您尝试以编程方式进行转义,则只需要一组斜杠。这不起作用:

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小提琴,它展示了一些奇怪的行为:

http://jsfiddle.net/dH3cV/

答案 5 :(得分:2)

问题是由于HTML实体造成的;浏览器将“ &lt; ”视为“ < ”。

bobince提供的例子也是如此;请注意,以下内容不适用于Win + FF3上的jQuery 1.32:

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>");

答案 6 :(得分:1)

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');
}

答案 7 :(得分:1)

安全escaping CSS string并不容易,无法使用简单的正则表达式完成。

您可以使用CSS.escape()

除了a polyfill exist之外,所有浏览器都不支持此功能。

答案 8 :(得分:1)

jQuery.escapeSelector()是jQuery 3中引入的。要使问题中的选项与值a'b]&lt;p>相匹配,可以使用:

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

通常,对于jQuery.escapeSelector()之类的事物,使用$('#' + $.escapeSelector(id))是一个好习惯,其中变量id可能包含特殊的CSS符号。