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尊い。