記事の見出し(h2とh3)をもとに、開閉できる目次を生成してスクロールでその項目へ移動するUI -『javascript』

ブログなど長めの記事で多用するUI。

javascript


var generateToc = function generateToc(target) {

  if (target.length) {
    (function () {

      var toc = $('<section class="toc"></section>'),
            title = $('<h2 class="toc_title">toc<br>ー</h2>'),
            ul = $('<ul class="toc_list"></ul>'),
            html = toc.prepend(title),
            h2 = target.find('h2'),
            anchorName = 'section',
            text = void 0,
            childText = void 0;

      // - -
      // create list item
      // - - - - - - - - -
      var createItem = function createItem() {

        h2.each(function (index, val) {

          var child = $('<ul class="toc_child"></ul>'),
                anchorId = anchorName + index;

          $(val).attr('id', anchorId).nextUntil('h2').filter('h3').each(function (ci, cv) {

            var anchorChildId = anchorId + '-' + ci;

            childText = $(cv).attr('id', anchorChildId).html();
            $('<li class="toc_item-child"></li>').text(childText).appendTo(child).wrapInner(function () {
              return '<a class="toc_target" href="#' + anchorChildId + '"></a>';
            });
          });

          text = $(val).html();
          $('<li class="toc_item"></li>').wrapInner(function () {
            return '<a class="toc_target" href="#' + anchorId + '">' + text + '</a>';
          }).appendTo(ul).append(child);
        });
      };
      createItem();

      // - -
      // insert toc
      // - - - - - - - - -
      var insertToc = function insertToc() {

        if (ul.find('li').length > 1) {

          html.append(ul);
          target.before(html);

        }
      };
      insertToc();

      // - -
      // toggle button
      // - - - - - - - - - -
      var clickBtn = function clickBtn() {

        title.on('click', function () {

          toc.toggleClass('is-active');
          ul.slideToggle(250);
        });
      };
      clickBtn();

      // - -
      // page scroll
      // - - - - - - - - - -
      var scroll = function scroll() {

        toc.find('a').on('click', function (e) {

          var anchor = $(this.hash),
                time = 550,
                topDistance = 15,
                anchorOffset = anchor.offset().top - topDistance;

          $('html,body').animate({
            scrollTop: anchorOffset
          }, {
            duration: time
          }, 'easeOutCubic');
        });
      };
      scroll();
    })();
  }
};
generateToc($('#js-toc'));

share
ー

related
ー