みちのえきまにあ

CBR1000RRで道の駅巡りをしているまったりツーリングライダーのブログ

【続編】目次と見出しの間をヌルっと移動できるようにしました

はい、どうもです。
以前にブログの目次と見出しの間をヌルっと移動できるjsを紹介しましたが、今回はその続編、改良版です。
前回同様にコピペですぐ使えますので、ぜひ使ってみてください。



改良するに至った経緯

以前に紹介したjsでは、ブログを書く際にいちいち目次部分のhtmlを記述する必要がありました。

www.michinoeki-mania.com

ここで書いている「ブログを書く際の注意点」という部分です。
見出しの分だけ目次部分にliタグを追加していくという作業が必要で、正直この作業は非常に面倒です。

そこで、見出しさえ作れば勝手に目次を生成してくれるようなスクリプトを作ろうとしていたのですが、なんと! はてなブログにはその機能がデフォルトで備わっていました。

PCでブログを書かれている方なら既にご存じの方も多いかと思いますが、ブログ記事作成画面のこのアイコンをクリックすると、目次用の要素が挿入されます。

f:id:michimani:20170405231912j:plain

たったこれだけの操作で、記事中に作成した見出しをもとにして目次を作ってくれるんです。
こんな便利な機能があったとは...。

ただしこの機能で作った目次では、各見出しへ移動する際に「ヌルっ」と移動するのではなく「パッ」と画面が切り替わるように移動します。
別ページへ移動する場合ならいいのですが、同じページの別の場所へ移動する(スクロールする)わけなので、移動する過程が見えたほうが今見ている場所を見失わなくていいんじゃないかと、個人的には思います。
よく企業などのページでも、リンクをクリックして別画面に遷移したと思ったら、実は同じページ内で表示位置が変わっていただけ、みたいなパターンがありますが、正直あの動きは好きじゃないですね。

ということで、今回はデフォルトで用意されている目次生成機能に対応するよう改良してみました。


改良後のソース

では、さっそくソースを見てみましょう。

<script>
  $(document).ready(function(){
    // 見出しタグにclass追加
    $(".entry-content h1").addClass("content-h");
    $(".entry-content h2").addClass("content-h");
    $(".entry-content h3").addClass("content-h");
    $(".entry-content h4").addClass("content-h");
    $(".entry-content h5").addClass("content-h");
  
    // 「目次」表示
    $(".table-of-contents").before('<div class="contents-table"></div>');
    $("<h3>目次</h3>").appendTo(".contents-table");
  
    // 目次リストをdiv内に移動・リンク削除・class追加
    $(".table-of-contents").appendTo(".contents-table");
    $(".table-of-contents li a").removeAttr("href");
    $(".table-of-contents li").addClass("ct-list-item");
  
    // 各見出しの後ろに目次に戻るアイコン追加
    var backToCt = "<div class='back-to-ct'><i class='blogicon-chevron-up'></i></div>";
    var $cth = $(".content-h");
    $(".content-h").append(backToCt);
  
     // 目次クリック時
    $(".ct-list-item a").click(function(){
      var idx = $(".ct-list-item a").index(this);
  
      var rect = $cth[idx].getBoundingClientRect();
      var position = rect.top + window.pageYOffset - 45;
  
      scrollToPosition(position);
    });
  
    // 目次へ戻る
    $(".back-to-ct").click(function(){
      var $cth = $(".table-of-contents");
      var position = 45;
      if ($cth.length > 0) {
        var rect = $cth[0].getBoundingClientRect();
        position = rect.top + window.pageYOffset - 45;
      }
  
      scrollToPosition(position);
    });
  
    function scrollToPosition(position) {
      $("html,body").animate({
        scrollTop : position
        }, {
        queue : false
      });
    }
  });
</script>

改良点


主な改良点としては、デフォルトの目次生成機能への対応はもちろんですが、一番大きいのはh1〜h5タグに対応した点です。

はてなでブログを書いている方はご存知かと思いますが、はてなブログの記法には以下の3つのモードがあります。

  • 見たままモード
  • はてな記法モード
  • Markdownモード

で、見たままモードで書いている方は、おそらく見出しを作成する際にツールバーの「見出し」から作成しているかと思いますが、実はこれで作成される見出しは h3〜h5 だったんです。

僕はいつもMarkdownモードで書いていて、基本的に # (h1)、もしくは ## (h2) しか使用しないので、以前のソースでも h1とh2にしか対応していませんでした。
今回の改良で h1〜h5まで対応したので、ツールバーの「見出し」から見出しを作っている場合でも問題なく動作するようになりました。

設置方法


設置方法ですが、まず前提として jQuery が読み込まれている必要があります。
読み込まれていない方は以下のソースも一緒に追記してください。

<script src="https://cdn.blog.st-hatena.com/js/external/jquery.min.js?version=1.12.3"></script>

設置場所は、 ダッシュボード>設定>詳細設定headに要素を追加 部分です。

f:id:michimani:20170405234701j:plain

コピペの順番としては、jQueryを一番上に、その下に今回のソースを貼り付けてください。

ブログを書くときの注意点


特にありません。

今まで通り好きなように見出しを作ってもらって、目次を表示したい部分にデフォルトの目次生成機能で目次要素を追加してもらえば、あとはいい感じに表示されて、目次と見出しの間をヌルっと移動できます。

一応自分のブログ内で動作確認はできていますが、もし何かあれば教えてください。