Skip to content

Instantly share code, notes, and snippets.

@gregogalante
Last active March 5, 2018 13:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gregogalante/7265398968b117a0127a2989842e1e62 to your computer and use it in GitHub Desktop.
Save gregogalante/7265398968b117a0127a2989842e1e62 to your computer and use it in GitHub Desktop.
A module to create a sidebar sections navigation based on content titles.
var SidebarSections = (function () {
var CONTENT_CONTAINER = 'YOUR CONTENT CONTAINER SELECTOR'
var SIDEBAR_CONTAINER = 'YOUR SIDEBAR CONTAINER SELECTOR'
var _titles = []
var _titlesGroup = []
// This function is used to initialize the module.
var init = function () {
_loadTitles()
_markTitles()
_groupTitles()
_createSidebar(null, _titlesGroup)
_animateScroll()
}
var _loadTitles = function () {
var container = jQuery(CONTENT_CONTAINER)
container.children('h2, h3, h4, h5, h6').each(function (_index, value) {
_titles.push(value)
})
}
var _markTitles = function () {
for (var i = 0; i < _titles.length; i++) {
var jQueryElement = jQuery(_titles[i])
jQueryElement.attr('id', _parametize(jQueryElement.text()))
}
}
var _groupTitles = function () {
var title, level, before
for (var i = 0; i < _titles.length; i++) {
title = _titles[i]
level = parseInt(title.tagName[title.tagName.length - 1])
if (!before) {
_titlesGroup.push(_createNode(title, level, null))
before = _titlesGroup[_titlesGroup.length - 1]
continue
}
if (level > before.level) {
before.children.push(_createNode(title, level, before))
before = before.children[before.children.length - 1]
continue
}
if (level === before.level && before.parent) {
before.parent.children.push(_createNode(title, level, before.parent))
before = before.parent.children[before.parent.children.length - 1]
continue
}
if (level === before.level && !before.parent) {
_titlesGroup.push(_createNode(title, level, null))
before = _titlesGroup[_titlesGroup.length - 1]
continue
}
if(level < before.level) {
while (before !== null || (before && before.level !== level)) {
before = before.parent ? before.parent : null
}
if (!before) {
_titlesGroup.push(_createNode(title, level, null))
before = _titlesGroup[_titlesGroup.length - 1]
} else {
before.parent.children.push(_createNode(title, level, before.parent))
before = before.parent.children[before.parent.children.length - 1]
}
}
}
}
var _createSidebar = function (parent, children) {
if( !children || !children.length ) return
if (!parent) {
parent = jQuery(SIDEBAR_CONTAINER)
}
var i, l, list, li, a
list = jQuery("<ul></ul>").appendTo(parent)
for(i = 0, l = children.length; i < l; i++) {
li = jQuery("<li></li>")
jQuery("<a></a>")
.text(children[i].title.innerText)
.attr('href', '#' + children[i].title.id)
.appendTo(li)
_createSidebar(li, children[i].children)
list.append(li)
}
}
var _animateScroll = function () {
jQuery(SIDEBAR_CONTAINER + " a[href^='#']").click(function (e) {
e.preventDefault()
var position = jQuery(jQuery(this).attr("href")).offset().top - 40
jQuery("body, html").animate({
scrollTop: position
} /* speed */ )
})
}
// Helpers:
function _parametize (str) {
return str.trim().toLowerCase().replace(/[^a-zA-Z0-9 -]/, "").replace(/\s/g, "-");
}
function _createNode(title, level, parent) {
var node = {
title: title,
level: level,
parent: parent,
children: []
}
return node
}
return {
init
}
})()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment