【问题标题】:jQuery selector value escapingjQuery选择器值转义
【发布时间】: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=" 选择器时转义值的正确方法是什么?

【问题讨论】:

  • 用户可以输入任何内容。他们不太可能......但如果他们这样做了,那么应用程序应该正确处理输入。

标签: jquery jquery-selectors escaping


【解决方案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外,并非所有浏览器都支持。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-05-27
            • 1970-01-01
            • 2017-05-02
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多