悬挂目录Affix table of contents

2017-04-12 09:25:00   技术   javascript jquery bootstrapt

这个东西其实在django版本的时候我已经弄过了,但是在各种博客的迁移过程中没有一起搬上来

现在放在这里主要是记录一些代码,万一以后还要搬迁呢

查找header并生成列表

来自于sinaapp的django版本(Sinaapp\gutools\1\static\js\blog_post.js)

当中的查嵌套header的逻辑是当时的我写的,现在不高兴Review了,反正可以用就行

var headers = $("#blog_content").find("h1,h2,h3,h4,h5,h6");
var maxHead = 6;
for (var i = 0; i < headers.length; i++) {
  var currentHead = parseInt(headers[i].tagName[1]);
  if (currentHead < maxHead) {
    maxHead = currentHead;
  }
}

var links = $("<ol></ol>").attr("id", "affix-nav-ul").attr("class", "nav nav-stacked").attr("role", "tablist");
var currentParent = links;
var lastLi = null;
var currentClass = maxHead;

for (var i = 0; i < headers.length; i++) {
  var currentHead = parseInt(headers[i].tagName[1]);
  if (currentHead > currentClass) {
    while (currentHead > currentClass) {
      var newUl = $("<ol></ol>");
      if (lastLi != null){
        lastLi.append(newUl)
      } else {
        currentParent.append(newUl);
      }
      currentClass += 1;
      currentParent = newUl;
    }
  } else if (currentHead < currentClass) {
    while (currentHead < currentClass) {
      currentClass -= 1;
      currentParent = currentParent.parent().parent();
    }
  }
  lastLi = $("<li></li").append($("<a></a>").attr("href", "#" + headers[i].id).text($(headers[i]).text()));
  currentParent.append(lastLi);
}

bootstrapt 相关的绑定affix部分

里面取位置主要还是用了outerHeight

最后body上安放监控居然是用add attr(我也不知道当时是怎么想的)

Sinaapp\gutools\1\static\js\blog_post.js:

$('#affix-nav').affix({
  offset: {
    top: function() {
      return (this.top = $('#top').outerHeight(true) + $('#right_standard').outerHeight(true));
    },
    bottom: function() {
      return (this.bottom = $('#bottom').outerHeight(true) + 20);
    }
  }
})

$('.affix-top').width($('#right_standard').width());
$('.affix').width($('#right_standard').width());

$(window).resize(function() {
  $('.affix').width($('#right_standard').width());
});

$(window).scroll(function() {
  $('.affix').width($('#right_standard').width());
});
   
$("body").attr("data-spy", "scroll");
$("body").attr("data-target", "#affix-nav");

然后是养龙结婚证的数据页面上用的代码,基本上是复用,不过一开始没直接迁移过来:

$("body").attr("data-spy", "scroll");

$('#affix-nav').affix({
    offset: {
        top: function() {
            return (this.top = $('#top').outerHeight(true));
        },
        bottom: function() {
            return (this.bottom = $('#bottom').outerHeight(true) + 20);
        }
    }
})

$('.affix-top').width($('#stand').width());
$('.affix').width($('#stand').width());

$(window).resize(function() {
    $('.affix').width($('#stand').width());
});

$(window).scroll(function() {
    $('.affix').width($('#stand').width());
});

affix相关的css

django版本的时候就写了的

关于缩进的部分写的好烂啊哈哈哈……

.affix {
  top: 20px;
}

.affix-bottom{
  position: absolute;
}

#affix-nav-ul ol{
  padding-left: 0px;
}

#affix-nav-ul li{
    position: relative;
    display: block;
    margin: 0px;
    background-color: #e9f0f6;
    padding: 0px;
    overflow:hidden;
}

#affix-nav-ul li > a {
    position: relative;
    display: block;
    padding: 10px 15px;
    white-space: nowrap;
    border-top: 1px solid #a1afc9;
}

#affix-nav-ul > li:first-child {
    border-top-right-radius: 4px;
    border-top-left-radius: 4px;
}

#affix-nav-ul > li:first-child > a {
    border-top-width: 0;
}

#affix-nav-ul > li:last-child {
    margin-bottom: 0px;
    border-bottom-width: 0;
    border-bottom-right-radius: 4px;
    border-bottom-left-radius: 4px;
}

#affix-nav-ul li.active > a, 
#affix-nav-ul li.active > a:hover, 
#affix-nav-ul li.active > a:focus {
  color: #161824;
  text-shadow: 1px 1px 1px #88ada6;
  font-weight: bold;
}

