Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <!-- header behavior -->
- <script>
- /*!
- * headroom.js v0.9.4 - Give your page some headroom. Hide your header until you need it
- * Copyright (c) 2017 Nick Williams - http://wicky.nillia.ms/headroom.js
- * License: MIT
- */
- (function(root, factory) {
- 'use strict';
- if (typeof define === 'function' && define.amd) {
- // AMD. Register as an anonymous module.
- define([], factory);
- }
- else if (typeof exports === 'object') {
- // COMMONJS
- module.exports = factory();
- }
- else {
- // BROWSER
- root.Headroom = factory();
- }
- }(this, function() {
- 'use strict';
- /* exported features */
- var features = {
- bind : !!(function(){}.bind),
- classList : 'classList' in document.documentElement,
- rAF : !!(window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame)
- };
- window.requestAnimationFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame;
- /**
- * Handles debouncing of events via requestAnimationFrame
- * @see http://www.html5rocks.com/en/tutorials/speed/animations/
- * @param {Function} callback The callback to handle whichever event
- */
- function Debouncer (callback) {
- this.callback = callback;
- this.ticking = false;
- }
- Debouncer.prototype = {
- constructor : Debouncer,
- /**
- * dispatches the event to the supplied callback
- * @private
- */
- update : function() {
- this.callback && this.callback();
- this.ticking = false;
- },
- /**
- * ensures events don't get stacked
- * @private
- */
- requestTick : function() {
- if(!this.ticking) {
- requestAnimationFrame(this.rafCallback || (this.rafCallback = this.update.bind(this)));
- this.ticking = true;
- }
- },
- /**
- * Attach this as the event listeners
- */
- handleEvent : function() {
- this.requestTick();
- }
- };
- /**
- * Check if object is part of the DOM
- * @constructor
- * @param {Object} obj element to check
- */
- function isDOMElement(obj) {
- return obj && typeof window !== 'undefined' && (obj === window || obj.nodeType);
- }
- /**
- * Helper function for extending objects
- */
- function extend (object /*, objectN ... */) {
- if(arguments.length <= 0) {
- throw new Error('Missing arguments in extend function');
- }
- var result = object || {},
- key,
- i;
- for (i = 1; i < arguments.length; i++) {
- var replacement = arguments[i] || {};
- for (key in replacement) {
- // Recurse into object except if the object is a DOM element
- if(typeof result[key] === 'object' && ! isDOMElement(result[key])) {
- result[key] = extend(result[key], replacement[key]);
- }
- else {
- result[key] = result[key] || replacement[key];
- }
- }
- }
- return result;
- }
- /**
- * Helper function for normalizing tolerance option to object format
- */
- function normalizeTolerance (t) {
- return t === Object(t) ? t : { down : t, up : t };
- }
- /**
- * UI enhancement for fixed headers.
- * Hides header when scrolling down
- * Shows header when scrolling up
- * @constructor
- * @param {DOMElement} elem the header element
- * @param {Object} options options for the widget
- */
- function Headroom (elem, options) {
- options = extend(options, Headroom.options);
- this.lastKnownScrollY = 0;
- this.elem = elem;
- this.tolerance = normalizeTolerance(options.tolerance);
- this.classes = options.classes;
- this.offset = options.offset;
- this.scroller = options.scroller;
- this.initialised = false;
- this.onPin = options.onPin;
- this.onUnpin = options.onUnpin;
- this.onTop = options.onTop;
- this.onNotTop = options.onNotTop;
- this.onBottom = options.onBottom;
- this.onNotBottom = options.onNotBottom;
- }
- Headroom.prototype = {
- constructor : Headroom,
- /**
- * Initialises the widget
- */
- init : function() {
- if(!Headroom.cutsTheMustard) {
- return;
- }
- this.debouncer = new Debouncer(this.update.bind(this));
- this.elem.classList.add(this.classes.initial);
- // defer event registration to handle browser
- // potentially restoring previous scroll position
- setTimeout(this.attachEvent.bind(this), 100);
- return this;
- },
- /**
- * Unattaches events and removes any classes that were added
- */
- destroy : function() {
- var classes = this.classes;
- this.initialised = false;
- for (var key in classes) {
- if(classes.hasOwnProperty(key)) {
- this.elem.classList.remove(classes[key]);
- }
- }
- this.scroller.removeEventListener('scroll', this.debouncer, false);
- },
- /**
- * Attaches the scroll event
- * @private
- */
- attachEvent : function() {
- if(!this.initialised){
- this.lastKnownScrollY = this.getScrollY();
- this.initialised = true;
- this.scroller.addEventListener('scroll', this.debouncer, false);
- this.debouncer.handleEvent();
- }
- },
- /**
- * Unpins the header if it's currently pinned
- */
- unpin : function() {
- var classList = this.elem.classList,
- classes = this.classes;
- if(classList.contains(classes.pinned) || !classList.contains(classes.unpinned)) {
- classList.add(classes.unpinned);
- classList.remove(classes.pinned);
- this.onUnpin && this.onUnpin.call(this);
- }
- },
- /**
- * Pins the header if it's currently unpinned
- */
- pin : function() {
- var classList = this.elem.classList,
- classes = this.classes;
- if(classList.contains(classes.unpinned)) {
- classList.remove(classes.unpinned);
- classList.add(classes.pinned);
- this.onPin && this.onPin.call(this);
- }
- },
- /**
- * Handles the top states
- */
- top : function() {
- var classList = this.elem.classList,
- classes = this.classes;
- if(!classList.contains(classes.top)) {
- classList.add(classes.top);
- classList.remove(classes.notTop);
- this.onTop && this.onTop.call(this);
- }
- },
- /**
- * Handles the not top state
- */
- notTop : function() {
- var classList = this.elem.classList,
- classes = this.classes;
- if(!classList.contains(classes.notTop)) {
- classList.add(classes.notTop);
- classList.remove(classes.top);
- this.onNotTop && this.onNotTop.call(this);
- }
- },
- bottom : function() {
- var classList = this.elem.classList,
- classes = this.classes;
- if(!classList.contains(classes.bottom)) {
- classList.add(classes.bottom);
- classList.remove(classes.notBottom);
- this.onBottom && this.onBottom.call(this);
- }
- },
- /**
- * Handles the not top state
- */
- notBottom : function() {
- var classList = this.elem.classList,
- classes = this.classes;
- if(!classList.contains(classes.notBottom)) {
- classList.add(classes.notBottom);
- classList.remove(classes.bottom);
- this.onNotBottom && this.onNotBottom.call(this);
- }
- },
- /**
- * Gets the Y scroll position
- * @see https://developer.mozilla.org/en-US/docs/Web/API/Window.scrollY
- * @return {Number} pixels the page has scrolled along the Y-axis
- */
- getScrollY : function() {
- return (this.scroller.pageYOffset !== undefined)
- ? this.scroller.pageYOffset
- : (this.scroller.scrollTop !== undefined)
- ? this.scroller.scrollTop
- : (document.documentElement || document.body.parentNode || document.body).scrollTop;
- },
- /**
- * Gets the height of the viewport
- * @see http://andylangton.co.uk/blog/development/get-viewport-size-width-and-height-javascript
- * @return {int} the height of the viewport in pixels
- */
- getViewportHeight : function () {
- return window.innerHeight
- || document.documentElement.clientHeight
- || document.body.clientHeight;
- },
- /**
- * Gets the physical height of the DOM element
- * @param {Object} elm the element to calculate the physical height of which
- * @return {int} the physical height of the element in pixels
- */
- getElementPhysicalHeight : function (elm) {
- return Math.max(
- elm.offsetHeight,
- elm.clientHeight
- );
- },
- /**
- * Gets the physical height of the scroller element
- * @return {int} the physical height of the scroller element in pixels
- */
- getScrollerPhysicalHeight : function () {
- return (this.scroller === window || this.scroller === document.body)
- ? this.getViewportHeight()
- : this.getElementPhysicalHeight(this.scroller);
- },
- /**
- * Gets the height of the document
- * @see http://james.padolsey.com/javascript/get-document-height-cross-browser/
- * @return {int} the height of the document in pixels
- */
- getDocumentHeight : function () {
- var body = document.body,
- documentElement = document.documentElement;
- return Math.max(
- body.scrollHeight, documentElement.scrollHeight,
- body.offsetHeight, documentElement.offsetHeight,
- body.clientHeight, documentElement.clientHeight
- );
- },
- /**
- * Gets the height of the DOM element
- * @param {Object} elm the element to calculate the height of which
- * @return {int} the height of the element in pixels
- */
- getElementHeight : function (elm) {
- return Math.max(
- elm.scrollHeight,
- elm.offsetHeight,
- elm.clientHeight
- );
- },
- /**
- * Gets the height of the scroller element
- * @return {int} the height of the scroller element in pixels
- */
- getScrollerHeight : function () {
- return (this.scroller === window || this.scroller === document.body)
- ? this.getDocumentHeight()
- : this.getElementHeight(this.scroller);
- },
- /**
- * determines if the scroll position is outside of document boundaries
- * @param {int} currentScrollY the current y scroll position
- * @return {bool} true if out of bounds, false otherwise
- */
- isOutOfBounds : function (currentScrollY) {
- var pastTop = currentScrollY < 0,
- pastBottom = currentScrollY + this.getScrollerPhysicalHeight() > this.getScrollerHeight();
- return pastTop || pastBottom;
- },
- /**
- * determines if the tolerance has been exceeded
- * @param {int} currentScrollY the current scroll y position
- * @return {bool} true if tolerance exceeded, false otherwise
- */
- toleranceExceeded : function (currentScrollY, direction) {
- return Math.abs(currentScrollY-this.lastKnownScrollY) >= this.tolerance[direction];
- },
- /**
- * determine if it is appropriate to unpin
- * @param {int} currentScrollY the current y scroll position
- * @param {bool} toleranceExceeded has the tolerance been exceeded?
- * @return {bool} true if should unpin, false otherwise
- */
- shouldUnpin : function (currentScrollY, toleranceExceeded) {
- var scrollingDown = currentScrollY > this.lastKnownScrollY,
- pastOffset = currentScrollY >= this.offset;
- return scrollingDown && pastOffset && toleranceExceeded;
- },
- /**
- * determine if it is appropriate to pin
- * @param {int} currentScrollY the current y scroll position
- * @param {bool} toleranceExceeded has the tolerance been exceeded?
- * @return {bool} true if should pin, false otherwise
- */
- shouldPin : function (currentScrollY, toleranceExceeded) {
- var scrollingUp = currentScrollY < this.lastKnownScrollY,
- pastOffset = currentScrollY <= this.offset;
- return (scrollingUp && toleranceExceeded) || pastOffset;
- },
- /**
- * Handles updating the state of the widget
- */
- update : function() {
- var currentScrollY = this.getScrollY(),
- scrollDirection = currentScrollY > this.lastKnownScrollY ? 'down' : 'up',
- toleranceExceeded = this.toleranceExceeded(currentScrollY, scrollDirection);
- if(this.isOutOfBounds(currentScrollY)) { // Ignore bouncy scrolling in OSX
- return;
- }
- if (currentScrollY <= this.offset ) {
- this.top();
- } else {
- this.notTop();
- }
- if(currentScrollY + this.getViewportHeight() >= this.getScrollerHeight()) {
- this.bottom();
- }
- else {
- this.notBottom();
- }
- if(this.shouldUnpin(currentScrollY, toleranceExceeded)) {
- this.unpin();
- }
- else if(this.shouldPin(currentScrollY, toleranceExceeded)) {
- this.pin();
- }
- this.lastKnownScrollY = currentScrollY;
- }
- };
- /**
- * Default options
- * @type {Object}
- */
- Headroom.options = {
- tolerance : {
- up : 0,
- down : 0
- },
- offset : 0,
- scroller: window,
- classes : {
- pinned : 'headroom--pinned',
- unpinned : 'headroom--unpinned',
- top : 'headroom--top',
- notTop : 'headroom--not-top',
- bottom : 'headroom--bottom',
- notBottom : 'headroom--not-bottom',
- initial : 'headroom'
- }
- };
- Headroom.cutsTheMustard = typeof features !== 'undefined' && features.rAF && features.bind && features.classList;
- return Headroom;
- }));
- // grab an element
- var myElement = document.querySelector("#header");
- // construct an instance of Headroom, passing the element
- var headroom = new Headroom(myElement);
- // initialise
- headroom.init();
- var headroom = new Headroom(elem, {
- "offset": 205,
- "tolerance": 5,
- "classes": {
- "initial": "animated",
- "pinned": "slideDown",
- "unpinned": "slideUp"
- }
- });
- headroom.init();
- // to destroy
- headroom.destroy();
- </script>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement