123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156 |
- (function (root, factory) {
- if (typeof define === 'function' && define.amd) {
- // AMD. Register as an anonymous module unless amdModuleId is set
- define([], function () {
- return (root['ScrollSpy'] = factory());
- });
- } else if (typeof exports === 'object') {
- // Node. Does not work with strict CommonJS, but
- // only CommonJS-like environments that support module.exports,
- // like Node.
- module.exports = factory();
- } else {
- root['ScrollSpy'] = factory();
- }
- }(this, function () {
- /**
- * ScrollSpy
- *
- */
- function ScrollSpy (wrapper, opt) {
- var doc = document;
- this.wrapper = doc.querySelector(wrapper);
- this.nav = this.wrapper.querySelectorAll(opt.nav);
- this.contents = [];
- this.win = window;
- this.body = doc.body;
- this.winH = this.win.innerHeight;
- this.className = opt.className;
- this.callback = opt.callback;
- this.init();
- }
- ScrollSpy.prototype.init = function () {
- this.contents = this.getContents();
- this.attachEvent();
- };
- ScrollSpy.prototype.getContents = function () {
- var targetList = [];
- for (var i = 0, max = this.nav.length; i < max; i++) {
- var href = this.nav[i].href;
- targetList.push(document.getElementById(href.split('#')[1]));
- }
- return targetList;
- };
- ScrollSpy.prototype.attachEvent = function () {
- this.win.addEventListener('load', (function () {
- this.spy(this.callback);
- }).bind(this));
- var scrollingTimer;
- this.win.addEventListener('scroll', (function () {
- if (scrollingTimer) {
- clearTimeout(scrollingTimer);
- }
- var _this = this;
- scrollingTimer = setTimeout(function () {
- _this.spy(_this.callback);
- }, 10);
- }).bind(this));
- var resizingTimer;
- this.win.addEventListener('resize', (function () {
- if (resizingTimer) {
- clearTimeout(resizingTimer);
- }
- var _this = this;
- resizingTimer = setTimeout(function () {
- _this.spy(_this.callback);
- }, 10);
- }).bind(this));
- };
- ScrollSpy.prototype.spy = function (cb) {
- var elems = this.getElemsViewState();
- this.markNav(elems);
- if (typeof cb === 'function') {
- cb(elems);
- }
- };
- ScrollSpy.prototype.getElemsViewState = function () {
- var elemsInView = [],
- elemsOutView = [],
- viewStatusList = [];
- for (var i = 0, max = this.contents.length; i < max; i++) {
- var currentContent = this.contents[i],
- isInView = this.isInView(currentContent);
- if (isInView) {
- elemsInView.push(currentContent);
- } else {
- elemsOutView.push(currentContent);
- }
- viewStatusList.push(isInView);
- }
- return {
- inView: elemsInView,
- outView: elemsOutView,
- viewStatusList: viewStatusList
- };
- };
- ScrollSpy.prototype.isInView = function (el) {
- var winH = this.winH,
- scrollTop = this.body.scrollTop,
- scrollBottom = scrollTop + winH,
- elTop = el.offsetTop,
- elBottom = elTop + el.offsetHeight;
- return (elTop < scrollBottom) && (elBottom > scrollTop);
- };
- ScrollSpy.prototype.markNav = function (elems) {
- var navItems = this.nav,
- isAlreadyMarked = false;
- for (var i = 0, max = navItems.length; i < max; i++) {
- if (elems.viewStatusList[i] && !isAlreadyMarked) {
- isAlreadyMarked = true;
- navItems[i].classList.add(this.className);
- } else {
- navItems[i].classList.remove(this.className);
- }
- }
- };
- return ScrollSpy;
- }));
|