0
1

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 5 years have passed since last update.

bootstrap scrollspyが数値始まりのidの影響で誤動作していた

Posted at

bootstrapのscrollspyを使って、いい感じにマーカつけてやろう、
とか思ってたのに、一部のマーカ位置がハイライトされなかった話。

だめな例

以下のようなHTMLを書く。
(bootstrapのサンプル改変)

<div id="list-example" class="list-group">
  <a class="list-group-item list-group-item-action" href="#first">Item 1</a>
  <a class="list-group-item list-group-item-action" href="#second">Item2</a>
  <a class="list-group-item list-group-item-action" href="#3rd">Item 3</a>
  <a class="list-group-item list-group-item-action" href="#fourth">Item 4</a>
</div>
<div data-spy="scroll" data-target="#list-example" data-offset="0" class="scrollspy-example">
  <h4 id="first">Item 1</h4>
  <p>...</p>
  <h4 id="second">Item 2</h4>
  <p>...</p>
  <h4 id="3rd">Item 3</h4>
  <p>...</p>
  <h4 id="fourth">Item 4</h4>
  <p>...</p>
</div>

このとき、scrollspyを利用し、画面スクロールさせると

  • first
    • activeつく
  • second
    • activeつく
  • 3rd
    • activeつかない
  • fourth
    • activeつく

となる。

原因

bootstrap.jsを見てみる。

      var _proto = ScrollSpy.prototype;
...
      _proto.refresh = function refresh() {
...
        this._targets = [];
        this._scrollHeight = this._getScrollHeight();
        var targets = [].slice.call(document.querySelectorAll(this._selector));
        targets.map(function (element) {
          var target;
          var targetSelector = Util.getSelectorFromElement(element);

          if (targetSelector) {
            target = document.querySelector(targetSelector);
          }
          if (target) {
              return オブジェクト省略
          }

          return null;
        })

と、

          var targetSelector = Util.getSelectorFromElement(element);

でselectorを取得しに行っていて、
Util.getSelectorFromElementは

      getSelectorFromElement: function getSelectorFromElement(element) {
        var selector = element.getAttribute('data-target');

        if (!selector || selector === '#') {
          selector = element.getAttribute('href') || '';
        }

        try {
          return document.querySelector(selector) ? selector : null;
        } catch (err) {
          return null;
        }
      },

のように

selector = element.getAttribute('href') || '';
return document.querySelector(selector) ? selector : null;

としてselectorを確認する。

このとき、selectorが数値始まりだと、

VM8638:1 Uncaught DOMException: Failed to execute 'querySelector' on
 'Document': '#3rd' is not a valid selector.

のように怒られる。

これは、CSSセレクタでは数値始まりのIDやクラスはNGだからのようです。

In CSS, identifiers (including element names, classes, and IDs in selectors) 
can contain only the characters [a-zA-Z0-9] and ISO 10646 characters U+0080 
and higher, plus the hyphen (-) and the underscore (_); 
they cannot start with a digit, two hyphens, or a hyphen followed by a digit. 

ちなみにjQueryでは数値始まりのセレクタでも持ってきてくれた。
jQuery尊い。

0
1
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
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?