#affix-nav-ul > li > ol > li > a {
  padding-left: 25px;
}

#affix-nav-ul > li > ol > li > ol > li > a {
  padding-left: 35px;
}

#affix-nav-ul > li > ol > li > ol > li > ol > li > a {
  padding-left: 45px;
}

#affix-nav-ul > li > ol > li > ol > li > ol > li > ol > li > a {
  padding-left: 55px;
}

#affix-nav-ul > li > ol > li > ol > li > ol > li > ol > li > ol > li > a {
  padding-left: 65px;
}

#affix-nav-ul li > ol > li {
    display: none;
}

#affix-nav-ul li[class|=active] > ol > li {
    display: initial;
}

目前版本的

affix.js

触发affix

我也没想明白为什么突然就用offset().top了。。

$(function() { 
  $('#affix-nav').affix({
    offset: {
      top: function() {
        return $('#rss_nav').offset().top + $('#rss_nav').outerHeight(true);
      },
      bottom: function() {
        return $('#bottom').outerHeight(true) + 20;
      }
    }
  });
  $('#affix-nav').width($('#rss_nav').width());
  $(window).resize(function () {
    $('#affix-nav').width($('#rss_nav').width());
  });
  $(window).scroll(function() {
    $('#affix-nav').width($('#rss_nav').width());
  });
});

查找header

基本是照抄,不过有些细节不同

var headers = $("#blog_content").find("h1,h2,h3,h4,h5,h6");
var maxHead = 6;
for (var i = 0; i < headers.length; i++) {
  $(headers[i]).attr("data-localize", $(headers[i]).text());
  var currentHead = parseInt(headers[i].tagName[1]);
  if (currentHead < maxHead) {
    maxHead = currentHead;
  }
}

var links = $("<ol></ol>").attr("id", "affix-nav-ul").attr("class", "nav nav-stacked").attr("role", "tablist");

links.append(
  $("<li></li").append(
    $("<a></a>").attr("affix_to","#top").attr('href', '#top').append(
      $("<span></span>").attr("class", "glyphicon glyphicon-triangle-top")
    )
  )
);

var currentParent = links;
var lastLi = null;
var currentClass = maxHead;

for (var i = 0; i < headers.length; i++) {
  var currentHead = parseInt(headers[i].tagName[1]);
  if (currentHead > currentClass) {
    while (currentHead > currentClass) {
      var newUl = $("<ol></ol>").addClass("nav").addClass("nav-stacked");
      if (lastLi != null){
        lastLi.append(newUl)
      } else {
        currentParent.append(newUl);
      }  

      currentClass += 1;
      currentParent = newUl;
    }
  } else if (currentHead < currentClass) {
    while (currentHead < currentClass) {
      currentClass -= 1;
      currentParent = currentParent.parent().parent();
    }
  } 

  lastLi = $("<li></li>").append(
    $("<a></a>").attr("affix_to","#" + headers[i].id).attr("href", "#" + headers[i].id).attr("data-localize", $(headers[i]).text()).text($(headers[i]).text())
  );
  currentParent.append(lastLi);
}

links.append(
  $("<li></li").append(
    $("<a></a>").attr("affix_to","#comments").attr('href', '#comments').append(
      $("<span></span>").attr("class", "glyphicon glyphicon-comment")
    ).append(" 评论")
  )
);

links.append(
  $("<li></li").append(
    $("<a></a>").attr("affix_to","#bottom").attr('href', '#bottom').append(
      $("<span></span>").attr("class", "glyphicon glyphicon-triangle-bottom")
    )
  )
);

$("#affix-nav-pannel").append(links);

挂载监听

直接用了scrollspy()

$('body').scrollspy({ target: '#affix-nav-pannel' });

animate scroll to

随便弄了个scroll to的方法,把a link到锚记都覆盖了

原来的版本是不管哪儿到哪儿都是1.5秒,后来感觉太慢了,改成1秒,后来又觉得不爽,就改成了固定1500px秒的速度

其实还有点儿不爽,我是不是要写个什么奇怪的函数……

$("a[affix_to]").click(function(){
  var target = $($(this).attr("affix_to"));
  var target_offset = 0;
  if ($(this).attr("affix_to") != "#top") {
    target_offset = target.offset().top
  }

  var current_position = document.documentElement.scrollTop || document.body.scrollTop;  
  $("html,body").animate({scrollTop: target_offset}, Math.floor(Math.abs(current_position - target_offset)/1.5));
  return false;
});
评论共