
縦長のHTMLコンテンツで下にスクロールした時にそのスクロール位置によって
目次のリンクにselectedクラスをDOMで追加し、現在どの部分を表示しているのかを視覚的にわかりやすくしたいのですが、
方法がわからず悩んでおります。そもそもHTMLの構造的に可能どうかもわからない素人ですが、どなたかご教授頂きたいと存じます。
現在のHTMLの構造は、
コンテンツのHTMLの前に目次の記述があり、その目次部分はposition:fixedで常に見える位置に表示してあります。
構造を簡単にしますと以下のようになっております。
<!-- 目次 START -->
<div id="toc">
<ul class="toc">
<li class="toc_lebel_1">
<a href="#見出し1"> class="toc">見出し1</a>
</li>
<li class="toc_lebel_1">
<a href="#見出し2"> class="toc">見出し2</a>
</li>
<li class="toc_lebel_1">
<a href="#見出し3"> class="toc">見出し3</a>
</li>
</ul>
</div>
<!-- 目次 END -->
<!-- コンテンツ START -->
<h1>
<a name="見出し1" id="見出し1">見出し1</a>
</h1>
・・・
<h2>
<a name="見出し2" id="見出し2">見出し2</a>
</h2>
・・・
<h2>
<a name="見出し3" id="見出し3">見出し3</a>
</h2>
・・・
<!-- コンテンツ END -->
このページはかなり縦長のページになっており、下にスクロールした際に現在表示している位置(例えば、見出し1と見出し2の間を表示している場合の位置)によって
目次の該当箇所の<a>タグにselectedのようなクラスを追加したいです。
よろしくお願いします。
No.1ベストアンサー
- 回答日時:
こんばんは、
こんなかんじでしょうか? ie では、うごきません。firefox でうごきました。
Array.reduce, document.querySelector(All), classList がつかえないとだめです。
いちのかんちは、たいまーをつかいました。
ぜんかくくうはくは、はんかくにしてください。
<!DOCTYPE html>
<title></title>
<meta charset="UTF-8"/>
<style>
body {
padding-left:8em;
}
#toc {
position:fixed;
left : 0;
}
p {
height : 20em;
}
a.selected {
border-bottom: 2px red solid;
color : red;
}
</style>
<body>
<div id="toc">
<ul class="toc">
<li class="toc_lebel_1">
<a href="#見出し1" class="toc selected">見出し1</a>
<li class="toc_lebel_1">
<a href="#見出し2" class="toc">見出し2</a>
<li class="toc_lebel_1">
<a href="#見出し3" class="toc">見出し3</a>
</ul>
</div>
<h1 id="見出し1">見出し1</h1>
<p>1<p>2<p>3<p>4<p>5
<h2 id="見出し2">見出し2</h2>
<p>1<p>2<p>3<p>4<p>5
<h2 id="見出し3">見出し3</h2>
<p>1<p>2<p>3<p>4<p>5
<script>
//対象のアンカータグを集める
var a = document.querySelectorAll ('div#toc > ul > li > a');
//対象のstyle.top の絶対値を求める
var b = function (c) {
for (var d = 0; c; c = c.offsetParent)
d += c.offsetTop;
return d;
};
//aで集めた.helf をidとした要素を集め、b() を求め、配列にする
var c = Array.prototype.reduce.call (a, function (d, e) {
var f = e.getAttribute ('href'), g;
if (/^#.+$/.test (f))
if (g = document.querySelector (f))
d.push ({ e: e, height: b (g) });
return d;
}, []);
var offset = 20;
var d = function () {
var f = 0, g = window.pageYOffset + offset, h;
for (var i = c.length; h = c[--i]; )
h.e.classList[(f += h.height <= g) === 1 ? 'add': 'remove']('selected');
};
setInterval (d, 500);
</script>
この回答への補足
babu_babooさん
困ったことにDOMが正常に動作するページと同じような構造のHTMLでありながら
結果が異なるページがあるのです。
そのページを読み込むとdiv#toc内のすべてのaがselectedになった状態で表示されてしまいます。
下にスクロールしていくと上の方から徐々にselectedが解除されていきます。
キャッシュをクリアし、何度読込しても特定の数ページだけ必ずそのような状態になります。
何か良い対処法はないでしょうか??
babu_babooさん
はじめましてこんばんわ!
早速ご回答くださいましてありがとうございます。
スクリプトを手前のHTMLで試してみましたが問題なく動作しております。
babu_babooさんの仰る通りIE9では動きませんでしたがchromeとOperaでは動きました。
質問の時にメジャーなライブラリ(Jqueryなど)を利用する場合でもOKですと記載するのを忘れていたのですが
そんなことも必要なくとても感動です。
querySelectorAllのところを少し変えるだけで他のサイトにも流用出来そうで非常に満足です。
他の方のご教授がなければこの質問は本日中に締め切りとさせていただきます。
No.3
- 回答日時:
まいかい おもいつきで すみません。
setInterval のまえに、いかの いちぶんを じっこうしてみてはどうだろうか?
Array.prototype.slice.call (document.getElementsByClassName ('selected'), 0).forEach (function (e) { e.classList.remove ('selected'); });
babu_babooさん
自サイトでいろいろとテストしてみると、CMSに使用しているプラグインが影響しているようでした。
このプラグインをOFFにすると問題なく該当のページ全てが正常にDOMが動くようになりました。
なので当面はこのプラグインを使用せず運用していこうと考えております。
それとは別に自サイトの訪問者のブラウザを調べてみるとIE使用者が7割りを超えている状況でしたので
今回のDOMについては時間があるときにbabu_babooさんにご教授頂いた手法を参考にIE対応出来るようにシたいと考えております。
改めてありがとうございました。
No.2
- 回答日時:
おはようございます。
すいしょうをながめてみます。
a,b は、c のためにあり、c は、そのごへんかしません。
>下にスクロールしていくと上の方から徐々にselectedが解除
と、あるので c はせいじょう。
なので、うがたがうは しょきのよみこみだんかいでおこなわれているとすいそく。
'selected' がついたままの、あんかーを node.cloneNode などをつかってこぴーしている。
h.e.classList[(f += h.height <= g) === 1 ? 'add': 'remove']('selected');
これは、かさんされていく f が、1 の場合のみ設定されるものであり、むしろ remove のほうがおおい。
css で、たかさのしていがないものをつかっている?
float だとか…
けつろん!
よくわからない。ごめん。
--
あと、23歳OL女子ならゆるせるが
Syntax error 'こんばんわ!'
あっ!ふだん えらーを りょうさんするのは、俺かっ。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
別フレームからの背景の変更
-
Jquery タブで、4つのliのうち...
-
同一ページ内で、任意の文字列...
-
JQueryタブのアクティブ アン...
-
jQuery UIを使用した画像スライ...
-
jquery sortableについて
-
「jQuery」アコーディオンメニ...
-
どの<li><a> が押されたか判別...
-
別ページのインラインフレーム...
-
jqueryのsortableで一部ソート...
-
javascriptで正規表現の検索が...
-
javascript テキストエリアを1...
-
MAX関数を使ってからLEFT JOIN...
-
JavaScriptで変更した属性の元...
-
c++std::string型をTCHARに変換...
-
jQueryで4枚の画像がフェードア...
-
行間
-
スタイルシートで画面を上下に...
-
指定したセルに表示
-
Livedoorのような画面の横につ...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
jqueryのsortableで一部ソート...
-
タブ切り替えの初期表示について
-
クリックした<a>タグのみにClas...
-
【javascript で動的に a タグ...
-
JQueryタブのアクティブ アン...
-
jQueryのhide,showで中の要素が...
-
JS <a></a>タグ内のリンク先ア...
-
javascriptで教えてください。 ...
-
ネストされたチェックボックス...
-
div要素をランダムに表示させたい
-
jquery ドロップダウンメニュー...
-
同一ページ内で、任意の文字列...
-
onMouseoutの有効な範囲
-
macromediaのようなメニュー
-
mootoolsを使ったドロップダウ...
-
tableやul,liで表示されたリス...
-
jQueryのeqで最後からn番目以降...
-
javascript, getElementsByTagN...
-
jQuery タブメニューへのダイ...
-
【jQuery】遅延実行(タイムラ...
おすすめ情報