public
Created

jQuery Plugin: Table of Contents with Smooth Scrolling

  • Download Gist
jquery.stoc.js
JavaScript
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
/**
* jQuery Plugin: Table of Contents with Smooth Scrolling
* @link http://www.1stwebdesigner.com/css/jquery-plugin-smooth-scrolling/
* @author Rochester Oliveira
*/
 
(function($){
$.fn.stoc = function(options) {
//Our default options
var defaults = {
search: "body", //where we will search for titles
depth: 6, //how many hN should we search
start: 1, //which hN will be the first (and after it we go just deeper)
stocTitle: "<h2>Contents</h2>", //what to display before our box
listType: "ul", //could be ul or ol
smoothScroll: 1,
beforeText: "", // can add <span class="text-class">
afterText: "" // can add </span> to match beforeText
};
 
//let's extend our plugin with default or user options when defined
var options = $.extend(defaults, options);
 
return this.each(function() {
//"cache" our target and search objects
obj = $(this); //target
src = $(options.search); //search
// if container is not found.
if (!src || 0 === src.length) {
return;
}
 
//let's declare some variables. We need this var declaration to create them as local variables (not global)
var appHTML = "",
tagNumber = 0,
txt = "",
id = "",
beforeText = options.beforeText,
afterText = options.afterText,
previous = options.start,
start = options.start,
depth = options.depth,
i = 0,
srcTags = "h" + options.start,
cacheHN = "";
 
//which tags we will search
while ( depth > 1) {
start++; //we will just get our start level and numbers higher than it
srcTags = srcTags + ", h" + start;
depth--; //since went one level up, our depth will go one level down
}
 
// if the target is not found
var found = src.find(srcTags);
if (!found || 0 === found.length) {
return;
}
found.each(function() {
//we will cache our current H element
cacheHN = $(this);
//if we are on h1, 2, 3...
tagNumber = ( cacheHN.get(0).tagName ).substr(1);
 
//sets the needed id to the element
id = cacheHN.attr('id');
if (id == "" || typeof id === "undefined") { //if it doesn't have only, of course
id = "h" + tagNumber + "_" + i;
cacheHN.attr('id', id);
}
//our current text
txt = beforeText + cacheHN.text() + afterText;
 
// apologize for this variable, I needed it for my localhost
var pathname = window.location.pathname;
 
switch(true) { //with switch(true) we can do comparisons in each case
case (tagNumber > previous) : //it means that we went down one level (e.g. from h2 to h3)
appHTML = appHTML + "<" + options.listType +"><li><a href=\"" + pathname + "#"+ id + "\">" + txt + "</a>";
previous = tagNumber;
break;
case (tagNumber == previous) : //it means that stay on the same level (e.g. h3 and stay on it)
appHTML = appHTML + "</li><li><a href=\"" + pathname + "#"+ id + "\">" + txt + "</a>";
break;
case (tagNumber < previous) : //it means that we went up but we don't know how much levels (e.g. from h3 to h2)
while(tagNumber != previous && (previous-tagNumber == 1)) {
appHTML = appHTML + "</" + options.listType +"></li>";
previous--;
}
appHTML = appHTML + "<li><a href=\"" + pathname + "#"+ id + "\">" + txt + "</a>";
break;
}
i++;
});
//corrects our last item, because it may have some opened ul's
while(tagNumber != options.start) {
appHTML = appHTML + "</" + options.listType +">";
tagNumber--;
}
//append our html to our object
appHTML = options.stocTitle + "<"+ options.listType + ">" + appHTML + "</" + options.listType + ">";
obj.append(appHTML);
 
// our pretty smooth scrolling here
// actually I've just compressed the code so you guys will think that I'm the man .
// Source: http://css-tricks.com/snippets/jquery/smooth-scrolling/
if (options.smoothScroll == 1) {
$(window).load(function(){
function filterPath(string){
return string.replace(/^\//,'').replace(/(index|default).[a-zA-Z]{3,4}$/,'').replace(/\/$/,'')
}
var locationPath=filterPath(location.pathname);
var scrollElem=scrollableElement('html','body');
obj.find('a[href*=#]').each(function(){
var thisPath=filterPath(this.pathname)||locationPath;
if(locationPath==thisPath&&(location.hostname==this.hostname||!this.hostname)&&this.hash.replace(/#/,'')){
var $target=$(this.hash),target=this.hash;
if(target){
var targetOffset=$target.offset().top;
$(this).click(function(event){
event.preventDefault();
$(scrollElem).animate({
scrollTop:targetOffset
},400,function(){
location.hash=target
})
})
}
}
});
function scrollableElement(els){
for(var i=0,argLength=arguments.length;i<argLength;i++){
var el=arguments[i],$scrollElement=$(el);
if($scrollElement.scrollTop()>0){
return el
}else{
$scrollElement.scrollTop(1);
var isScrollable=$scrollElement.scrollTop()>0;
$scrollElement.scrollTop(0);
if(isScrollable){
return el
}
}
}
return[]
}
});
}
});
};
})(jQuery);

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.