8
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

ディップAdvent Calendar 2019

Day 10

今更ながらjQueryのセレクタにハマった話

Posted at

ディップ Advent Calendar 2019の10日目です。

はじめに

こんにちは、ディップ株式会社に2018年新卒で入社し、求人系サービスの開発や社内向けツールの開発を行なっている@taku-0728です。
今回は私がjQueryのセレクタでハマった話を書きたいと思います。
知ってる方からすれば当たり前だと思うかもしれませんが、自分用メモとして残します。
よろしくお願いいたします。

結論

細かいことはいいから結論が知りたい忙しい人用に僕がこの記事で言いたいことを一言でいうと「jQueryでセレクタに使う際にエスケープが必要なものがある」ということです。エスケープが必要な文字は下記です。先頭に半角スペースを含んでいます。

 !"#$%&'()*+,./:;<=>?@[\]^`{|}~

(先頭の半角スペースを含んだ)これらの文字は2つのバックスラッシュ\\を使ってエスケープする必要があります。

実例

<html>
  <head>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
  </head>
  <body>
    <p id='test'>test</p>
    <button id='button[0]'>消す</button>
    <button id ='button[1]'>表示する</button>
  </body>
  <script>
    $('#button[0]').on('click', function(){
      $('#test').hide();
    })
    $('#button[1]').on('click', function(){
      $('#test').show();
    })
  </script>
</html>

3分で書いた雑なコードですがご了承ください。「消す」ボタンをクリックするとtestという文字列が消え、「表示する」ボタンをクリックすると文字列が表示される・・・と思われるかもしれませんが、このコード実はこのままでは期待した動作をしないんです。セレクタに[]が入っているので、下記のようにエスケープしてあげる必要があります。

<html>
  <head>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
  </head>
  <body>
    <p id='test'>test</p>
    <button id='button[0]'>消す</button>
    <button id ='button[1]'>表示する</button>
  </body>
  <script>
    $('#button\\[0\\]').on('click', function(){
      $('#test').hide();
    })
    $('#button\\[1\\]').on('click', function(){
      $('#test').show();
    })
  </script>
</html>

理由

なぜエスケープする必要があるのでしょうか?
以下公式より

To use any of the meta-characters as a literal part of a name, it must be escaped with with two backslashes: \. For example, an element with id="foo.bar", can use the selector $("#foo\.bar").

公式曰く、「メタ文字など  !"#$%&'()*+,./:;<=>?@[]^`{|}~ を名前のリテラル部分として使用するには、2つのバックスラッシュを使用してエスケープする必要があります。」とのことです。

どうすればいいか

本来はエスケープする必要がないように記述するべきだと思います。
ただもし特殊文字を使用したい場面があった場合、エスケープする必要があるとはいえ記述時にバックスラッシュを2つ入れるのは面倒ですし、可読性が落ちる原因にもなりそうです。エスケープする関数を作りそっちで対応する方がいいと思います。

function selectorEscape(val){
    return val.replace(/[ !"#$%&'()*+,.\/:;<=>?@\[\\\]^`{|}~]/g, '\\$&');
}

さっきのコードに加えるとしたらこんな感じですね

<html>
  <head>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
  </head>
  <body>
    <p id='test'>test</p>
    <button id='button[0]'>消す</button>
    <button id ='button[1]'>表示する</button>
  </body>
  <script>
    $('#' + selectorEscape('button[0]')).on('click', function(){
      $('#test').hide();
    })
    $('#' + selectorEscape('button[1]')).on('click', function(){
      $('#test').show();
    })

    function selectorEscape(val){
      return val.replace(/[ !"#$%&'()*+,.\/:;<=>?@\[\\\]^`{|}~]/g, '\\$&');
    }
  </script>
</html>

まとめ

セレクタには極力特殊文字は使わないようにするべきですが、どうしても使いたい場合はバックスラッシュ2つ\\でエスケープするのを忘れないようにしましょう。
私はこの問題にハマって数時間無駄にしてしまったので、この記事を読むことによって2度と私のような人が現れないことを祈っています。

参考

jQueryセレクタのエスケープ
公式

8
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?