jQuery selector value escaping

2019-01-01 16:04发布

I have a dropdown list that contains a series of options:

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

Notice that the option value/text contains some nasty stuff:

  • single quotes
  • closing square bracket
  • escaped html

I need to remove the a'b]<p> option but I'm having no luck writing the selector. Neither:

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

or

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

are returning the option.

What is the correct way to escape values when using the "value=" selector?

8条回答
其实,你不懂
2楼-- · 2019-01-01 16:15

use .filter() with a custom function. txt should contain your nasty string, or you could just replace indexOf with any other function you choose.

$("#SomeDropdown option")
   .filter(function(i){
       return $(this).attr("value").indexOf(txt) != -1;
   })
   .remove();
查看更多
柔情千种
3楼-- · 2019-01-01 16:15

If you are trying to do the escaping programmatically, you only need one set of slashes. This won't work:

var key = 'user[1][name]';
$(this).find('select[name=' + key + ']');

But this will:

var key = 'user\[1\]\[name\]';
$(this).find('select[name=' + key + ']');

And so will this:

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

You can use this javascript to build a correctly escaped selector:

if(key.indexOf('[') !== -1) {
    key = key.replace(/([\[\]])/g, "\\$1");
}

Here's a JS Fiddle that shows some of the weird behavior:

http://jsfiddle.net/dH3cV/

查看更多
浮光初槿花落
4楼-- · 2019-01-01 16:17

I find that you can use \ \ to escape selectors. Think of it as one \ for the regex and one to escape from the regex.

Example:

$(this).find('input[name=user\\[1\\]\\[name\\]]').val();
查看更多
后来的你喜欢了谁
5楼-- · 2019-01-01 16:20

jQuery's forum has a nice solution for this:

https://learn.jquery.com/using-jquery-core/faq/how-do-i-select-an-element-by-an-id-that-has-characters-used-in-css-notation/

This slightly modified version of what they suggest is also nullsafe.

function jqid (id) {
  return (!id) ? null : '#' + id.replace(/(:|\.|\[|\]|,)/g, '\\$1');
}
查看更多
明月照影归
6楼-- · 2019-01-01 16:20

Safely escaping CSS string is not easy and can't be done with simple regex.

You can use CSS.escape() .

this is not supported by all browsers but a polyfill exist.

查看更多
妖精总统
7楼-- · 2019-01-01 16:22

The problem is due to HTML entities; the "&lt;" is seen by the browser as "<".

The same could be said for the example provided by bobince; please note that the following does not work with jQuery 1.32 on 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');
    }   
}

However, changing the entity to a literal will indeed find the desired value:

var select= document.getElementById('SomeDropdown');
for (var i= select.options.length; i-->0;) {
    if (select.options[i].value=="a'b]<p>") {
        alert('found it');
    }   
}

Of course, there is a problem here, as the value that you're specifying is not the exact value that you're looking for. This can also be corrected with the addition of a helper function:

function html_entity_decode(str) {
    var decoder = document.createElement('textarea');
    decoder.innerHTML = str;
    return decoder.value;
}

All together now:

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

Any now, the input value that you're searching for exactly matches the value of the select element.

This can also be written using jQuery methods:

var srcValue = html_entity_decode("a'b]&lt;p>");
$($('#SomeDropdown').attr('options')).each(function() {
    if (this.value == srcValue)
    {
        $(this).remove();
    }
});

And then finally, as a plugin since they are so easy to make:

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>");
查看更多
登录 后发表回答