Created
March 7, 2016 11:51
-
-
Save nfq/1e1c2a4d1f66e2446e8e to your computer and use it in GitHub Desktop.
stroll.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*! | |
* Stroll v1.0.0: Scroll progress bar and anchor points | |
* (c) 2016 Nathan Querido | |
* MIT License | |
* http://github.com/nfq/stroll | |
*/ | |
(function (root, factory) { | |
if ( typeof define === 'function' && define.amd ) { | |
define([], factory(root)); | |
} else if ( typeof exports === 'object' ) { | |
module.exports = factory(root); | |
} else { | |
root.stroll = factory(root); | |
} | |
})(typeof global !== 'undefined' ? global : this.window || this.global, function (root) { | |
//'use strict'; | |
// | |
// Variables | |
// | |
var stroll = {}; // Object for public APIs | |
var supports = 'querySelector' in document && 'addEventListener' in root && 'classList' in document.createElement('_'); // Feature test | |
var settings; | |
// Default settings | |
var defaults = { | |
wrapper: '.progress_indicator', | |
progress: '.progress_bar', | |
highlight: '.progress_bar_highlight', | |
position: 'right', | |
section: "section", | |
pagination: true, | |
initClass: 'js-stroll', | |
callback: function () {} | |
}; | |
// | |
// Methods | |
// | |
/** | |
* A simple forEach() implementation for Arrays, Objects and NodeLists. | |
* @private | |
* @author Todd Motto | |
* @link https://github.com/toddmotto/foreach | |
* @param {Array|Object|NodeList} collection Collection of items to iterate | |
* @param {Function} callback Callback function for each iteration | |
* @param {Array|Object|NodeList} scope Object/NodeList/Array that forEach is iterating over (aka `this`) | |
*/ | |
var forEach = function ( collection, callback, scope ) { | |
if ( Object.prototype.toString.call( collection ) === '[object Object]' ) { | |
for ( var prop in collection ) { | |
if ( Object.prototype.hasOwnProperty.call( collection, prop ) ) { | |
callback.call( scope, collection[prop], prop, collection ); | |
} | |
} | |
} else { | |
for ( var i = 0, len = collection.length; i < len; i++ ) { | |
callback.call( scope, collection[i], i, collection ); | |
} | |
} | |
}; | |
/** | |
* Merge two or more objects. Returns a new object. | |
* @private | |
* @param {Boolean} deep If true, do a deep (or recursive) merge [optional] | |
* @param {Object} objects The objects to merge together | |
* @returns {Object} Merged values of defaults and options | |
*/ | |
var extend = function () { | |
// Variables | |
var extended = {}; | |
var deep = false; | |
var i = 0; | |
var length = arguments.length; | |
// Check if a deep merge | |
if ( Object.prototype.toString.call( arguments[0] ) === '[object Boolean]' ) { | |
deep = arguments[0]; | |
i++; | |
} | |
// Merge the object into the extended object | |
var merge = function (obj) { | |
for ( var prop in obj ) { | |
if ( Object.prototype.hasOwnProperty.call( obj, prop ) ) { | |
// If deep merge and property is an object, merge properties | |
if ( deep && Object.prototype.toString.call(obj[prop]) === '[object Object]' ) { | |
extended[prop] = extend( true, extended[prop], obj[prop] ); | |
} else { | |
extended[prop] = obj[prop]; | |
} | |
} | |
} | |
}; | |
// Loop through each object and conduct a merge | |
for ( ; i < length; i++ ) { | |
var obj = arguments[i]; | |
merge(obj); | |
} | |
return extended; | |
}; | |
/** | |
* Create DOM elements which graphically represent the progress | |
* @method _createElements | |
* @private | |
*/ | |
var _createElements = function () { | |
var wrapper = document.querySelector( settings.wrapper ); | |
var progress = document.querySelector( settings.progress ); | |
var highlight = document.querySelector( settings.highlight ); | |
progress = document.createElement('div'); | |
highlight = document.createElement('div'); | |
progress.classList.add( settings.progress ); | |
highlight.classList.add( settings.highlight ); | |
progress.appendChild( highlight ); | |
wrapper.appendChild( progress ); | |
// Progress bar highlight | |
// A links | |
// Dots | |
// Labels | |
}; | |
/** Set styles on DOM elements | |
* @method _elementStyles | |
* @private | |
*/ | |
var _elementStyles = function () { | |
}; | |
/** Section dots | |
* @method _sectionDots | |
* @private | |
*/ | |
var _sectionDots = function () { | |
var body = document.body; | |
var sections = document.querySelectorAll( settings.section ); | |
var item = JSON.parse(this.getAttribute('data-stroll')); | |
paginationList = ""; | |
// Get all sections | |
for( var i = 0; i < sections.length; i++){ | |
sections[i].dataset.index = i + 1; | |
if(settings.pagination == true) { | |
paginationList += "<li><a data-index='" + (i + 1) + "' href='#" + (item.id) + "' data-scroll><span class=\"dot\"></span><span class=\"label\">"+ (item.label) +"</span></a></li>"; | |
} | |
} | |
// This should go in _createElements | |
if(settings.pagination == true) { | |
var pagination = document.createElement("nav"); | |
pagination.setAttribute("class", "progress_indicator"); | |
body.appendChild(pagination); | |
pagination.innerHTML = paginationList; | |
//var posTop = (document.querySelector(".onepage-pagination").offsetHeight / 2) * -1; | |
//document.querySelector(".onepage-pagination").style.marginTop = posTop; | |
} | |
}; | |
/** | |
* Scroll method | |
* @method _scrollMethod | |
* @private | |
*/ | |
var _scrollMethod = function () { | |
var body = document.body; | |
var highlight = document.querySelector( settings.highlight ); | |
if (body.scrollTop) { | |
percent = (body.scrollTop/(body.scrollHeight - document.documentElement.clientHeight))*100 + '%'; | |
} else { | |
percent = (window.pageYOffset/(body.scrollHeight - document.documentElement.clientHeight))*100 + '%'; | |
} | |
if (settings.position === 'top' || settings.position === 'bottom') { | |
highlight.style.width = percent; | |
} | |
if (settings.position === 'left' || settings.position === 'right') { | |
highlight.style.height = percent; | |
} | |
}; | |
/** | |
* Handle scroll event methods | |
* @method _eventHandler | |
* @private | |
*/ | |
var _eventHandler = function ( event ) { | |
if ( event.type === 'scroll' ) { | |
_scrollMethod(); | |
} | |
}; | |
/** | |
* Destroy the current initialization. | |
* @public | |
*/ | |
stroll.destroy = function () { | |
// If plugin isn't already initialized, stop | |
if ( !settings ) return; | |
document.documentElement.classList.remove( settings.initClass ); | |
// Remove event listeners | |
document.removeEventListener('scroll', _eventHandler, false); | |
// Reset variables | |
settings = null; | |
}; | |
/** | |
* Initialize Stroll | |
* @public | |
* @param {Object} options User settings | |
*/ | |
stroll.init = function ( options ) { | |
// Feature test | |
if ( !supports ) return; | |
// Destroy any existing initializations | |
stroll.destroy(); | |
// Merge user options with defaults | |
settings = extend( defaults, options || {} ); // Merge user options with defaults | |
//_createElements(); | |
_sectionDots(); | |
// Add class to HTML element to activate conditional CSS | |
document.documentElement.classList.add( settings.initClass ); | |
// Listen for scroll events and run event handler | |
document.addEventListener('scroll', _eventHandler, false); | |
}; | |
// | |
// Public APIs | |
// | |
return stroll; | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment