web-dev-qa-db-ja.com

jQueryセレクター値のエスケープ

一連のオプションを含むドロップダウンリストがあります。

<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 =」セレクターを使用するときに値をエスケープする正しい方法は何ですか?

54
user53794

できるとは思わない。それべき

#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に要求するよりも何倍も簡単で高速であり、特殊文字をエスケープすることを心配することなく、好きな値の文字列を使用できます。

38
bobince

この関数を使用して、jqueryセレクターをエスケープします。それは基本的に疑わしいすべてを免れますが、攻撃的すぎるかもしれません。

 function escapeStr(str)
 {
 if(str)
 return str.replace(/([#;?%&、。+ *〜\ ' : "!^ $ [\]()=> | \/@])/ g、 '\\ $ 1'); 
 
 return str; 
} 
51
Sam Hendley

カスタム関数で.filter()を使用します。 txtには厄介な文字列が含まれている必要があります。または、indexOfを他の選択した関数に置き換えることができます。

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

\ \を使用してセレクターをエスケープできることがわかりました。正規表現の1つと正規表現からの脱出の1つと考えてください。

例:

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

プログラムでエスケープを実行しようとしている場合、必要なのは1組のスラッシュだけです。これは機能しません:

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/

3
Steve Tauber

この問題は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>");
2
ken

安全に CSS文字列のエスケープ は簡単ではなく、単純な正規表現では実行できません。

CSS.escape() を使用できます。

これはすべてのブラウザでサポートされているわけではありませんが、 ポリフィルが存在します

1
Yukulélé

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