56

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

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

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

  • 单引号
  • 右方括号
  • 转义的 html

我需要删除 a'b]<p> 选项,但我没有运气编写选择器。两者都不:

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

或者

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

正在返回选项。

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

4

9 回答 9

53

我使用这个函数来转义 jquery 选择器。它基本上避开了所有有问题的东西,但可能过于激进。

函数 escapeStr(str)
{
    如果(字符串)
        return str.replace(/([ #;?%&,.+*~\':"!^$[\]()=>|\/@])/g,'\\$1');      

    返回字符串;
}
于 2010-06-24T20:46:28.130 回答
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 费力地解析和实现您的选择器要简单和快很多倍,并且您可以使用任何您喜欢的值字符串,而不必担心转义特殊字符。

于 2009-04-11T14:18:44.787 回答
10

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

$("#SomeDropdown option")
   .filter(function(i){
       return $(this).attr("value").indexOf(txt) != -1;
   })
   .remove();
于 2012-06-10T04:32:49.270 回答
5

我发现您可以使用 \\ 来转义选择器。将其视为正则表达式的一个 \ 和一个从正则表达式中逃脱的。

例子:

$(this).find('input[name=user\\[1\\]\\[name\\]]').val();
于 2012-11-23T16:52:01.250 回答
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 Fiddle,它显示了一些奇怪的行为:

http://jsfiddle.net/dH3cV/

于 2013-03-18T23:56:40.640 回答
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');
    }   
}

现在,您正在搜索的输入值与选择元素的值完全匹配。

这也可以使用 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>");
于 2009-04-11T22:46:05.130 回答
2

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

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

一般来说,对于变量可能包含特殊 CSS 符号jQuery.escapeSelector()的情况,使用是一种很好的做法。$('#' + $.escapeSelector(id))id

于 2020-06-09T16:33:36.047 回答
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');
}
于 2015-12-11T00:38:28.623 回答
1

安全地转义 CSS 字符串并不容易,而且不能用简单的正则表达式来完成。

您可以使用CSS.escape().

并非所有浏览器都支持此功能,但存在 polyfill

于 2016-03-09T20:37:44.190 回答