jQuery选择器值转义

Posted

技术标签:

【中文标题】jQuery选择器值转义【英文标题】:jQuery selector value escaping 【发布时间】:2010-10-18 21:20:52 【问题描述】:

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

<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=" 选择器时转义值的正确方法是什么?

【问题讨论】:

用户可以输入任何内容。他们不太可能......但如果他们这样做了,那么应用程序应该正确处理输入。 【参考方案1】:

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

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

【讨论】:

你测试过吗?当我测试它时,它只在元字符前放了 1 个斜杠。这是我写的:str.replace(/([ !"#$%&amp;'()*+,.\/:;&lt;=&gt;?@[\\\]^`|~])/g,'\\\\$1'). @Mark,使用答案中的代码可以很好地转义 jquery 选择器中的特殊字符。 @Justin:你可能是对的。医生欺骗了我。它说你需要两个斜杠,但一个只是用于转义 javascript 字符串中的斜杠,第二个是用于实际转义 CSS 选择器。 我修改了正则表达式以包含匹配 ?: return str.replace(/([ #;?&amp;,.+*~\':"!^$[\]()=&gt;|\/@])/g,'\\$1'); 百分号%也需要转义。【参考方案2】:

我不认为你可以。它应该是:

#SomeDropdown >option[value='a\'b]<p>']

这确实可以用作 CSS 选择器(在现代浏览器中)。用 JavaScript 字符串文字表示,你自然需要另一轮转义:

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

但这在 jQuery 中不起作用,因为它的选择器解析器不完全符合标准。它使用此正则表达式来解析 [attr=value] 条件的 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 费力地解析和实现你的选择器要简单和快速很多倍,你可以使用任何你喜欢的值字符串,而不必担心转义特殊字符。

【讨论】:

我建议将其作为纯 DOM 的 jQuery 替代品: $('option', '#SomeDropdown').filter(function() return $(this).val() == "a'b]

"; );

@PaoloBergantino 您的回答是我的案例的完美解决方案。非常感谢您的评论。【参考方案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();

【讨论】:

我写了一个 .replace 正则表达式来为你转义选择器here【参考方案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 实体造成的; “&amp;lt;”被浏览器视为“&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>");

【讨论】:

【参考方案7】:

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

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

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

【讨论】:

【参考方案8】:

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, '\\$1');

【讨论】:

【参考方案9】:

安全地escaping CSS string 并不容易,不能用简单的正则表达式来完成。

你可以使用CSS.escape()

除a polyfill exist外,并非所有浏览器都支持。

【讨论】:

以上是关于jQuery选择器值转义的主要内容,如果未能解决你的问题,请参考以下文章

如何让这个 jQuery 选择器正常工作?带有转义字符

jQuery 选择器转义冒号“:”在 IE 中有效,但在其他地方无效

Jquery选择器-基本选择器

jQuery 选择器

jquery选择器

jquery 选择器包含特殊字符