diff --git a/.github/contributing.md b/.github/contributing.md
index a9e4594..6cf9168 100644
--- a/.github/contributing.md
+++ b/.github/contributing.md
@@ -11,7 +11,7 @@ Report bugs, ask questions, and request features using [GitHub Issues](https://g
- Clearly demonstrate the bug or issue.
- Include the bare minimum HTML, CSS, and JavaScript required to demonstrate the bug.
- A link to your production site is **not** a reduced test case.
- - You can create one by [forking this JSFiddle](https://jsfiddle.net/cferdinandi/87v3pqp0/).
+ - You can create one by [forking this CodePen](https://codepen.io/cferdinandi/pen/RqGLpz).
3. The browser and OS that you're using.
Duplicates and issues without a reduced test case may be closed without comment.
\ No newline at end of file
diff --git a/.github/issue_template.md b/.github/issue_template.md
index e92cc83..664bfaa 100755
--- a/.github/issue_template.md
+++ b/.github/issue_template.md
@@ -1,3 +1,3 @@
-
+
-**Test case:** https://jsfiddle.net/cferdinandi/87v3pqp0/
\ No newline at end of file
+**Test case:** https://codepen.io/cferdinandi/pen/RqGLpz
\ No newline at end of file
diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml
new file mode 100644
index 0000000..42b06b4
--- /dev/null
+++ b/.github/workflows/push.yml
@@ -0,0 +1,13 @@
+on: push
+name: publish on release
+jobs:
+ publish:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@master
+ - name: publish
+ uses: actions/npm@master
+ env:
+ NPM_AUTH_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }}
+ with:
+ args: publish
diff --git a/README.md b/README.md
index 9211a28..ed77c95 100755
--- a/README.md
+++ b/README.md
@@ -1,7 +1,25 @@
+**DEPRECATION NOTICE:**
+
+Smooth Scroll is, without a doubt, my most popular and widely used plugin.
+
+But in the time since I created it, a CSS-only method for smooth scrolling has emerged, and now has fantastic browser support. It can do things this plugin can't (like scrolling to anchor links from another page), and addresses bugs and limitations in the plugin that I have never gotten around to fixing.
+
+This plugin has run its course, and the browser now offers a better, more feature rich and resilient solution out-of-the-box.
+
+Learn [how to animate scrolling to anchor links with one line of CSS](https://gomakethings.com/how-to-animate-scrolling-to-anchor-links-with-one-line-of-css/), and [how to prevent anchor links from scrolling behind fixed or sticky headers](https://gomakethings.com/how-to-prevent-anchor-links-from-scrolling-behind-a-sticky-header-with-one-line-of-css/).
+
+Thanks for the years of support!
+
+---
+
# Smooth Scroll [](https://travis-ci.org/cferdinandi/smooth-scroll)
A lightweight script to animate scrolling to anchor links. Smooth Scroll works great with [Gumshoe](https://github.com/cferdinandi/gumshoe).
-[Demo](http://cferdinandi.github.io/smooth-scroll/)
+**[View the Demo on CodePen →](https://codepen.io/cferdinandi/pen/wQzrdM)**
+
+[Getting Started](#getting-started) | [Scroll Speed](#scroll-speed) | [Easing Options](#easing-options) | [API](#api) | [What's new?](#whats-new) | [Known Issues](#known-issues) | [Browser Compatibility](#browser-compatibility) | [License](#license)
+
+*__Quick aside:__ you might not need this library. There's [a native CSS way to handle smooth scrolling](https://gomakethings.com/smooth-scrolling-links-with-only-css/) that might fit your needs.*
@@ -11,7 +29,6 @@ A lightweight script to animate scrolling to anchor links. Smooth Scroll works g
-
## Getting Started
Compiled and production-ready code can be found in the `dist` directory. The `src` directory contains development code.
@@ -40,13 +57,21 @@ You can also use the [jsDelivr CDN](https://cdn.jsdelivr.net/gh/cferdinandi/smoo
-
+
-
+
-
+
+```
+
+**NPM**
+
+You can also use NPM (or your favorite package manager).
+
+```bash
+npm install smooth-scroll
```
### 2. Add the markup to your HTML.
@@ -74,48 +99,93 @@ In the footer of your page, after the content, initialize Smooth Scroll by passi
***Note:*** *The `a[href*="#"]` selector will apply Smooth Scroll to all anchor links. You can selectively target links using any other selector(s) you'd like. Smooth Scroll accepts multiple selectors as a comma separated list. Example: `'.js-scroll, [data-scroll], #some-link'`.*
-## ES6 Modules
-Smooth Scroll does not have a default export, but does support CommonJS and can be used with native ES6 module imports.
+## Scroll Speed
+
+Smooth Scroll allows you to adjust the speed of your animations with the `speed` option.
+
+This a number representing the amount of time in milliseconds that it should take to scroll 1000px. Scroll distances shorter than that will take less time, and scroll distances longer than that will take more time. The default is 300ms.
```js
-import('/path/to/smooth-scroll.polyfills.min.js')
- .then(function () {
- var scroll = new SmoothScroll('a[href*="#"]');
- });
+var scroll = new SmoothScroll('a[href*="#"]', {
+ speed: 300
+});
```
-It uses a UMD pattern, and should also work in most major module bundlers and package managers.
+If you want all of your animations to take exactly the same amount of time (the value you set for `speed`), set the `speedAsDuration` option to `true`.
+```js
+// All animations will take exactly 500ms
+var scroll = new SmoothScroll('a[href*="#"]', {
+ speed: 500,
+ speedAsDuration: true
+});
+```
-## Working with the Source Files
+## Easing Options
-If you would prefer, you can work with the development code in the `src` directory using the included [Gulp build system](http://gulpjs.com/). This compiles, lints, and minifies code.
+Smooth Scroll comes with about a dozen common easing patterns. [Here's a demo of the different patterns.](https://codepen.io/cferdinandi/pen/jQMGaB)
-### Dependencies
-Make sure these are installed first.
+**Linear**
+*Moves at the same speed from start to finish.*
-* [Node.js](http://nodejs.org)
-* [Gulp](http://gulpjs.com) `sudo npm install -g gulp`
+- `Linear`
-### Quick Start
-1. In bash/terminal/command line, `cd` into your project directory.
-2. Run `npm install` to install required files.
-3. When it's done installing, run one of the task runners to get going:
- * `gulp` manually compiles files.
- * `gulp watch` automatically compiles files when changes are made and applies changes using [LiveReload](http://livereload.com/).
+**Ease-In**
+*Gradually increases in speed.*
+- `easeInQuad`
+- `easeInCubic`
+- `easeInQuart`
+- `easeInQuint`
-## Options and Settings
+**Ease-In-Out**
+*Gradually increases in speed, peaks, and then gradually slows down.*
+
+- `easeInOutQuad`
+- `easeInOutCubic`
+- `easeInOutQuart`
+- `easeInOutQuint`
+
+
+**Ease-Out**
+*Gradually decreases in speed.*
+
+- `easeOutQuad`
+- `easeOutCubic`
+- `easeOutQuart`
+- `easeOutQuint`
+
+
+You can also pass in your own custom easing pattern [using the `customEasing` option](#global-settings).
+
+```js
+var scroll = new SmoothScroll('a[href*="#"]', {
+ // Function. Custom easing pattern
+ // If this is set to anything other than null, will override the easing option above
+ customEasing: function (time) {
+
+ // return
+
+ // Example: easeInOut Quad
+ return time < 0.5 ? 2 * time * time : -1 + (4 - 2 * time) * time;
+
+ }
+});
+```
+
+
+
+## API
Smooth Scroll includes smart defaults and works right out of the box. But if you want to customize things, it also has a robust API that provides multiple ways for you to adjust the default options and settings.
-### Global Settings
+### Options and Settings
-You can pass options and callbacks into Smooth Scroll through the `init()` function:
+You can pass options and callbacks into Smooth Scroll when instantiating.
```javascript
var scroll = new SmoothScroll('a[href*="#"]', {
@@ -125,8 +195,11 @@ var scroll = new SmoothScroll('a[href*="#"]', {
header: null, // Selector for fixed headers (must be a valid CSS selector)
topOnEmptyHash: true, // Scroll to the top of the page for links with href="#"
- // Speed & Easing
- speed: 500, // Integer. How fast to complete the scroll in milliseconds
+ // Speed & Duration
+ speed: 500, // Integer. Amount of time in milliseconds it should take to scroll 1000px
+ speedAsDuration: false, // If true, use speed as the total duration of the scroll animation
+ durationMax: null, // Integer. The maximum amount of time the scroll animation should take
+ durationMin: null, // Integer. The minimum amount of time the scroll animation should take
clip: true, // If true, adjust scroll distance to prevent abrupt stops near the bottom of the page
offset: function (anchor, toggle) {
@@ -141,6 +214,8 @@ var scroll = new SmoothScroll('a[href*="#"]', {
}
},
+
+ // Easing
easing: 'easeInOutCubic', // Easing pattern to use
customEasing: function (time) {
@@ -164,44 +239,6 @@ var scroll = new SmoothScroll('a[href*="#"]', {
});
```
-#### Easing Options
-
-Some common easing patterns are included by default, but you can also pass in your own custom easing pattern using the `customEasing` option noted above.
-
-**Linear**
-*Moves at the same speed from start to finish.*
-
-* `Linear`
-
-
-**Ease-In**
-*Gradually increases in speed.*
-
-* `easeInQuad`
-* `easeInCubic`
-* `easeInQuart`
-* `easeInQuint`
-
-
-**Ease-In-Out**
-*Gradually increases in speed, peaks, and then gradually slows down.*
-
-* `easeInOutQuad`
-* `easeInOutCubic`
-* `easeInOutQuart`
-* `easeInOutQuint`
-
-
-**Ease-Out**
-*Gradually decreases in speed.*
-
-* `easeOutQuad`
-* `easeOutCubic`
-* `easeOutQuart`
-* `easeOutQuint`
-
-Learn more about the different easing patterns and what they do at [easings.net](http://easings.net/).
-
### Custom Events
Smooth Scroll emits three custom events:
@@ -233,9 +270,9 @@ document.addEventListener('scrollStop', logScrollEvent, false);
document.addEventListener('scrollCancel', logScrollEvent, false);
```
-### Use Smooth Scroll events in your own scripts
+### Methods
-You can also call Smooth Scroll's methods in your own scripts.
+Smooth Scroll also exposes several public methods.
#### animateScroll()
Animate scrolling to an anchor.
@@ -285,16 +322,8 @@ scroll.cancelScroll();
***Note:*** *This does not handle focus management. The user will stop in place, and focus will remain on the anchor link that triggered the scroll.*
-#### init()
-Initialize Smooth Scroll. This is called automatically when you setup your `new SmoothScroll` object, but can be used to reinitialize your instance.
-
-```javascript
-var scroll = new SmoothScroll();
-scroll.init('.some-selector');
-```
-
#### destroy()
-Destroy the current `smoothScroll.init()`. This is called automatically during the `init` function to remove any existing initializations.
+Destroy the current initialization. This is called automatically in the `init` method to remove any existing initializations.
```javascript
var scroll = new SmoothScroll();
@@ -321,38 +350,22 @@ If you have multiple fixed headers, pass in the last one in the markup.
```
-## Migrating to Smooth Scroll 14 from Older Versions
-
-### New Features
-
-- You can now choose not to update the URL as a native feature. No more hacks using the API.
-- You can choose not to scroll to top on `href="#"`, providing more flexibility for some CMS implementations.
-- Custom events let you more easily hook into Smooth Scroll from other scripts.
-- The feature test is scoped to a function, allowing for server-side implementations.
-- The loss of styling with IDs experienced in earlier versions has been eliminated.
-- The `anchor` and `toggle` elements are now passed into the `offset()` function, allowing for more customization [v14.1.0 and up].
-### Breaking Changes
+## What's new?
-- Callback methods have been removed in favor of events.
+Scroll duration now varies based on distance traveled. If you want to maintain the old scroll animation duration behavior, set the `speedAsDuration` option to `true`.
-## Browser Compatibility
-
-Smooth Scroll works in all modern browsers, and IE 9 and above.
-
-Smooth Scroll is built with modern JavaScript APIs, and uses progressive enhancement. If the JavaScript file fails to load, or if your site is viewed on older and less capable browsers, anchor links will jump the way they normally would.
-
-### Polyfills
+## Known Issues
-Support back to IE9 requires polyfills for `closest()`, `requestAnimationFrame()`, and `CustomEvent()`. Without them, support starts with Edge.
+### Reduce Motion Settings
-Use the included polyfills version of Smooth Scroll, or include your own.
+This isn't really an "issue" so-much as a question I get a lot.
+Smooth Scroll respects [the `Reduce Motion` setting](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-reduced-motion) available in certain operating systems. In browsers that surface that setting, Smooth Scroll will not run and will revert to the default "jump to location" anchor link behavior.
-
-## Known Issues
+I've decided to respect user preferences of developer desires here. This is *not* a configurable setting.
### `` styling
@@ -370,6 +383,22 @@ Most browsers instantly jump you to the anchor location when you load a page. Yo
+## Browser Compatibility
+
+Smooth Scroll works in all modern browsers, and IE 9 and above.
+
+Smooth Scroll is built with modern JavaScript APIs, and uses progressive enhancement. If the JavaScript file fails to load, or if your site is viewed on older and less capable browsers, anchor links will jump the way they normally would.
+
+*__Note:__ Smooth Scroll will not run—even in supported browsers—if users have `Reduce Motion` enabled. [Learn more in the "Known Issues" section.](#reduce-motion-settings)*
+
+### Polyfills
+
+Support back to IE9 requires polyfills for `closest()`, `requestAnimationFrame()`, and `CustomEvent()`. Without them, support starts with Edge.
+
+Use the included polyfills version of Smooth Scroll, or include your own.
+
+
+
## License
The code is available under the [MIT License](LICENSE.md).
\ No newline at end of file
diff --git a/dist/smooth-scroll.js b/dist/smooth-scroll.js
old mode 100755
new mode 100644
index 74ce7cc..4984899
--- a/dist/smooth-scroll.js
+++ b/dist/smooth-scroll.js
@@ -1,38 +1,30 @@
-/*!
- * smooth-scroll v14.2.1: Animate scrolling to anchor links
- * (c) 2018 Chris Ferdinandi
- * MIT License
- * http://github.com/cferdinandi/smooth-scroll
- */
-
-(function (root, factory) {
- if (typeof define === 'function' && define.amd) {
- define([], (function () {
- return factory(root);
- }));
- } else if (typeof exports === 'object') {
- module.exports = factory(root);
- } else {
- root.SmoothScroll = factory(root);
- }
-})(typeof global !== 'undefined' ? global : typeof window !== 'undefined' ? window : this, (function (window) {
-
- 'use strict';
+/*! SmoothScroll v16.1.4 | (c) 2020 Chris Ferdinandi | MIT License | http://github.com/cferdinandi/smooth-scroll */
+(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
+ typeof define === 'function' && define.amd ? define(factory) :
+ (global = global || self, global.SmoothScroll = factory());
+}(this, (function () { 'use strict';
//
// Default settings
//
var defaults = {
+
// Selectors
ignore: '[data-scroll-ignore]',
header: null,
topOnEmptyHash: true,
- // Speed & Easing
+ // Speed & Duration
speed: 500,
+ speedAsDuration: false,
+ durationMax: null,
+ durationMin: null,
clip: true,
offset: 0,
+
+ // Easing
easing: 'easeInOutCubic',
customEasing: null,
@@ -42,6 +34,7 @@
// Custom Events
emitEvents: true
+
};
@@ -63,38 +56,26 @@
};
/**
- * Merge two or more objects. Returns a new object.
- * @param {Object} objects The objects to merge together
- * @returns {Object} Merged values of defaults and options
+ * Merge two or more objects together.
+ * @param {Object} objects The objects to merge together
+ * @returns {Object} Merged values of defaults and options
*/
var extend = function () {
-
- // Variables
- var extended = {};
-
- // Merge the object into the extended object
- var merge = function (obj) {
- for (var prop in obj) {
- if (obj.hasOwnProperty(prop)) {
- extended[prop] = obj[prop];
- }
+ var merged = {};
+ Array.prototype.forEach.call(arguments, function (obj) {
+ for (var key in obj) {
+ if (!obj.hasOwnProperty(key)) return;
+ merged[key] = obj[key];
}
- };
-
- // Loop through each object and conduct a merge
- for (var i = 0; i < arguments.length; i++) {
- merge(arguments[i]);
- }
-
- return extended;
-
+ });
+ return merged;
};
/**
* Check to see if user prefers reduced motion
* @param {Object} settings Script settings
*/
- var reduceMotion = function (settings) {
+ var reduceMotion = function () {
if ('matchMedia' in window && window.matchMedia('(prefers-reduced-motion)').matches) {
return true;
}
@@ -110,21 +91,6 @@
return parseInt(window.getComputedStyle(elem).height, 10);
};
- /**
- * Decode a URI, with error check
- * @param {String} hash The URI to decode
- * @return {String} A decoded URI (or the original string if an error is thrown)
- */
- var decode = function (hash) {
- var decoded;
- try {
- decoded = decodeURIComponent(hash);
- } catch(e) {
- decoded = hash;
- }
- return decoded;
- };
-
/**
* Escape special characters for use with querySelector
* @author Mathias Bynens
@@ -201,21 +167,15 @@
}
// Return sanitized hash
- var hash;
- try {
- hash = decodeURIComponent('#' + result);
- } catch(e) {
- hash = '#' + result;
- }
- return hash;
+ return '#' + result;
};
/**
* Calculate the easing pattern
* @link https://gist.github.com/gre/1650294
- * @param {String} type Easing pattern
- * @param {Number} time Time animation should take to complete
+ * @param {Object} settings Easing pattern
+ * @param {Number} time Time animation should take to complete
* @returns {Number}
*/
var easingPattern = function (settings, time) {
@@ -274,7 +234,7 @@
if (clip) {
location = Math.min(location, getDocumentHeight() - window.innerHeight);
}
- return location;
+ return location;
};
/**
@@ -286,6 +246,40 @@
return !header ? 0 : (getHeight(header) + header.offsetTop);
};
+ /**
+ * Calculate the speed to use for the animation
+ * @param {Number} distance The distance to travel
+ * @param {Object} settings The plugin settings
+ * @return {Number} How fast to animate
+ */
+ var getSpeed = function (distance, settings) {
+ var speed = settings.speedAsDuration ? settings.speed : Math.abs(distance / 1000 * settings.speed);
+ if (settings.durationMax && speed > settings.durationMax) return settings.durationMax;
+ if (settings.durationMin && speed < settings.durationMin) return settings.durationMin;
+ return parseInt(speed, 10);
+ };
+
+ var setHistory = function (options) {
+
+ // Make sure this should run
+ if (!history.replaceState || !options.updateURL || history.state) return;
+
+ // Get the hash to use
+ var hash = window.location.hash;
+ hash = hash ? hash : '';
+
+ // Set a default history
+ history.replaceState(
+ {
+ smoothScroll: JSON.stringify(options),
+ anchor: hash ? hash : window.pageYOffset
+ },
+ document.title,
+ hash ? hash : window.location.href
+ );
+
+ };
+
/**
* Update the URL
* @param {Node} anchor The anchor that was scrolled to
@@ -370,7 +364,7 @@
//
var smoothScroll = {}; // Object for public APIs
- var settings, anchor, toggle, fixedHeader, headerHeight, eventTimeout, animationInterval;
+ var settings, toggle, fixedHeader, animationInterval;
//
@@ -395,26 +389,27 @@
*/
smoothScroll.animateScroll = function (anchor, toggle, options) {
+ // Cancel any in progress scrolls
+ smoothScroll.cancelScroll();
+
// Local settings
- var animateSettings = extend(settings || defaults, options || {}); // Merge user options with defaults
+ var _settings = extend(settings || defaults, options || {}); // Merge user options with defaults
// Selectors and variables
var isNum = Object.prototype.toString.call(anchor) === '[object Number]' ? true : false;
var anchorElem = isNum || !anchor.tagName ? null : anchor;
if (!isNum && !anchorElem) return;
var startLocation = window.pageYOffset; // Current location on the page
- if (animateSettings.header && !fixedHeader) {
+ if (_settings.header && !fixedHeader) {
// Get the fixed header if not already set
- fixedHeader = document.querySelector(animateSettings.header);
+ fixedHeader = document.querySelector(_settings.header);
}
- if (!headerHeight) {
- // Get the height of a fixed header if one exists and not already set
- headerHeight = getHeaderHeight(fixedHeader);
- }
- var endLocation = isNum ? anchor : getEndLocation(anchorElem, headerHeight, parseInt((typeof animateSettings.offset === 'function' ? animateSettings.offset(anchor, toggle) : animateSettings.offset), 10), animateSettings.clip); // Location to scroll to
+ var headerHeight = getHeaderHeight(fixedHeader);
+ var endLocation = isNum ? anchor : getEndLocation(anchorElem, headerHeight, parseInt((typeof _settings.offset === 'function' ? _settings.offset(anchor, toggle) : _settings.offset), 10), _settings.clip); // Location to scroll to
var distance = endLocation - startLocation; // distance to travel
var documentHeight = getDocumentHeight();
var timeLapsed = 0;
+ var speed = getSpeed(distance, _settings);
var start, percentage, position;
/**
@@ -438,7 +433,7 @@
adjustFocus(anchor, endLocation, isNum);
// Emit a custom event
- emitEvent('scrollStop', animateSettings, anchor, toggle);
+ emitEvent('scrollStop', _settings, anchor, toggle);
// Reset start
start = null;
@@ -455,9 +450,9 @@
var loopAnimateScroll = function (timestamp) {
if (!start) { start = timestamp; }
timeLapsed += timestamp - start;
- percentage = (timeLapsed / parseInt(animateSettings.speed, 10));
+ percentage = speed === 0 ? 0 : (timeLapsed / speed);
percentage = (percentage > 1) ? 1 : percentage;
- position = startLocation + (distance * easingPattern(animateSettings, percentage));
+ position = startLocation + (distance * easingPattern(_settings, percentage));
window.scrollTo(0, Math.floor(position));
if (!stopAnimateScroll(position, endLocation)) {
animationInterval = window.requestAnimationFrame(loopAnimateScroll);
@@ -474,10 +469,16 @@
}
// Update the URL
- updateURL(anchor, isNum, animateSettings);
+ updateURL(anchor, isNum, _settings);
+
+ // If the user prefers reduced motion, jump to location
+ if (reduceMotion()) {
+ adjustFocus(anchor, Math.floor(endLocation), false);
+ return;
+ }
// Emit a custom event
- emitEvent('scrollStart', animateSettings, anchor, toggle);
+ emitEvent('scrollStart', _settings, anchor, toggle);
// Start scrolling animation
smoothScroll.cancelScroll(true);
@@ -490,15 +491,16 @@
*/
var clickHandler = function (event) {
- // Don't run if the user prefers reduced motion
- if (reduceMotion(settings)) return;
+ // Don't run if event was canceled but still bubbled up
+ // By @mgreter - https://github.com/cferdinandi/smooth-scroll/pull/462/
+ if (event.defaultPrevented) return;
- // Don't run if right-click or command/control + click
- if (event.button !== 0 || event.metaKey || event.ctrlKey) return;
+ // Don't run if right-click or command/control + click or shift + click
+ if (event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey) return;
// Check if event.target has closest() method
// By @totegi - https://github.com/cferdinandi/smooth-scroll/pull/401/
- if(!('closest' in event.target))return;
+ if (!('closest' in event.target)) return;
// Check if a smooth scroll link was clicked
toggle = event.target.closest(selector);
@@ -508,15 +510,27 @@
if (toggle.hostname !== window.location.hostname || toggle.pathname !== window.location.pathname || !/#/.test(toggle.href)) return;
// Get an escaped version of the hash
- var hash = escapeCharacters(decode(toggle.hash));
+ var hash;
+ try {
+ hash = escapeCharacters(decodeURIComponent(toggle.hash));
+ } catch(e) {
+ hash = escapeCharacters(toggle.hash);
+ }
// Get the anchored element
- var anchor = settings.topOnEmptyHash && hash === '#' ? document.documentElement : document.querySelector(hash);
+ var anchor;
+ if (hash === '#') {
+ if (!settings.topOnEmptyHash) return;
+ anchor = document.documentElement;
+ } else {
+ anchor = document.querySelector(hash);
+ }
anchor = !anchor && hash === '#top' ? document.documentElement : anchor;
// If anchored element exists, scroll to it
if (!anchor) return;
event.preventDefault();
+ setHistory(settings);
smoothScroll.animateScroll(anchor, toggle);
};
@@ -524,38 +538,27 @@
/**
* Animate scroll on popstate events
*/
- var popstateHandler = function (event) {
+ var popstateHandler = function () {
+
// Stop if history.state doesn't exist (ex. if clicking on a broken anchor link).
// fixes `Cannot read property 'smoothScroll' of null` error getting thrown.
- if (history.state === null) return;
+ if (history.state === null) return;
// Only run if state is a popstate record for this instantiation
if (!history.state.smoothScroll || history.state.smoothScroll !== JSON.stringify(settings)) return;
- // Only run if state includes an anchor
- if (!history.state.anchor) return;
-
// Get the anchor
- var anchor = document.querySelector(escapeCharacters(decode(history.state.anchor)));
- if (!anchor) return;
+ var anchor = history.state.anchor;
+ if (typeof anchor === 'string' && anchor) {
+ anchor = document.querySelector(escapeCharacters(history.state.anchor));
+ if (!anchor) return;
+ }
// Animate scroll to anchor link
smoothScroll.animateScroll(anchor, null, {updateURL: false});
};
- /**
- * On window scroll and resize, only run events at a rate of 15fps for better performance
- */
- var resizeThrottler = function (event) {
- if (!eventTimeout) {
- eventTimeout = setTimeout((function() {
- eventTimeout = null; // Reset timeout
- headerHeight = getHeaderHeight(fixedHeader); // Get the height of a fixed header if one exists
- }), 66);
- }
- };
-
/**
* Destroy the current initialization.
*/
@@ -566,7 +569,6 @@
// Remove event listeners
document.removeEventListener('click', clickHandler, false);
- window.removeEventListener('resize', resizeThrottler, false);
window.removeEventListener('popstate', popstateHandler, false);
// Cancel any scrolls-in-progress
@@ -574,11 +576,8 @@
// Reset variables
settings = null;
- anchor = null;
toggle = null;
fixedHeader = null;
- headerHeight = null;
- eventTimeout = null;
animationInterval = null;
};
@@ -587,7 +586,7 @@
* Initialize Smooth Scroll
* @param {Object} options User settings
*/
- smoothScroll.init = function (options) {
+ var init = function () {
// feature test
if (!supports()) throw 'Smooth Scroll: This browser does not support the required JavaScript methods and browser APIs.';
@@ -598,16 +597,10 @@
// Selectors and variables
settings = extend(defaults, options || {}); // Merge user options with defaults
fixedHeader = settings.header ? document.querySelector(settings.header) : null; // Get the fixed header
- headerHeight = getHeaderHeight(fixedHeader);
// When a toggle is clicked, run the click handler
document.addEventListener('click', clickHandler, false);
- // If window is resized and there's a fixed header, recalculate its size
- if (fixedHeader) {
- window.addEventListener('resize', resizeThrottler, false);
- }
-
// If updateURL and popState are enabled, listen for pop events
if (settings.updateURL && settings.popstate) {
window.addEventListener('popstate', popstateHandler, false);
@@ -620,7 +613,7 @@
// Initialize plugin
//
- smoothScroll.init(options);
+ init();
//
@@ -633,4 +626,4 @@
return SmoothScroll;
-}));
+})));
diff --git a/dist/smooth-scroll.min.js b/dist/smooth-scroll.min.js
old mode 100755
new mode 100644
index f4ba547..b3d1fe0
--- a/dist/smooth-scroll.min.js
+++ b/dist/smooth-scroll.min.js
@@ -1,2 +1,2 @@
-/*! smooth-scroll v14.2.1 | (c) 2018 Chris Ferdinandi | MIT License | http://github.com/cferdinandi/smooth-scroll */
-!(function(e,t){"function"==typeof define&&define.amd?define([],(function(){return t(e)})):"object"==typeof exports?module.exports=t(e):e.SmoothScroll=t(e)})("undefined"!=typeof global?global:"undefined"!=typeof window?window:this,(function(e){"use strict";var t={ignore:"[data-scroll-ignore]",header:null,topOnEmptyHash:!0,speed:500,clip:!0,offset:0,easing:"easeInOutCubic",customEasing:null,updateURL:!0,popstate:!0,emitEvents:!0},n=function(){return"querySelector"in document&&"addEventListener"in e&&"requestAnimationFrame"in e&&"closest"in e.Element.prototype},o=function(){for(var e={},t=0;t=1&&t<=31||127==t||0===r&&t>=48&&t<=57||1===r&&t>=48&&t<=57&&45===i?a+="\\"+t.toString(16)+" ":a+=t>=128||45===t||95===t||t>=48&&t<=57||t>=65&&t<=90||t>=97&&t<=122?n.charAt(r):"\\"+n.charAt(r)}var c;try{c=decodeURIComponent("#"+a)}catch(e){c="#"+a}return c},u=function(e,t){var n;return"easeInQuad"===e.easing&&(n=t*t),"easeOutQuad"===e.easing&&(n=t*(2-t)),"easeInOutQuad"===e.easing&&(n=t<.5?2*t*t:(4-2*t)*t-1),"easeInCubic"===e.easing&&(n=t*t*t),"easeOutCubic"===e.easing&&(n=--t*t*t+1),"easeInOutCubic"===e.easing&&(n=t<.5?4*t*t*t:(t-1)*(2*t-2)*(2*t-2)+1),"easeInQuart"===e.easing&&(n=t*t*t*t),"easeOutQuart"===e.easing&&(n=1- --t*t*t*t),"easeInOutQuart"===e.easing&&(n=t<.5?8*t*t*t*t:1-8*--t*t*t*t),"easeInQuint"===e.easing&&(n=t*t*t*t*t),"easeOutQuint"===e.easing&&(n=1+--t*t*t*t*t),"easeInOutQuint"===e.easing&&(n=t<.5?16*t*t*t*t*t:1+16*--t*t*t*t*t),e.customEasing&&(n=e.customEasing(t)),n||t},s=function(){return Math.max(document.body.scrollHeight,document.documentElement.scrollHeight,document.body.offsetHeight,document.documentElement.offsetHeight,document.body.clientHeight,document.documentElement.clientHeight)},l=function(t,n,o,r){var a=0;if(t.offsetParent)do{a+=t.offsetTop,t=t.offsetParent}while(t);return a=Math.max(a-n-o,0),r&&(a=Math.min(a,s()-e.innerHeight)),a},d=function(e){return e?a(e)+e.offsetTop:0},f=function(e,t,n){t||history.pushState&&n.updateURL&&history.pushState({smoothScroll:JSON.stringify(n),anchor:e.id},document.title,e===document.documentElement?"#top":"#"+e.id)},m=function(t,n,o){0===t&&document.body.focus(),o||(t.focus(),document.activeElement!==t&&(t.setAttribute("tabindex","-1"),t.focus(),t.style.outline="none"),e.scrollTo(0,n))},h=function(t,n,o,r){if(n.emitEvents&&"function"==typeof e.CustomEvent){var a=new CustomEvent(t,{bubbles:!0,detail:{anchor:o,toggle:r}});document.dispatchEvent(a)}};return function(a,p){var g,v,y,S,E,b,O,I={};I.cancelScroll=function(e){cancelAnimationFrame(O),O=null,e||h("scrollCancel",g)},I.animateScroll=function(n,r,a){var i=o(g||t,a||{}),c="[object Number]"===Object.prototype.toString.call(n),p=c||!n.tagName?null:n;if(c||p){var v=e.pageYOffset;i.header&&!S&&(S=document.querySelector(i.header)),E||(E=d(S));var y,b,C,w=c?n:l(p,E,parseInt("function"==typeof i.offset?i.offset(n,r):i.offset,10),i.clip),L=w-v,A=s(),H=0,q=function(t,o){var a=e.pageYOffset;if(t==o||a==o||(v=A)return I.cancelScroll(!0),m(n,o,c),h("scrollStop",i,n,r),y=null,O=null,!0},Q=function(t){y||(y=t),H+=t-y,b=H/parseInt(i.speed,10),b=b>1?1:b,C=v+L*u(i,b),e.scrollTo(0,Math.floor(C)),q(C,w)||(O=e.requestAnimationFrame(Q),y=t)};0===e.pageYOffset&&e.scrollTo(0,0),f(n,c,i),h("scrollStart",i,n,r),I.cancelScroll(!0),e.requestAnimationFrame(Q)}};var C=function(t){if(!r()&&0===t.button&&!t.metaKey&&!t.ctrlKey&&"closest"in t.target&&(y=t.target.closest(a))&&"a"===y.tagName.toLowerCase()&&!t.target.closest(g.ignore)&&y.hostname===e.location.hostname&&y.pathname===e.location.pathname&&/#/.test(y.href)){var n=c(i(y.hash)),o=g.topOnEmptyHash&&"#"===n?document.documentElement:document.querySelector(n);o=o||"#top"!==n?o:document.documentElement,o&&(t.preventDefault(),I.animateScroll(o,y))}},w=function(e){if(null!==history.state&&history.state.smoothScroll&&history.state.smoothScroll===JSON.stringify(g)&&history.state.anchor){var t=document.querySelector(c(i(history.state.anchor)));t&&I.animateScroll(t,null,{updateURL:!1})}},L=function(e){b||(b=setTimeout((function(){b=null,E=d(S)}),66))};return I.destroy=function(){g&&(document.removeEventListener("click",C,!1),e.removeEventListener("resize",L,!1),e.removeEventListener("popstate",w,!1),I.cancelScroll(),g=null,v=null,y=null,S=null,E=null,b=null,O=null)},I.init=function(r){if(!n())throw"Smooth Scroll: This browser does not support the required JavaScript methods and browser APIs.";I.destroy(),g=o(t,r||{}),S=g.header?document.querySelector(g.header):null,E=d(S),document.addEventListener("click",C,!1),S&&e.addEventListener("resize",L,!1),g.updateURL&&g.popstate&&e.addEventListener("popstate",w,!1)},I.init(p),I}}));
\ No newline at end of file
+/*! SmoothScroll v16.1.4 | (c) 2020 Chris Ferdinandi | MIT License | http://github.com/cferdinandi/smooth-scroll */
+!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e=e||self).SmoothScroll=t()}(this,(function(){"use strict";var e={ignore:"[data-scroll-ignore]",header:null,topOnEmptyHash:!0,speed:500,speedAsDuration:!1,durationMax:null,durationMin:null,clip:!0,offset:0,easing:"easeInOutCubic",customEasing:null,updateURL:!0,popstate:!0,emitEvents:!0},t=function(){var e={};return Array.prototype.forEach.call(arguments,(function(t){for(var n in t){if(!t.hasOwnProperty(n))return;e[n]=t[n]}})),e},n=function(e){"#"===e.charAt(0)&&(e=e.substr(1));for(var t,n=String(e),o=n.length,a=-1,i="",r=n.charCodeAt(0);++a=1&&t<=31||127==t||0===a&&t>=48&&t<=57||1===a&&t>=48&&t<=57&&45===r?i+="\\"+t.toString(16)+" ":i+=t>=128||45===t||95===t||t>=48&&t<=57||t>=65&&t<=90||t>=97&&t<=122?n.charAt(a):"\\"+n.charAt(a)}return"#"+i},o=function(){return Math.max(document.body.scrollHeight,document.documentElement.scrollHeight,document.body.offsetHeight,document.documentElement.offsetHeight,document.body.clientHeight,document.documentElement.clientHeight)},a=function(e){return e?(t=e,parseInt(window.getComputedStyle(t).height,10)+e.offsetTop):0;var t},i=function(e,t,n){0===e&&document.body.focus(),n||(e.focus(),document.activeElement!==e&&(e.setAttribute("tabindex","-1"),e.focus(),e.style.outline="none"),window.scrollTo(0,t))},r=function(e,t,n,o){if(t.emitEvents&&"function"==typeof window.CustomEvent){var a=new CustomEvent(e,{bubbles:!0,detail:{anchor:n,toggle:o}});document.dispatchEvent(a)}};return function(s,c){var u,l,d,f,m={};m.cancelScroll=function(e){cancelAnimationFrame(f),f=null,e||r("scrollCancel",u)},m.animateScroll=function(n,s,c){m.cancelScroll();var l=t(u||e,c||{}),h="[object Number]"===Object.prototype.toString.call(n),p=h||!n.tagName?null:n;if(h||p){var w=window.pageYOffset;l.header&&!d&&(d=document.querySelector(l.header));var g,y,v,S=a(d),E=h?n:function(e,t,n,a){var i=0;if(e.offsetParent)do{i+=e.offsetTop,e=e.offsetParent}while(e);return i=Math.max(i-t-n,0),a&&(i=Math.min(i,o()-window.innerHeight)),i}(p,S,parseInt("function"==typeof l.offset?l.offset(n,s):l.offset,10),l.clip),b=E-w,O=o(),I=0,M=function(e,t){var n=t.speedAsDuration?t.speed:Math.abs(e/1e3*t.speed);return t.durationMax&&n>t.durationMax?t.durationMax:t.durationMin&&n1?1:y),window.scrollTo(0,Math.floor(v)),function(e,t){var o=window.pageYOffset;if(e==t||o==t||(w=O)return m.cancelScroll(!0),i(n,t,h),r("scrollStop",l,n,s),g=null,f=null,!0}(v,E)||(f=window.requestAnimationFrame(A),g=e)};0===window.pageYOffset&&window.scrollTo(0,0),function(e,t,n){t||history.pushState&&n.updateURL&&history.pushState({smoothScroll:JSON.stringify(n),anchor:e.id},document.title,e===document.documentElement?"#top":"#"+e.id)}(n,h,l),"matchMedia"in window&&window.matchMedia("(prefers-reduced-motion)").matches?i(n,Math.floor(E),!1):(r("scrollStart",l,n,s),m.cancelScroll(!0),window.requestAnimationFrame(A))}};var h=function(e){if(!e.defaultPrevented&&!(0!==e.button||e.metaKey||e.ctrlKey||e.shiftKey)&&"closest"in e.target&&(l=e.target.closest(s))&&"a"===l.tagName.toLowerCase()&&!e.target.closest(u.ignore)&&l.hostname===window.location.hostname&&l.pathname===window.location.pathname&&/#/.test(l.href)){var t,o;try{t=n(decodeURIComponent(l.hash))}catch(e){t=n(l.hash)}if("#"===t){if(!u.topOnEmptyHash)return;o=document.documentElement}else o=document.querySelector(t);(o=o||"#top"!==t?o:document.documentElement)&&(e.preventDefault(),function(e){if(history.replaceState&&e.updateURL&&!history.state){var t=window.location.hash;t=t||"",history.replaceState({smoothScroll:JSON.stringify(e),anchor:t||window.pageYOffset},document.title,t||window.location.href)}}(u),m.animateScroll(o,l))}},p=function(){if(null!==history.state&&history.state.smoothScroll&&history.state.smoothScroll===JSON.stringify(u)){var e=history.state.anchor;"string"==typeof e&&e&&!(e=document.querySelector(n(history.state.anchor)))||m.animateScroll(e,null,{updateURL:!1})}};m.destroy=function(){u&&(document.removeEventListener("click",h,!1),window.removeEventListener("popstate",p,!1),m.cancelScroll(),u=null,l=null,d=null,f=null)};return function(){if(!("querySelector"in document&&"addEventListener"in window&&"requestAnimationFrame"in window&&"closest"in window.Element.prototype))throw"Smooth Scroll: This browser does not support the required JavaScript methods and browser APIs.";m.destroy(),u=t(e,c||{}),d=u.header?document.querySelector(u.header):null,document.addEventListener("click",h,!1),u.updateURL&&u.popstate&&window.addEventListener("popstate",p,!1)}(),m}}));
diff --git a/dist/smooth-scroll.polyfills.js b/dist/smooth-scroll.polyfills.js
index 553531a..3c98174 100644
--- a/dist/smooth-scroll.polyfills.js
+++ b/dist/smooth-scroll.polyfills.js
@@ -1,108 +1,101 @@
-/*!
- * smooth-scroll v14.2.1: Animate scrolling to anchor links
- * (c) 2018 Chris Ferdinandi
- * MIT License
- * http://github.com/cferdinandi/smooth-scroll
- */
-
-/**
- * closest() polyfill
- * @link https://developer.mozilla.org/en-US/docs/Web/API/Element/closest#Polyfill
- */
-if (window.Element && !Element.prototype.closest) {
- Element.prototype.closest = function(s) {
- var matches = (this.document || this.ownerDocument).querySelectorAll(s),
- i,
- el = this;
- do {
- i = matches.length;
- while (--i >= 0 && matches.item(i) !== el) {}
- } while ((i < 0) && (el = el.parentElement));
- return el;
- };
-}
+/*! SmoothScroll v16.1.4 | (c) 2020 Chris Ferdinandi | MIT License | http://github.com/cferdinandi/smooth-scroll */
+(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
+ typeof define === 'function' && define.amd ? define(factory) :
+ (global = global || self, global.SmoothScroll = factory());
+}(this, (function () { 'use strict';
-/**
- * CustomEvent() polyfill
- * https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent#Polyfill
- */
-(function () {
+ /**
+ * closest() polyfill
+ * @link https://developer.mozilla.org/en-US/docs/Web/API/Element/closest#Polyfill
+ */
+ if (window.Element && !Element.prototype.closest) {
+ Element.prototype.closest = function(s) {
+ var matches = (this.document || this.ownerDocument).querySelectorAll(s),
+ i,
+ el = this;
+ do {
+ i = matches.length;
+ while (--i >= 0 && matches.item(i) !== el) {}
+ } while ((i < 0) && (el = el.parentElement));
+ return el;
+ };
+ }
- if (typeof window.CustomEvent === "function") return false;
+ /**
+ * CustomEvent() polyfill
+ * https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent#Polyfill
+ */
+ (function () {
- function CustomEvent(event, params) {
- params = params || { bubbles: false, cancelable: false, detail: undefined };
- var evt = document.createEvent('CustomEvent');
- evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);
- return evt;
- }
+ if (typeof window.CustomEvent === "function") return false;
- CustomEvent.prototype = window.Event.prototype;
-
- window.CustomEvent = CustomEvent;
-})();
-/**
- * requestAnimationFrame() polyfill
- * By Erik Möller. Fixes from Paul Irish and Tino Zijdel.
- * @link http://paulirish.com/2011/requestanimationframe-for-smart-animating/
- * @link http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating
- * @license MIT
- */
-(function() {
- var lastTime = 0;
- var vendors = ['ms', 'moz', 'webkit', 'o'];
- for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
- window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
- window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame'] ||
- window[vendors[x]+'CancelRequestAnimationFrame'];
- }
+ function CustomEvent(event, params) {
+ params = params || { bubbles: false, cancelable: false, detail: undefined };
+ var evt = document.createEvent('CustomEvent');
+ evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);
+ return evt;
+ }
- if (!window.requestAnimationFrame) {
- window.requestAnimationFrame = function(callback, element) {
- var currTime = new Date().getTime();
- var timeToCall = Math.max(0, 16 - (currTime - lastTime));
- var id = window.setTimeout((function() { callback(currTime + timeToCall); }),
- timeToCall);
- lastTime = currTime + timeToCall;
- return id;
- };
- }
+ CustomEvent.prototype = window.Event.prototype;
- if (!window.cancelAnimationFrame) {
- window.cancelAnimationFrame = function(id) {
- clearTimeout(id);
- };
- }
-}());
-
-(function (root, factory) {
- if (typeof define === 'function' && define.amd) {
- define([], (function () {
- return factory(root);
- }));
- } else if (typeof exports === 'object') {
- module.exports = factory(root);
- } else {
- root.SmoothScroll = factory(root);
- }
-})(typeof global !== 'undefined' ? global : typeof window !== 'undefined' ? window : this, (function (window) {
+ window.CustomEvent = CustomEvent;
+ })();
- 'use strict';
+ /**
+ * requestAnimationFrame() polyfill
+ * By Erik Möller. Fixes from Paul Irish and Tino Zijdel.
+ * @link http://paulirish.com/2011/requestanimationframe-for-smart-animating/
+ * @link http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating
+ * @license MIT
+ */
+ (function() {
+ var lastTime = 0;
+ var vendors = ['ms', 'moz', 'webkit', 'o'];
+ for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
+ window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
+ window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame'] ||
+ window[vendors[x]+'CancelRequestAnimationFrame'];
+ }
+
+ if (!window.requestAnimationFrame) {
+ window.requestAnimationFrame = function(callback, element) {
+ var currTime = new Date().getTime();
+ var timeToCall = Math.max(0, 16 - (currTime - lastTime));
+ var id = window.setTimeout(function() { callback(currTime + timeToCall); },
+ timeToCall);
+ lastTime = currTime + timeToCall;
+ return id;
+ };
+ }
+
+ if (!window.cancelAnimationFrame) {
+ window.cancelAnimationFrame = function(id) {
+ clearTimeout(id);
+ };
+ }
+ }());
//
// Default settings
//
var defaults = {
+
// Selectors
ignore: '[data-scroll-ignore]',
header: null,
topOnEmptyHash: true,
- // Speed & Easing
+ // Speed & Duration
speed: 500,
+ speedAsDuration: false,
+ durationMax: null,
+ durationMin: null,
clip: true,
offset: 0,
+
+ // Easing
easing: 'easeInOutCubic',
customEasing: null,
@@ -112,6 +105,7 @@ if (window.Element && !Element.prototype.closest) {
// Custom Events
emitEvents: true
+
};
@@ -133,38 +127,26 @@ if (window.Element && !Element.prototype.closest) {
};
/**
- * Merge two or more objects. Returns a new object.
- * @param {Object} objects The objects to merge together
- * @returns {Object} Merged values of defaults and options
+ * Merge two or more objects together.
+ * @param {Object} objects The objects to merge together
+ * @returns {Object} Merged values of defaults and options
*/
var extend = function () {
-
- // Variables
- var extended = {};
-
- // Merge the object into the extended object
- var merge = function (obj) {
- for (var prop in obj) {
- if (obj.hasOwnProperty(prop)) {
- extended[prop] = obj[prop];
- }
+ var merged = {};
+ Array.prototype.forEach.call(arguments, function (obj) {
+ for (var key in obj) {
+ if (!obj.hasOwnProperty(key)) return;
+ merged[key] = obj[key];
}
- };
-
- // Loop through each object and conduct a merge
- for (var i = 0; i < arguments.length; i++) {
- merge(arguments[i]);
- }
-
- return extended;
-
+ });
+ return merged;
};
/**
* Check to see if user prefers reduced motion
* @param {Object} settings Script settings
*/
- var reduceMotion = function (settings) {
+ var reduceMotion = function () {
if ('matchMedia' in window && window.matchMedia('(prefers-reduced-motion)').matches) {
return true;
}
@@ -180,21 +162,6 @@ if (window.Element && !Element.prototype.closest) {
return parseInt(window.getComputedStyle(elem).height, 10);
};
- /**
- * Decode a URI, with error check
- * @param {String} hash The URI to decode
- * @return {String} A decoded URI (or the original string if an error is thrown)
- */
- var decode = function (hash) {
- var decoded;
- try {
- decoded = decodeURIComponent(hash);
- } catch(e) {
- decoded = hash;
- }
- return decoded;
- };
-
/**
* Escape special characters for use with querySelector
* @author Mathias Bynens
@@ -271,21 +238,15 @@ if (window.Element && !Element.prototype.closest) {
}
// Return sanitized hash
- var hash;
- try {
- hash = decodeURIComponent('#' + result);
- } catch(e) {
- hash = '#' + result;
- }
- return hash;
+ return '#' + result;
};
/**
* Calculate the easing pattern
* @link https://gist.github.com/gre/1650294
- * @param {String} type Easing pattern
- * @param {Number} time Time animation should take to complete
+ * @param {Object} settings Easing pattern
+ * @param {Number} time Time animation should take to complete
* @returns {Number}
*/
var easingPattern = function (settings, time) {
@@ -344,7 +305,7 @@ if (window.Element && !Element.prototype.closest) {
if (clip) {
location = Math.min(location, getDocumentHeight() - window.innerHeight);
}
- return location;
+ return location;
};
/**
@@ -356,6 +317,40 @@ if (window.Element && !Element.prototype.closest) {
return !header ? 0 : (getHeight(header) + header.offsetTop);
};
+ /**
+ * Calculate the speed to use for the animation
+ * @param {Number} distance The distance to travel
+ * @param {Object} settings The plugin settings
+ * @return {Number} How fast to animate
+ */
+ var getSpeed = function (distance, settings) {
+ var speed = settings.speedAsDuration ? settings.speed : Math.abs(distance / 1000 * settings.speed);
+ if (settings.durationMax && speed > settings.durationMax) return settings.durationMax;
+ if (settings.durationMin && speed < settings.durationMin) return settings.durationMin;
+ return parseInt(speed, 10);
+ };
+
+ var setHistory = function (options) {
+
+ // Make sure this should run
+ if (!history.replaceState || !options.updateURL || history.state) return;
+
+ // Get the hash to use
+ var hash = window.location.hash;
+ hash = hash ? hash : '';
+
+ // Set a default history
+ history.replaceState(
+ {
+ smoothScroll: JSON.stringify(options),
+ anchor: hash ? hash : window.pageYOffset
+ },
+ document.title,
+ hash ? hash : window.location.href
+ );
+
+ };
+
/**
* Update the URL
* @param {Node} anchor The anchor that was scrolled to
@@ -440,7 +435,7 @@ if (window.Element && !Element.prototype.closest) {
//
var smoothScroll = {}; // Object for public APIs
- var settings, anchor, toggle, fixedHeader, headerHeight, eventTimeout, animationInterval;
+ var settings, toggle, fixedHeader, animationInterval;
//
@@ -465,26 +460,27 @@ if (window.Element && !Element.prototype.closest) {
*/
smoothScroll.animateScroll = function (anchor, toggle, options) {
+ // Cancel any in progress scrolls
+ smoothScroll.cancelScroll();
+
// Local settings
- var animateSettings = extend(settings || defaults, options || {}); // Merge user options with defaults
+ var _settings = extend(settings || defaults, options || {}); // Merge user options with defaults
// Selectors and variables
var isNum = Object.prototype.toString.call(anchor) === '[object Number]' ? true : false;
var anchorElem = isNum || !anchor.tagName ? null : anchor;
if (!isNum && !anchorElem) return;
var startLocation = window.pageYOffset; // Current location on the page
- if (animateSettings.header && !fixedHeader) {
+ if (_settings.header && !fixedHeader) {
// Get the fixed header if not already set
- fixedHeader = document.querySelector(animateSettings.header);
+ fixedHeader = document.querySelector(_settings.header);
}
- if (!headerHeight) {
- // Get the height of a fixed header if one exists and not already set
- headerHeight = getHeaderHeight(fixedHeader);
- }
- var endLocation = isNum ? anchor : getEndLocation(anchorElem, headerHeight, parseInt((typeof animateSettings.offset === 'function' ? animateSettings.offset(anchor, toggle) : animateSettings.offset), 10), animateSettings.clip); // Location to scroll to
+ var headerHeight = getHeaderHeight(fixedHeader);
+ var endLocation = isNum ? anchor : getEndLocation(anchorElem, headerHeight, parseInt((typeof _settings.offset === 'function' ? _settings.offset(anchor, toggle) : _settings.offset), 10), _settings.clip); // Location to scroll to
var distance = endLocation - startLocation; // distance to travel
var documentHeight = getDocumentHeight();
var timeLapsed = 0;
+ var speed = getSpeed(distance, _settings);
var start, percentage, position;
/**
@@ -508,7 +504,7 @@ if (window.Element && !Element.prototype.closest) {
adjustFocus(anchor, endLocation, isNum);
// Emit a custom event
- emitEvent('scrollStop', animateSettings, anchor, toggle);
+ emitEvent('scrollStop', _settings, anchor, toggle);
// Reset start
start = null;
@@ -525,9 +521,9 @@ if (window.Element && !Element.prototype.closest) {
var loopAnimateScroll = function (timestamp) {
if (!start) { start = timestamp; }
timeLapsed += timestamp - start;
- percentage = (timeLapsed / parseInt(animateSettings.speed, 10));
+ percentage = speed === 0 ? 0 : (timeLapsed / speed);
percentage = (percentage > 1) ? 1 : percentage;
- position = startLocation + (distance * easingPattern(animateSettings, percentage));
+ position = startLocation + (distance * easingPattern(_settings, percentage));
window.scrollTo(0, Math.floor(position));
if (!stopAnimateScroll(position, endLocation)) {
animationInterval = window.requestAnimationFrame(loopAnimateScroll);
@@ -544,10 +540,16 @@ if (window.Element && !Element.prototype.closest) {
}
// Update the URL
- updateURL(anchor, isNum, animateSettings);
+ updateURL(anchor, isNum, _settings);
+
+ // If the user prefers reduced motion, jump to location
+ if (reduceMotion()) {
+ adjustFocus(anchor, Math.floor(endLocation), false);
+ return;
+ }
// Emit a custom event
- emitEvent('scrollStart', animateSettings, anchor, toggle);
+ emitEvent('scrollStart', _settings, anchor, toggle);
// Start scrolling animation
smoothScroll.cancelScroll(true);
@@ -560,15 +562,16 @@ if (window.Element && !Element.prototype.closest) {
*/
var clickHandler = function (event) {
- // Don't run if the user prefers reduced motion
- if (reduceMotion(settings)) return;
+ // Don't run if event was canceled but still bubbled up
+ // By @mgreter - https://github.com/cferdinandi/smooth-scroll/pull/462/
+ if (event.defaultPrevented) return;
- // Don't run if right-click or command/control + click
- if (event.button !== 0 || event.metaKey || event.ctrlKey) return;
+ // Don't run if right-click or command/control + click or shift + click
+ if (event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey) return;
// Check if event.target has closest() method
// By @totegi - https://github.com/cferdinandi/smooth-scroll/pull/401/
- if(!('closest' in event.target))return;
+ if (!('closest' in event.target)) return;
// Check if a smooth scroll link was clicked
toggle = event.target.closest(selector);
@@ -578,15 +581,27 @@ if (window.Element && !Element.prototype.closest) {
if (toggle.hostname !== window.location.hostname || toggle.pathname !== window.location.pathname || !/#/.test(toggle.href)) return;
// Get an escaped version of the hash
- var hash = escapeCharacters(decode(toggle.hash));
+ var hash;
+ try {
+ hash = escapeCharacters(decodeURIComponent(toggle.hash));
+ } catch(e) {
+ hash = escapeCharacters(toggle.hash);
+ }
// Get the anchored element
- var anchor = settings.topOnEmptyHash && hash === '#' ? document.documentElement : document.querySelector(hash);
+ var anchor;
+ if (hash === '#') {
+ if (!settings.topOnEmptyHash) return;
+ anchor = document.documentElement;
+ } else {
+ anchor = document.querySelector(hash);
+ }
anchor = !anchor && hash === '#top' ? document.documentElement : anchor;
// If anchored element exists, scroll to it
if (!anchor) return;
event.preventDefault();
+ setHistory(settings);
smoothScroll.animateScroll(anchor, toggle);
};
@@ -594,38 +609,27 @@ if (window.Element && !Element.prototype.closest) {
/**
* Animate scroll on popstate events
*/
- var popstateHandler = function (event) {
+ var popstateHandler = function () {
+
// Stop if history.state doesn't exist (ex. if clicking on a broken anchor link).
// fixes `Cannot read property 'smoothScroll' of null` error getting thrown.
- if (history.state === null) return;
+ if (history.state === null) return;
// Only run if state is a popstate record for this instantiation
if (!history.state.smoothScroll || history.state.smoothScroll !== JSON.stringify(settings)) return;
- // Only run if state includes an anchor
- if (!history.state.anchor) return;
-
// Get the anchor
- var anchor = document.querySelector(escapeCharacters(decode(history.state.anchor)));
- if (!anchor) return;
+ var anchor = history.state.anchor;
+ if (typeof anchor === 'string' && anchor) {
+ anchor = document.querySelector(escapeCharacters(history.state.anchor));
+ if (!anchor) return;
+ }
// Animate scroll to anchor link
smoothScroll.animateScroll(anchor, null, {updateURL: false});
};
- /**
- * On window scroll and resize, only run events at a rate of 15fps for better performance
- */
- var resizeThrottler = function (event) {
- if (!eventTimeout) {
- eventTimeout = setTimeout((function() {
- eventTimeout = null; // Reset timeout
- headerHeight = getHeaderHeight(fixedHeader); // Get the height of a fixed header if one exists
- }), 66);
- }
- };
-
/**
* Destroy the current initialization.
*/
@@ -636,7 +640,6 @@ if (window.Element && !Element.prototype.closest) {
// Remove event listeners
document.removeEventListener('click', clickHandler, false);
- window.removeEventListener('resize', resizeThrottler, false);
window.removeEventListener('popstate', popstateHandler, false);
// Cancel any scrolls-in-progress
@@ -644,11 +647,8 @@ if (window.Element && !Element.prototype.closest) {
// Reset variables
settings = null;
- anchor = null;
toggle = null;
fixedHeader = null;
- headerHeight = null;
- eventTimeout = null;
animationInterval = null;
};
@@ -657,7 +657,7 @@ if (window.Element && !Element.prototype.closest) {
* Initialize Smooth Scroll
* @param {Object} options User settings
*/
- smoothScroll.init = function (options) {
+ var init = function () {
// feature test
if (!supports()) throw 'Smooth Scroll: This browser does not support the required JavaScript methods and browser APIs.';
@@ -668,16 +668,10 @@ if (window.Element && !Element.prototype.closest) {
// Selectors and variables
settings = extend(defaults, options || {}); // Merge user options with defaults
fixedHeader = settings.header ? document.querySelector(settings.header) : null; // Get the fixed header
- headerHeight = getHeaderHeight(fixedHeader);
// When a toggle is clicked, run the click handler
document.addEventListener('click', clickHandler, false);
- // If window is resized and there's a fixed header, recalculate its size
- if (fixedHeader) {
- window.addEventListener('resize', resizeThrottler, false);
- }
-
// If updateURL and popState are enabled, listen for pop events
if (settings.updateURL && settings.popstate) {
window.addEventListener('popstate', popstateHandler, false);
@@ -690,7 +684,7 @@ if (window.Element && !Element.prototype.closest) {
// Initialize plugin
//
- smoothScroll.init(options);
+ init();
//
@@ -703,4 +697,4 @@ if (window.Element && !Element.prototype.closest) {
return SmoothScroll;
-}));
+})));
diff --git a/dist/smooth-scroll.polyfills.min.js b/dist/smooth-scroll.polyfills.min.js
index 4ba1334..575a67b 100644
--- a/dist/smooth-scroll.polyfills.min.js
+++ b/dist/smooth-scroll.polyfills.min.js
@@ -1,2 +1,10 @@
-/*! smooth-scroll v14.2.1 | (c) 2018 Chris Ferdinandi | MIT License | http://github.com/cferdinandi/smooth-scroll */
-window.Element&&!Element.prototype.closest&&(Element.prototype.closest=function(e){var t,n=(this.document||this.ownerDocument).querySelectorAll(e),o=this;do{for(t=n.length;--t>=0&&n.item(t)!==o;);}while(t<0&&(o=o.parentElement));return o}),(function(){function e(e,t){t=t||{bubbles:!1,cancelable:!1,detail:void 0};var n=document.createEvent("CustomEvent");return n.initCustomEvent(e,t.bubbles,t.cancelable,t.detail),n}if("function"==typeof window.CustomEvent)return!1;e.prototype=window.Event.prototype,window.CustomEvent=e})(),(function(){for(var e=0,t=["ms","moz","webkit","o"],n=0;n=1&&t<=31||127==t||0===i&&t>=48&&t<=57||1===i&&t>=48&&t<=57&&45===a?r+="\\"+t.toString(16)+" ":r+=t>=128||45===t||95===t||t>=48&&t<=57||t>=65&&t<=90||t>=97&&t<=122?n.charAt(i):"\\"+n.charAt(i)}var u;try{u=decodeURIComponent("#"+r)}catch(e){u="#"+r}return u},c=function(e,t){var n;return"easeInQuad"===e.easing&&(n=t*t),"easeOutQuad"===e.easing&&(n=t*(2-t)),"easeInOutQuad"===e.easing&&(n=t<.5?2*t*t:(4-2*t)*t-1),"easeInCubic"===e.easing&&(n=t*t*t),"easeOutCubic"===e.easing&&(n=--t*t*t+1),"easeInOutCubic"===e.easing&&(n=t<.5?4*t*t*t:(t-1)*(2*t-2)*(2*t-2)+1),"easeInQuart"===e.easing&&(n=t*t*t*t),"easeOutQuart"===e.easing&&(n=1- --t*t*t*t),"easeInOutQuart"===e.easing&&(n=t<.5?8*t*t*t*t:1-8*--t*t*t*t),"easeInQuint"===e.easing&&(n=t*t*t*t*t),"easeOutQuint"===e.easing&&(n=1+--t*t*t*t*t),"easeInOutQuint"===e.easing&&(n=t<.5?16*t*t*t*t*t:1+16*--t*t*t*t*t),e.customEasing&&(n=e.customEasing(t)),n||t},s=function(){return Math.max(document.body.scrollHeight,document.documentElement.scrollHeight,document.body.offsetHeight,document.documentElement.offsetHeight,document.body.clientHeight,document.documentElement.clientHeight)},l=function(t,n,o,i){var r=0;if(t.offsetParent)do{r+=t.offsetTop,t=t.offsetParent}while(t);return r=Math.max(r-n-o,0),i&&(r=Math.min(r,s()-e.innerHeight)),r},m=function(e){return e?r(e)+e.offsetTop:0},d=function(e,t,n){t||history.pushState&&n.updateURL&&history.pushState({smoothScroll:JSON.stringify(n),anchor:e.id},document.title,e===document.documentElement?"#top":"#"+e.id)},f=function(t,n,o){0===t&&document.body.focus(),o||(t.focus(),document.activeElement!==t&&(t.setAttribute("tabindex","-1"),t.focus(),t.style.outline="none"),e.scrollTo(0,n))},h=function(t,n,o,i){if(n.emitEvents&&"function"==typeof e.CustomEvent){var r=new CustomEvent(t,{bubbles:!0,detail:{anchor:o,toggle:i}});document.dispatchEvent(r)}};return function(r,p){var g,v,w,y,E,b,S,A={};A.cancelScroll=function(e){cancelAnimationFrame(S),S=null,e||h("scrollCancel",g)},A.animateScroll=function(n,i,r){var a=o(g||t,r||{}),u="[object Number]"===Object.prototype.toString.call(n),p=u||!n.tagName?null:n;if(u||p){var v=e.pageYOffset;a.header&&!y&&(y=document.querySelector(a.header)),E||(E=m(y));var w,b,C,O=u?n:l(p,E,parseInt("function"==typeof a.offset?a.offset(n,i):a.offset,10),a.clip),I=O-v,q=s(),F=0,L=function(t,o){var r=e.pageYOffset;if(t==o||r==o||(v=q)return A.cancelScroll(!0),f(n,o,u),h("scrollStop",a,n,i),w=null,S=null,!0},H=function(t){w||(w=t),F+=t-w,b=F/parseInt(a.speed,10),b=b>1?1:b,C=v+I*c(a,b),e.scrollTo(0,Math.floor(C)),L(C,O)||(S=e.requestAnimationFrame(H),w=t)};0===e.pageYOffset&&e.scrollTo(0,0),d(n,u,a),h("scrollStart",a,n,i),A.cancelScroll(!0),e.requestAnimationFrame(H)}};var C=function(t){if(!i()&&0===t.button&&!t.metaKey&&!t.ctrlKey&&"closest"in t.target&&(w=t.target.closest(r))&&"a"===w.tagName.toLowerCase()&&!t.target.closest(g.ignore)&&w.hostname===e.location.hostname&&w.pathname===e.location.pathname&&/#/.test(w.href)){var n=u(a(w.hash)),o=g.topOnEmptyHash&&"#"===n?document.documentElement:document.querySelector(n);o=o||"#top"!==n?o:document.documentElement,o&&(t.preventDefault(),A.animateScroll(o,w))}},O=function(e){if(null!==history.state&&history.state.smoothScroll&&history.state.smoothScroll===JSON.stringify(g)&&history.state.anchor){var t=document.querySelector(u(a(history.state.anchor)));t&&A.animateScroll(t,null,{updateURL:!1})}},I=function(e){b||(b=setTimeout((function(){b=null,E=m(y)}),66))};return A.destroy=function(){g&&(document.removeEventListener("click",C,!1),e.removeEventListener("resize",I,!1),e.removeEventListener("popstate",O,!1),A.cancelScroll(),g=null,v=null,w=null,y=null,E=null,b=null,S=null)},A.init=function(i){if(!n())throw"Smooth Scroll: This browser does not support the required JavaScript methods and browser APIs.";A.destroy(),g=o(t,i||{}),y=g.header?document.querySelector(g.header):null,E=m(y),document.addEventListener("click",C,!1),y&&e.addEventListener("resize",I,!1),g.updateURL&&g.popstate&&e.addEventListener("popstate",O,!1)},A.init(p),A}}));
\ No newline at end of file
+/*! SmoothScroll v16.1.4 | (c) 2020 Chris Ferdinandi | MIT License | http://github.com/cferdinandi/smooth-scroll */
+!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e=e||self).SmoothScroll=t()}(this,(function(){"use strict";window.Element&&!Element.prototype.closest&&(Element.prototype.closest=function(e){var t,n=(this.document||this.ownerDocument).querySelectorAll(e),o=this;do{for(t=n.length;--t>=0&&n.item(t)!==o;);}while(t<0&&(o=o.parentElement));return o}),function(){if("function"==typeof window.CustomEvent)return!1;function e(e,t){t=t||{bubbles:!1,cancelable:!1,detail:void 0};var n=document.createEvent("CustomEvent");return n.initCustomEvent(e,t.bubbles,t.cancelable,t.detail),n}e.prototype=window.Event.prototype,window.CustomEvent=e}(),
+/**
+ * requestAnimationFrame() polyfill
+ * By Erik Möller. Fixes from Paul Irish and Tino Zijdel.
+ * @link http://paulirish.com/2011/requestanimationframe-for-smart-animating/
+ * @link http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating
+ * @license MIT
+ */
+function(){for(var e=0,t=["ms","moz","webkit","o"],n=0;n=1&&t<=31||127==t||0===i&&t>=48&&t<=57||1===i&&t>=48&&t<=57&&45===r?a+="\\"+t.toString(16)+" ":a+=t>=128||45===t||95===t||t>=48&&t<=57||t>=65&&t<=90||t>=97&&t<=122?n.charAt(i):"\\"+n.charAt(i)}return"#"+a},o=function(){return Math.max(document.body.scrollHeight,document.documentElement.scrollHeight,document.body.offsetHeight,document.documentElement.offsetHeight,document.body.clientHeight,document.documentElement.clientHeight)},i=function(e){return e?(t=e,parseInt(window.getComputedStyle(t).height,10)+e.offsetTop):0;var t},a=function(e,t,n){0===e&&document.body.focus(),n||(e.focus(),document.activeElement!==e&&(e.setAttribute("tabindex","-1"),e.focus(),e.style.outline="none"),window.scrollTo(0,t))},r=function(e,t,n,o){if(t.emitEvents&&"function"==typeof window.CustomEvent){var i=new CustomEvent(e,{bubbles:!0,detail:{anchor:n,toggle:o}});document.dispatchEvent(i)}};return function(c,u){var s,l,d,m,f={};f.cancelScroll=function(e){cancelAnimationFrame(m),m=null,e||r("scrollCancel",s)},f.animateScroll=function(n,c,u){f.cancelScroll();var l=t(s||e,u||{}),w="[object Number]"===Object.prototype.toString.call(n),h=w||!n.tagName?null:n;if(w||h){var p=window.pageYOffset;l.header&&!d&&(d=document.querySelector(l.header));var g,y,v,S=i(d),E=w?n:function(e,t,n,i){var a=0;if(e.offsetParent)do{a+=e.offsetTop,e=e.offsetParent}while(e);return a=Math.max(a-t-n,0),i&&(a=Math.min(a,o()-window.innerHeight)),a}(h,S,parseInt("function"==typeof l.offset?l.offset(n,c):l.offset,10),l.clip),b=E-p,A=o(),O=0,C=function(e,t){var n=t.speedAsDuration?t.speed:Math.abs(e/1e3*t.speed);return t.durationMax&&n>t.durationMax?t.durationMax:t.durationMin&&n1?1:y),window.scrollTo(0,Math.floor(v)),function(e,t){var o=window.pageYOffset;if(e==t||o==t||(p=A)return f.cancelScroll(!0),a(n,t,w),r("scrollStop",l,n,c),g=null,m=null,!0}(v,E)||(m=window.requestAnimationFrame(M),g=e)};0===window.pageYOffset&&window.scrollTo(0,0),function(e,t,n){t||history.pushState&&n.updateURL&&history.pushState({smoothScroll:JSON.stringify(n),anchor:e.id},document.title,e===document.documentElement?"#top":"#"+e.id)}(n,w,l),"matchMedia"in window&&window.matchMedia("(prefers-reduced-motion)").matches?a(n,Math.floor(E),!1):(r("scrollStart",l,n,c),f.cancelScroll(!0),window.requestAnimationFrame(M))}};var w=function(e){if(!e.defaultPrevented&&!(0!==e.button||e.metaKey||e.ctrlKey||e.shiftKey)&&"closest"in e.target&&(l=e.target.closest(c))&&"a"===l.tagName.toLowerCase()&&!e.target.closest(s.ignore)&&l.hostname===window.location.hostname&&l.pathname===window.location.pathname&&/#/.test(l.href)){var t,o;try{t=n(decodeURIComponent(l.hash))}catch(e){t=n(l.hash)}if("#"===t){if(!s.topOnEmptyHash)return;o=document.documentElement}else o=document.querySelector(t);(o=o||"#top"!==t?o:document.documentElement)&&(e.preventDefault(),function(e){if(history.replaceState&&e.updateURL&&!history.state){var t=window.location.hash;t=t||"",history.replaceState({smoothScroll:JSON.stringify(e),anchor:t||window.pageYOffset},document.title,t||window.location.href)}}(s),f.animateScroll(o,l))}},h=function(){if(null!==history.state&&history.state.smoothScroll&&history.state.smoothScroll===JSON.stringify(s)){var e=history.state.anchor;"string"==typeof e&&e&&!(e=document.querySelector(n(history.state.anchor)))||f.animateScroll(e,null,{updateURL:!1})}};f.destroy=function(){s&&(document.removeEventListener("click",w,!1),window.removeEventListener("popstate",h,!1),f.cancelScroll(),s=null,l=null,d=null,m=null)};return function(){if(!("querySelector"in document&&"addEventListener"in window&&"requestAnimationFrame"in window&&"closest"in window.Element.prototype))throw"Smooth Scroll: This browser does not support the required JavaScript methods and browser APIs.";f.destroy(),s=t(e,u||{}),d=s.header?document.querySelector(s.header):null,document.addEventListener("click",w,!1),s.updateURL&&s.popstate&&window.addEventListener("popstate",h,!1)}(),f}}));
diff --git a/docs/dist/smooth-scroll.js b/docs/dist/smooth-scroll.js
deleted file mode 100755
index 74ce7cc..0000000
--- a/docs/dist/smooth-scroll.js
+++ /dev/null
@@ -1,636 +0,0 @@
-/*!
- * smooth-scroll v14.2.1: Animate scrolling to anchor links
- * (c) 2018 Chris Ferdinandi
- * MIT License
- * http://github.com/cferdinandi/smooth-scroll
- */
-
-(function (root, factory) {
- if (typeof define === 'function' && define.amd) {
- define([], (function () {
- return factory(root);
- }));
- } else if (typeof exports === 'object') {
- module.exports = factory(root);
- } else {
- root.SmoothScroll = factory(root);
- }
-})(typeof global !== 'undefined' ? global : typeof window !== 'undefined' ? window : this, (function (window) {
-
- 'use strict';
-
- //
- // Default settings
- //
-
- var defaults = {
- // Selectors
- ignore: '[data-scroll-ignore]',
- header: null,
- topOnEmptyHash: true,
-
- // Speed & Easing
- speed: 500,
- clip: true,
- offset: 0,
- easing: 'easeInOutCubic',
- customEasing: null,
-
- // History
- updateURL: true,
- popstate: true,
-
- // Custom Events
- emitEvents: true
- };
-
-
- //
- // Utility Methods
- //
-
- /**
- * Check if browser supports required methods
- * @return {Boolean} Returns true if all required methods are supported
- */
- var supports = function () {
- return (
- 'querySelector' in document &&
- 'addEventListener' in window &&
- 'requestAnimationFrame' in window &&
- 'closest' in window.Element.prototype
- );
- };
-
- /**
- * Merge two or more objects. Returns a new object.
- * @param {Object} objects The objects to merge together
- * @returns {Object} Merged values of defaults and options
- */
- var extend = function () {
-
- // Variables
- var extended = {};
-
- // Merge the object into the extended object
- var merge = function (obj) {
- for (var prop in obj) {
- if (obj.hasOwnProperty(prop)) {
- extended[prop] = obj[prop];
- }
- }
- };
-
- // Loop through each object and conduct a merge
- for (var i = 0; i < arguments.length; i++) {
- merge(arguments[i]);
- }
-
- return extended;
-
- };
-
- /**
- * Check to see if user prefers reduced motion
- * @param {Object} settings Script settings
- */
- var reduceMotion = function (settings) {
- if ('matchMedia' in window && window.matchMedia('(prefers-reduced-motion)').matches) {
- return true;
- }
- return false;
- };
-
- /**
- * Get the height of an element.
- * @param {Node} elem The element to get the height of
- * @return {Number} The element's height in pixels
- */
- var getHeight = function (elem) {
- return parseInt(window.getComputedStyle(elem).height, 10);
- };
-
- /**
- * Decode a URI, with error check
- * @param {String} hash The URI to decode
- * @return {String} A decoded URI (or the original string if an error is thrown)
- */
- var decode = function (hash) {
- var decoded;
- try {
- decoded = decodeURIComponent(hash);
- } catch(e) {
- decoded = hash;
- }
- return decoded;
- };
-
- /**
- * Escape special characters for use with querySelector
- * @author Mathias Bynens
- * @link https://github.com/mathiasbynens/CSS.escape
- * @param {String} id The anchor ID to escape
- */
- var escapeCharacters = function (id) {
-
- // Remove leading hash
- if (id.charAt(0) === '#') {
- id = id.substr(1);
- }
-
- var string = String(id);
- var length = string.length;
- var index = -1;
- var codeUnit;
- var result = '';
- var firstCodeUnit = string.charCodeAt(0);
- while (++index < length) {
- codeUnit = string.charCodeAt(index);
- // Note: there’s no need to special-case astral symbols, surrogate
- // pairs, or lone surrogates.
-
- // If the character is NULL (U+0000), then throw an
- // `InvalidCharacterError` exception and terminate these steps.
- if (codeUnit === 0x0000) {
- throw new InvalidCharacterError(
- 'Invalid character: the input contains U+0000.'
- );
- }
-
- if (
- // If the character is in the range [\1-\1F] (U+0001 to U+001F) or is
- // U+007F, […]
- (codeUnit >= 0x0001 && codeUnit <= 0x001F) || codeUnit == 0x007F ||
- // If the character is the first character and is in the range [0-9]
- // (U+0030 to U+0039), […]
- (index === 0 && codeUnit >= 0x0030 && codeUnit <= 0x0039) ||
- // If the character is the second character and is in the range [0-9]
- // (U+0030 to U+0039) and the first character is a `-` (U+002D), […]
- (
- index === 1 &&
- codeUnit >= 0x0030 && codeUnit <= 0x0039 &&
- firstCodeUnit === 0x002D
- )
- ) {
- // http://dev.w3.org/csswg/cssom/#escape-a-character-as-code-point
- result += '\\' + codeUnit.toString(16) + ' ';
- continue;
- }
-
- // If the character is not handled by one of the above rules and is
- // greater than or equal to U+0080, is `-` (U+002D) or `_` (U+005F), or
- // is in one of the ranges [0-9] (U+0030 to U+0039), [A-Z] (U+0041 to
- // U+005A), or [a-z] (U+0061 to U+007A), […]
- if (
- codeUnit >= 0x0080 ||
- codeUnit === 0x002D ||
- codeUnit === 0x005F ||
- codeUnit >= 0x0030 && codeUnit <= 0x0039 ||
- codeUnit >= 0x0041 && codeUnit <= 0x005A ||
- codeUnit >= 0x0061 && codeUnit <= 0x007A
- ) {
- // the character itself
- result += string.charAt(index);
- continue;
- }
-
- // Otherwise, the escaped character.
- // http://dev.w3.org/csswg/cssom/#escape-a-character
- result += '\\' + string.charAt(index);
-
- }
-
- // Return sanitized hash
- var hash;
- try {
- hash = decodeURIComponent('#' + result);
- } catch(e) {
- hash = '#' + result;
- }
- return hash;
-
- };
-
- /**
- * Calculate the easing pattern
- * @link https://gist.github.com/gre/1650294
- * @param {String} type Easing pattern
- * @param {Number} time Time animation should take to complete
- * @returns {Number}
- */
- var easingPattern = function (settings, time) {
- var pattern;
-
- // Default Easing Patterns
- if (settings.easing === 'easeInQuad') pattern = time * time; // accelerating from zero velocity
- if (settings.easing === 'easeOutQuad') pattern = time * (2 - time); // decelerating to zero velocity
- if (settings.easing === 'easeInOutQuad') pattern = time < 0.5 ? 2 * time * time : -1 + (4 - 2 * time) * time; // acceleration until halfway, then deceleration
- if (settings.easing === 'easeInCubic') pattern = time * time * time; // accelerating from zero velocity
- if (settings.easing === 'easeOutCubic') pattern = (--time) * time * time + 1; // decelerating to zero velocity
- if (settings.easing === 'easeInOutCubic') pattern = time < 0.5 ? 4 * time * time * time : (time - 1) * (2 * time - 2) * (2 * time - 2) + 1; // acceleration until halfway, then deceleration
- if (settings.easing === 'easeInQuart') pattern = time * time * time * time; // accelerating from zero velocity
- if (settings.easing === 'easeOutQuart') pattern = 1 - (--time) * time * time * time; // decelerating to zero velocity
- if (settings.easing === 'easeInOutQuart') pattern = time < 0.5 ? 8 * time * time * time * time : 1 - 8 * (--time) * time * time * time; // acceleration until halfway, then deceleration
- if (settings.easing === 'easeInQuint') pattern = time * time * time * time * time; // accelerating from zero velocity
- if (settings.easing === 'easeOutQuint') pattern = 1 + (--time) * time * time * time * time; // decelerating to zero velocity
- if (settings.easing === 'easeInOutQuint') pattern = time < 0.5 ? 16 * time * time * time * time * time : 1 + 16 * (--time) * time * time * time * time; // acceleration until halfway, then deceleration
-
- // Custom Easing Patterns
- if (!!settings.customEasing) pattern = settings.customEasing(time);
-
- return pattern || time; // no easing, no acceleration
- };
-
- /**
- * Determine the document's height
- * @returns {Number}
- */
- var getDocumentHeight = function () {
- return Math.max(
- document.body.scrollHeight, document.documentElement.scrollHeight,
- document.body.offsetHeight, document.documentElement.offsetHeight,
- document.body.clientHeight, document.documentElement.clientHeight
- );
- };
-
- /**
- * Calculate how far to scroll
- * Clip support added by robjtede - https://github.com/cferdinandi/smooth-scroll/issues/405
- * @param {Element} anchor The anchor element to scroll to
- * @param {Number} headerHeight Height of a fixed header, if any
- * @param {Number} offset Number of pixels by which to offset scroll
- * @param {Boolean} clip If true, adjust scroll distance to prevent abrupt stops near the bottom of the page
- * @returns {Number}
- */
- var getEndLocation = function (anchor, headerHeight, offset, clip) {
- var location = 0;
- if (anchor.offsetParent) {
- do {
- location += anchor.offsetTop;
- anchor = anchor.offsetParent;
- } while (anchor);
- }
- location = Math.max(location - headerHeight - offset, 0);
- if (clip) {
- location = Math.min(location, getDocumentHeight() - window.innerHeight);
- }
- return location;
- };
-
- /**
- * Get the height of the fixed header
- * @param {Node} header The header
- * @return {Number} The height of the header
- */
- var getHeaderHeight = function (header) {
- return !header ? 0 : (getHeight(header) + header.offsetTop);
- };
-
- /**
- * Update the URL
- * @param {Node} anchor The anchor that was scrolled to
- * @param {Boolean} isNum If true, anchor is a number
- * @param {Object} options Settings for Smooth Scroll
- */
- var updateURL = function (anchor, isNum, options) {
-
- // Bail if the anchor is a number
- if (isNum) return;
-
- // Verify that pushState is supported and the updateURL option is enabled
- if (!history.pushState || !options.updateURL) return;
-
- // Update URL
- history.pushState(
- {
- smoothScroll: JSON.stringify(options),
- anchor: anchor.id
- },
- document.title,
- anchor === document.documentElement ? '#top' : '#' + anchor.id
- );
-
- };
-
- /**
- * Bring the anchored element into focus
- * @param {Node} anchor The anchor element
- * @param {Number} endLocation The end location to scroll to
- * @param {Boolean} isNum If true, scroll is to a position rather than an element
- */
- var adjustFocus = function (anchor, endLocation, isNum) {
-
- // Is scrolling to top of page, blur
- if (anchor === 0) {
- document.body.focus();
- }
-
- // Don't run if scrolling to a number on the page
- if (isNum) return;
-
- // Otherwise, bring anchor element into focus
- anchor.focus();
- if (document.activeElement !== anchor) {
- anchor.setAttribute('tabindex', '-1');
- anchor.focus();
- anchor.style.outline = 'none';
- }
- window.scrollTo(0 , endLocation);
-
- };
-
- /**
- * Emit a custom event
- * @param {String} type The event type
- * @param {Object} options The settings object
- * @param {Node} anchor The anchor element
- * @param {Node} toggle The toggle element
- */
- var emitEvent = function (type, options, anchor, toggle) {
- if (!options.emitEvents || typeof window.CustomEvent !== 'function') return;
- var event = new CustomEvent(type, {
- bubbles: true,
- detail: {
- anchor: anchor,
- toggle: toggle
- }
- });
- document.dispatchEvent(event);
- };
-
-
- //
- // SmoothScroll Constructor
- //
-
- var SmoothScroll = function (selector, options) {
-
- //
- // Variables
- //
-
- var smoothScroll = {}; // Object for public APIs
- var settings, anchor, toggle, fixedHeader, headerHeight, eventTimeout, animationInterval;
-
-
- //
- // Methods
- //
-
- /**
- * Cancel a scroll-in-progress
- */
- smoothScroll.cancelScroll = function (noEvent) {
- cancelAnimationFrame(animationInterval);
- animationInterval = null;
- if (noEvent) return;
- emitEvent('scrollCancel', settings);
- };
-
- /**
- * Start/stop the scrolling animation
- * @param {Node|Number} anchor The element or position to scroll to
- * @param {Element} toggle The element that toggled the scroll event
- * @param {Object} options
- */
- smoothScroll.animateScroll = function (anchor, toggle, options) {
-
- // Local settings
- var animateSettings = extend(settings || defaults, options || {}); // Merge user options with defaults
-
- // Selectors and variables
- var isNum = Object.prototype.toString.call(anchor) === '[object Number]' ? true : false;
- var anchorElem = isNum || !anchor.tagName ? null : anchor;
- if (!isNum && !anchorElem) return;
- var startLocation = window.pageYOffset; // Current location on the page
- if (animateSettings.header && !fixedHeader) {
- // Get the fixed header if not already set
- fixedHeader = document.querySelector(animateSettings.header);
- }
- if (!headerHeight) {
- // Get the height of a fixed header if one exists and not already set
- headerHeight = getHeaderHeight(fixedHeader);
- }
- var endLocation = isNum ? anchor : getEndLocation(anchorElem, headerHeight, parseInt((typeof animateSettings.offset === 'function' ? animateSettings.offset(anchor, toggle) : animateSettings.offset), 10), animateSettings.clip); // Location to scroll to
- var distance = endLocation - startLocation; // distance to travel
- var documentHeight = getDocumentHeight();
- var timeLapsed = 0;
- var start, percentage, position;
-
- /**
- * Stop the scroll animation when it reaches its target (or the bottom/top of page)
- * @param {Number} position Current position on the page
- * @param {Number} endLocation Scroll to location
- * @param {Number} animationInterval How much to scroll on this loop
- */
- var stopAnimateScroll = function (position, endLocation) {
-
- // Get the current location
- var currentLocation = window.pageYOffset;
-
- // Check if the end location has been reached yet (or we've hit the end of the document)
- if (position == endLocation || currentLocation == endLocation || ((startLocation < endLocation && window.innerHeight + currentLocation) >= documentHeight)) {
-
- // Clear the animation timer
- smoothScroll.cancelScroll(true);
-
- // Bring the anchored element into focus
- adjustFocus(anchor, endLocation, isNum);
-
- // Emit a custom event
- emitEvent('scrollStop', animateSettings, anchor, toggle);
-
- // Reset start
- start = null;
- animationInterval = null;
-
- return true;
-
- }
- };
-
- /**
- * Loop scrolling animation
- */
- var loopAnimateScroll = function (timestamp) {
- if (!start) { start = timestamp; }
- timeLapsed += timestamp - start;
- percentage = (timeLapsed / parseInt(animateSettings.speed, 10));
- percentage = (percentage > 1) ? 1 : percentage;
- position = startLocation + (distance * easingPattern(animateSettings, percentage));
- window.scrollTo(0, Math.floor(position));
- if (!stopAnimateScroll(position, endLocation)) {
- animationInterval = window.requestAnimationFrame(loopAnimateScroll);
- start = timestamp;
- }
- };
-
- /**
- * Reset position to fix weird iOS bug
- * @link https://github.com/cferdinandi/smooth-scroll/issues/45
- */
- if (window.pageYOffset === 0) {
- window.scrollTo(0, 0);
- }
-
- // Update the URL
- updateURL(anchor, isNum, animateSettings);
-
- // Emit a custom event
- emitEvent('scrollStart', animateSettings, anchor, toggle);
-
- // Start scrolling animation
- smoothScroll.cancelScroll(true);
- window.requestAnimationFrame(loopAnimateScroll);
-
- };
-
- /**
- * If smooth scroll element clicked, animate scroll
- */
- var clickHandler = function (event) {
-
- // Don't run if the user prefers reduced motion
- if (reduceMotion(settings)) return;
-
- // Don't run if right-click or command/control + click
- if (event.button !== 0 || event.metaKey || event.ctrlKey) return;
-
- // Check if event.target has closest() method
- // By @totegi - https://github.com/cferdinandi/smooth-scroll/pull/401/
- if(!('closest' in event.target))return;
-
- // Check if a smooth scroll link was clicked
- toggle = event.target.closest(selector);
- if (!toggle || toggle.tagName.toLowerCase() !== 'a' || event.target.closest(settings.ignore)) return;
-
- // Only run if link is an anchor and points to the current page
- if (toggle.hostname !== window.location.hostname || toggle.pathname !== window.location.pathname || !/#/.test(toggle.href)) return;
-
- // Get an escaped version of the hash
- var hash = escapeCharacters(decode(toggle.hash));
-
- // Get the anchored element
- var anchor = settings.topOnEmptyHash && hash === '#' ? document.documentElement : document.querySelector(hash);
- anchor = !anchor && hash === '#top' ? document.documentElement : anchor;
-
- // If anchored element exists, scroll to it
- if (!anchor) return;
- event.preventDefault();
- smoothScroll.animateScroll(anchor, toggle);
-
- };
-
- /**
- * Animate scroll on popstate events
- */
- var popstateHandler = function (event) {
- // Stop if history.state doesn't exist (ex. if clicking on a broken anchor link).
- // fixes `Cannot read property 'smoothScroll' of null` error getting thrown.
- if (history.state === null) return;
-
- // Only run if state is a popstate record for this instantiation
- if (!history.state.smoothScroll || history.state.smoothScroll !== JSON.stringify(settings)) return;
-
- // Only run if state includes an anchor
- if (!history.state.anchor) return;
-
- // Get the anchor
- var anchor = document.querySelector(escapeCharacters(decode(history.state.anchor)));
- if (!anchor) return;
-
- // Animate scroll to anchor link
- smoothScroll.animateScroll(anchor, null, {updateURL: false});
-
- };
-
- /**
- * On window scroll and resize, only run events at a rate of 15fps for better performance
- */
- var resizeThrottler = function (event) {
- if (!eventTimeout) {
- eventTimeout = setTimeout((function() {
- eventTimeout = null; // Reset timeout
- headerHeight = getHeaderHeight(fixedHeader); // Get the height of a fixed header if one exists
- }), 66);
- }
- };
-
- /**
- * Destroy the current initialization.
- */
- smoothScroll.destroy = function () {
-
- // If plugin isn't already initialized, stop
- if (!settings) return;
-
- // Remove event listeners
- document.removeEventListener('click', clickHandler, false);
- window.removeEventListener('resize', resizeThrottler, false);
- window.removeEventListener('popstate', popstateHandler, false);
-
- // Cancel any scrolls-in-progress
- smoothScroll.cancelScroll();
-
- // Reset variables
- settings = null;
- anchor = null;
- toggle = null;
- fixedHeader = null;
- headerHeight = null;
- eventTimeout = null;
- animationInterval = null;
-
- };
-
- /**
- * Initialize Smooth Scroll
- * @param {Object} options User settings
- */
- smoothScroll.init = function (options) {
-
- // feature test
- if (!supports()) throw 'Smooth Scroll: This browser does not support the required JavaScript methods and browser APIs.';
-
- // Destroy any existing initializations
- smoothScroll.destroy();
-
- // Selectors and variables
- settings = extend(defaults, options || {}); // Merge user options with defaults
- fixedHeader = settings.header ? document.querySelector(settings.header) : null; // Get the fixed header
- headerHeight = getHeaderHeight(fixedHeader);
-
- // When a toggle is clicked, run the click handler
- document.addEventListener('click', clickHandler, false);
-
- // If window is resized and there's a fixed header, recalculate its size
- if (fixedHeader) {
- window.addEventListener('resize', resizeThrottler, false);
- }
-
- // If updateURL and popState are enabled, listen for pop events
- if (settings.updateURL && settings.popstate) {
- window.addEventListener('popstate', popstateHandler, false);
- }
-
- };
-
-
- //
- // Initialize plugin
- //
-
- smoothScroll.init(options);
-
-
- //
- // Public APIs
- //
-
- return smoothScroll;
-
- };
-
- return SmoothScroll;
-
-}));
diff --git a/docs/dist/smooth-scroll.min.js b/docs/dist/smooth-scroll.min.js
deleted file mode 100755
index f4ba547..0000000
--- a/docs/dist/smooth-scroll.min.js
+++ /dev/null
@@ -1,2 +0,0 @@
-/*! smooth-scroll v14.2.1 | (c) 2018 Chris Ferdinandi | MIT License | http://github.com/cferdinandi/smooth-scroll */
-!(function(e,t){"function"==typeof define&&define.amd?define([],(function(){return t(e)})):"object"==typeof exports?module.exports=t(e):e.SmoothScroll=t(e)})("undefined"!=typeof global?global:"undefined"!=typeof window?window:this,(function(e){"use strict";var t={ignore:"[data-scroll-ignore]",header:null,topOnEmptyHash:!0,speed:500,clip:!0,offset:0,easing:"easeInOutCubic",customEasing:null,updateURL:!0,popstate:!0,emitEvents:!0},n=function(){return"querySelector"in document&&"addEventListener"in e&&"requestAnimationFrame"in e&&"closest"in e.Element.prototype},o=function(){for(var e={},t=0;t=1&&t<=31||127==t||0===r&&t>=48&&t<=57||1===r&&t>=48&&t<=57&&45===i?a+="\\"+t.toString(16)+" ":a+=t>=128||45===t||95===t||t>=48&&t<=57||t>=65&&t<=90||t>=97&&t<=122?n.charAt(r):"\\"+n.charAt(r)}var c;try{c=decodeURIComponent("#"+a)}catch(e){c="#"+a}return c},u=function(e,t){var n;return"easeInQuad"===e.easing&&(n=t*t),"easeOutQuad"===e.easing&&(n=t*(2-t)),"easeInOutQuad"===e.easing&&(n=t<.5?2*t*t:(4-2*t)*t-1),"easeInCubic"===e.easing&&(n=t*t*t),"easeOutCubic"===e.easing&&(n=--t*t*t+1),"easeInOutCubic"===e.easing&&(n=t<.5?4*t*t*t:(t-1)*(2*t-2)*(2*t-2)+1),"easeInQuart"===e.easing&&(n=t*t*t*t),"easeOutQuart"===e.easing&&(n=1- --t*t*t*t),"easeInOutQuart"===e.easing&&(n=t<.5?8*t*t*t*t:1-8*--t*t*t*t),"easeInQuint"===e.easing&&(n=t*t*t*t*t),"easeOutQuint"===e.easing&&(n=1+--t*t*t*t*t),"easeInOutQuint"===e.easing&&(n=t<.5?16*t*t*t*t*t:1+16*--t*t*t*t*t),e.customEasing&&(n=e.customEasing(t)),n||t},s=function(){return Math.max(document.body.scrollHeight,document.documentElement.scrollHeight,document.body.offsetHeight,document.documentElement.offsetHeight,document.body.clientHeight,document.documentElement.clientHeight)},l=function(t,n,o,r){var a=0;if(t.offsetParent)do{a+=t.offsetTop,t=t.offsetParent}while(t);return a=Math.max(a-n-o,0),r&&(a=Math.min(a,s()-e.innerHeight)),a},d=function(e){return e?a(e)+e.offsetTop:0},f=function(e,t,n){t||history.pushState&&n.updateURL&&history.pushState({smoothScroll:JSON.stringify(n),anchor:e.id},document.title,e===document.documentElement?"#top":"#"+e.id)},m=function(t,n,o){0===t&&document.body.focus(),o||(t.focus(),document.activeElement!==t&&(t.setAttribute("tabindex","-1"),t.focus(),t.style.outline="none"),e.scrollTo(0,n))},h=function(t,n,o,r){if(n.emitEvents&&"function"==typeof e.CustomEvent){var a=new CustomEvent(t,{bubbles:!0,detail:{anchor:o,toggle:r}});document.dispatchEvent(a)}};return function(a,p){var g,v,y,S,E,b,O,I={};I.cancelScroll=function(e){cancelAnimationFrame(O),O=null,e||h("scrollCancel",g)},I.animateScroll=function(n,r,a){var i=o(g||t,a||{}),c="[object Number]"===Object.prototype.toString.call(n),p=c||!n.tagName?null:n;if(c||p){var v=e.pageYOffset;i.header&&!S&&(S=document.querySelector(i.header)),E||(E=d(S));var y,b,C,w=c?n:l(p,E,parseInt("function"==typeof i.offset?i.offset(n,r):i.offset,10),i.clip),L=w-v,A=s(),H=0,q=function(t,o){var a=e.pageYOffset;if(t==o||a==o||(v=A)return I.cancelScroll(!0),m(n,o,c),h("scrollStop",i,n,r),y=null,O=null,!0},Q=function(t){y||(y=t),H+=t-y,b=H/parseInt(i.speed,10),b=b>1?1:b,C=v+L*u(i,b),e.scrollTo(0,Math.floor(C)),q(C,w)||(O=e.requestAnimationFrame(Q),y=t)};0===e.pageYOffset&&e.scrollTo(0,0),f(n,c,i),h("scrollStart",i,n,r),I.cancelScroll(!0),e.requestAnimationFrame(Q)}};var C=function(t){if(!r()&&0===t.button&&!t.metaKey&&!t.ctrlKey&&"closest"in t.target&&(y=t.target.closest(a))&&"a"===y.tagName.toLowerCase()&&!t.target.closest(g.ignore)&&y.hostname===e.location.hostname&&y.pathname===e.location.pathname&&/#/.test(y.href)){var n=c(i(y.hash)),o=g.topOnEmptyHash&&"#"===n?document.documentElement:document.querySelector(n);o=o||"#top"!==n?o:document.documentElement,o&&(t.preventDefault(),I.animateScroll(o,y))}},w=function(e){if(null!==history.state&&history.state.smoothScroll&&history.state.smoothScroll===JSON.stringify(g)&&history.state.anchor){var t=document.querySelector(c(i(history.state.anchor)));t&&I.animateScroll(t,null,{updateURL:!1})}},L=function(e){b||(b=setTimeout((function(){b=null,E=d(S)}),66))};return I.destroy=function(){g&&(document.removeEventListener("click",C,!1),e.removeEventListener("resize",L,!1),e.removeEventListener("popstate",w,!1),I.cancelScroll(),g=null,v=null,y=null,S=null,E=null,b=null,O=null)},I.init=function(r){if(!n())throw"Smooth Scroll: This browser does not support the required JavaScript methods and browser APIs.";I.destroy(),g=o(t,r||{}),S=g.header?document.querySelector(g.header):null,E=d(S),document.addEventListener("click",C,!1),S&&e.addEventListener("resize",L,!1),g.updateURL&&g.popstate&&e.addEventListener("popstate",w,!1)},I.init(p),I}}));
\ No newline at end of file
diff --git a/docs/dist/smooth-scroll.polyfills.js b/docs/dist/smooth-scroll.polyfills.js
deleted file mode 100644
index 553531a..0000000
--- a/docs/dist/smooth-scroll.polyfills.js
+++ /dev/null
@@ -1,706 +0,0 @@
-/*!
- * smooth-scroll v14.2.1: Animate scrolling to anchor links
- * (c) 2018 Chris Ferdinandi
- * MIT License
- * http://github.com/cferdinandi/smooth-scroll
- */
-
-/**
- * closest() polyfill
- * @link https://developer.mozilla.org/en-US/docs/Web/API/Element/closest#Polyfill
- */
-if (window.Element && !Element.prototype.closest) {
- Element.prototype.closest = function(s) {
- var matches = (this.document || this.ownerDocument).querySelectorAll(s),
- i,
- el = this;
- do {
- i = matches.length;
- while (--i >= 0 && matches.item(i) !== el) {}
- } while ((i < 0) && (el = el.parentElement));
- return el;
- };
-}
-
-/**
- * CustomEvent() polyfill
- * https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent#Polyfill
- */
-(function () {
-
- if (typeof window.CustomEvent === "function") return false;
-
- function CustomEvent(event, params) {
- params = params || { bubbles: false, cancelable: false, detail: undefined };
- var evt = document.createEvent('CustomEvent');
- evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);
- return evt;
- }
-
- CustomEvent.prototype = window.Event.prototype;
-
- window.CustomEvent = CustomEvent;
-})();
-/**
- * requestAnimationFrame() polyfill
- * By Erik Möller. Fixes from Paul Irish and Tino Zijdel.
- * @link http://paulirish.com/2011/requestanimationframe-for-smart-animating/
- * @link http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating
- * @license MIT
- */
-(function() {
- var lastTime = 0;
- var vendors = ['ms', 'moz', 'webkit', 'o'];
- for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
- window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
- window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame'] ||
- window[vendors[x]+'CancelRequestAnimationFrame'];
- }
-
- if (!window.requestAnimationFrame) {
- window.requestAnimationFrame = function(callback, element) {
- var currTime = new Date().getTime();
- var timeToCall = Math.max(0, 16 - (currTime - lastTime));
- var id = window.setTimeout((function() { callback(currTime + timeToCall); }),
- timeToCall);
- lastTime = currTime + timeToCall;
- return id;
- };
- }
-
- if (!window.cancelAnimationFrame) {
- window.cancelAnimationFrame = function(id) {
- clearTimeout(id);
- };
- }
-}());
-
-(function (root, factory) {
- if (typeof define === 'function' && define.amd) {
- define([], (function () {
- return factory(root);
- }));
- } else if (typeof exports === 'object') {
- module.exports = factory(root);
- } else {
- root.SmoothScroll = factory(root);
- }
-})(typeof global !== 'undefined' ? global : typeof window !== 'undefined' ? window : this, (function (window) {
-
- 'use strict';
-
- //
- // Default settings
- //
-
- var defaults = {
- // Selectors
- ignore: '[data-scroll-ignore]',
- header: null,
- topOnEmptyHash: true,
-
- // Speed & Easing
- speed: 500,
- clip: true,
- offset: 0,
- easing: 'easeInOutCubic',
- customEasing: null,
-
- // History
- updateURL: true,
- popstate: true,
-
- // Custom Events
- emitEvents: true
- };
-
-
- //
- // Utility Methods
- //
-
- /**
- * Check if browser supports required methods
- * @return {Boolean} Returns true if all required methods are supported
- */
- var supports = function () {
- return (
- 'querySelector' in document &&
- 'addEventListener' in window &&
- 'requestAnimationFrame' in window &&
- 'closest' in window.Element.prototype
- );
- };
-
- /**
- * Merge two or more objects. Returns a new object.
- * @param {Object} objects The objects to merge together
- * @returns {Object} Merged values of defaults and options
- */
- var extend = function () {
-
- // Variables
- var extended = {};
-
- // Merge the object into the extended object
- var merge = function (obj) {
- for (var prop in obj) {
- if (obj.hasOwnProperty(prop)) {
- extended[prop] = obj[prop];
- }
- }
- };
-
- // Loop through each object and conduct a merge
- for (var i = 0; i < arguments.length; i++) {
- merge(arguments[i]);
- }
-
- return extended;
-
- };
-
- /**
- * Check to see if user prefers reduced motion
- * @param {Object} settings Script settings
- */
- var reduceMotion = function (settings) {
- if ('matchMedia' in window && window.matchMedia('(prefers-reduced-motion)').matches) {
- return true;
- }
- return false;
- };
-
- /**
- * Get the height of an element.
- * @param {Node} elem The element to get the height of
- * @return {Number} The element's height in pixels
- */
- var getHeight = function (elem) {
- return parseInt(window.getComputedStyle(elem).height, 10);
- };
-
- /**
- * Decode a URI, with error check
- * @param {String} hash The URI to decode
- * @return {String} A decoded URI (or the original string if an error is thrown)
- */
- var decode = function (hash) {
- var decoded;
- try {
- decoded = decodeURIComponent(hash);
- } catch(e) {
- decoded = hash;
- }
- return decoded;
- };
-
- /**
- * Escape special characters for use with querySelector
- * @author Mathias Bynens
- * @link https://github.com/mathiasbynens/CSS.escape
- * @param {String} id The anchor ID to escape
- */
- var escapeCharacters = function (id) {
-
- // Remove leading hash
- if (id.charAt(0) === '#') {
- id = id.substr(1);
- }
-
- var string = String(id);
- var length = string.length;
- var index = -1;
- var codeUnit;
- var result = '';
- var firstCodeUnit = string.charCodeAt(0);
- while (++index < length) {
- codeUnit = string.charCodeAt(index);
- // Note: there’s no need to special-case astral symbols, surrogate
- // pairs, or lone surrogates.
-
- // If the character is NULL (U+0000), then throw an
- // `InvalidCharacterError` exception and terminate these steps.
- if (codeUnit === 0x0000) {
- throw new InvalidCharacterError(
- 'Invalid character: the input contains U+0000.'
- );
- }
-
- if (
- // If the character is in the range [\1-\1F] (U+0001 to U+001F) or is
- // U+007F, […]
- (codeUnit >= 0x0001 && codeUnit <= 0x001F) || codeUnit == 0x007F ||
- // If the character is the first character and is in the range [0-9]
- // (U+0030 to U+0039), […]
- (index === 0 && codeUnit >= 0x0030 && codeUnit <= 0x0039) ||
- // If the character is the second character and is in the range [0-9]
- // (U+0030 to U+0039) and the first character is a `-` (U+002D), […]
- (
- index === 1 &&
- codeUnit >= 0x0030 && codeUnit <= 0x0039 &&
- firstCodeUnit === 0x002D
- )
- ) {
- // http://dev.w3.org/csswg/cssom/#escape-a-character-as-code-point
- result += '\\' + codeUnit.toString(16) + ' ';
- continue;
- }
-
- // If the character is not handled by one of the above rules and is
- // greater than or equal to U+0080, is `-` (U+002D) or `_` (U+005F), or
- // is in one of the ranges [0-9] (U+0030 to U+0039), [A-Z] (U+0041 to
- // U+005A), or [a-z] (U+0061 to U+007A), […]
- if (
- codeUnit >= 0x0080 ||
- codeUnit === 0x002D ||
- codeUnit === 0x005F ||
- codeUnit >= 0x0030 && codeUnit <= 0x0039 ||
- codeUnit >= 0x0041 && codeUnit <= 0x005A ||
- codeUnit >= 0x0061 && codeUnit <= 0x007A
- ) {
- // the character itself
- result += string.charAt(index);
- continue;
- }
-
- // Otherwise, the escaped character.
- // http://dev.w3.org/csswg/cssom/#escape-a-character
- result += '\\' + string.charAt(index);
-
- }
-
- // Return sanitized hash
- var hash;
- try {
- hash = decodeURIComponent('#' + result);
- } catch(e) {
- hash = '#' + result;
- }
- return hash;
-
- };
-
- /**
- * Calculate the easing pattern
- * @link https://gist.github.com/gre/1650294
- * @param {String} type Easing pattern
- * @param {Number} time Time animation should take to complete
- * @returns {Number}
- */
- var easingPattern = function (settings, time) {
- var pattern;
-
- // Default Easing Patterns
- if (settings.easing === 'easeInQuad') pattern = time * time; // accelerating from zero velocity
- if (settings.easing === 'easeOutQuad') pattern = time * (2 - time); // decelerating to zero velocity
- if (settings.easing === 'easeInOutQuad') pattern = time < 0.5 ? 2 * time * time : -1 + (4 - 2 * time) * time; // acceleration until halfway, then deceleration
- if (settings.easing === 'easeInCubic') pattern = time * time * time; // accelerating from zero velocity
- if (settings.easing === 'easeOutCubic') pattern = (--time) * time * time + 1; // decelerating to zero velocity
- if (settings.easing === 'easeInOutCubic') pattern = time < 0.5 ? 4 * time * time * time : (time - 1) * (2 * time - 2) * (2 * time - 2) + 1; // acceleration until halfway, then deceleration
- if (settings.easing === 'easeInQuart') pattern = time * time * time * time; // accelerating from zero velocity
- if (settings.easing === 'easeOutQuart') pattern = 1 - (--time) * time * time * time; // decelerating to zero velocity
- if (settings.easing === 'easeInOutQuart') pattern = time < 0.5 ? 8 * time * time * time * time : 1 - 8 * (--time) * time * time * time; // acceleration until halfway, then deceleration
- if (settings.easing === 'easeInQuint') pattern = time * time * time * time * time; // accelerating from zero velocity
- if (settings.easing === 'easeOutQuint') pattern = 1 + (--time) * time * time * time * time; // decelerating to zero velocity
- if (settings.easing === 'easeInOutQuint') pattern = time < 0.5 ? 16 * time * time * time * time * time : 1 + 16 * (--time) * time * time * time * time; // acceleration until halfway, then deceleration
-
- // Custom Easing Patterns
- if (!!settings.customEasing) pattern = settings.customEasing(time);
-
- return pattern || time; // no easing, no acceleration
- };
-
- /**
- * Determine the document's height
- * @returns {Number}
- */
- var getDocumentHeight = function () {
- return Math.max(
- document.body.scrollHeight, document.documentElement.scrollHeight,
- document.body.offsetHeight, document.documentElement.offsetHeight,
- document.body.clientHeight, document.documentElement.clientHeight
- );
- };
-
- /**
- * Calculate how far to scroll
- * Clip support added by robjtede - https://github.com/cferdinandi/smooth-scroll/issues/405
- * @param {Element} anchor The anchor element to scroll to
- * @param {Number} headerHeight Height of a fixed header, if any
- * @param {Number} offset Number of pixels by which to offset scroll
- * @param {Boolean} clip If true, adjust scroll distance to prevent abrupt stops near the bottom of the page
- * @returns {Number}
- */
- var getEndLocation = function (anchor, headerHeight, offset, clip) {
- var location = 0;
- if (anchor.offsetParent) {
- do {
- location += anchor.offsetTop;
- anchor = anchor.offsetParent;
- } while (anchor);
- }
- location = Math.max(location - headerHeight - offset, 0);
- if (clip) {
- location = Math.min(location, getDocumentHeight() - window.innerHeight);
- }
- return location;
- };
-
- /**
- * Get the height of the fixed header
- * @param {Node} header The header
- * @return {Number} The height of the header
- */
- var getHeaderHeight = function (header) {
- return !header ? 0 : (getHeight(header) + header.offsetTop);
- };
-
- /**
- * Update the URL
- * @param {Node} anchor The anchor that was scrolled to
- * @param {Boolean} isNum If true, anchor is a number
- * @param {Object} options Settings for Smooth Scroll
- */
- var updateURL = function (anchor, isNum, options) {
-
- // Bail if the anchor is a number
- if (isNum) return;
-
- // Verify that pushState is supported and the updateURL option is enabled
- if (!history.pushState || !options.updateURL) return;
-
- // Update URL
- history.pushState(
- {
- smoothScroll: JSON.stringify(options),
- anchor: anchor.id
- },
- document.title,
- anchor === document.documentElement ? '#top' : '#' + anchor.id
- );
-
- };
-
- /**
- * Bring the anchored element into focus
- * @param {Node} anchor The anchor element
- * @param {Number} endLocation The end location to scroll to
- * @param {Boolean} isNum If true, scroll is to a position rather than an element
- */
- var adjustFocus = function (anchor, endLocation, isNum) {
-
- // Is scrolling to top of page, blur
- if (anchor === 0) {
- document.body.focus();
- }
-
- // Don't run if scrolling to a number on the page
- if (isNum) return;
-
- // Otherwise, bring anchor element into focus
- anchor.focus();
- if (document.activeElement !== anchor) {
- anchor.setAttribute('tabindex', '-1');
- anchor.focus();
- anchor.style.outline = 'none';
- }
- window.scrollTo(0 , endLocation);
-
- };
-
- /**
- * Emit a custom event
- * @param {String} type The event type
- * @param {Object} options The settings object
- * @param {Node} anchor The anchor element
- * @param {Node} toggle The toggle element
- */
- var emitEvent = function (type, options, anchor, toggle) {
- if (!options.emitEvents || typeof window.CustomEvent !== 'function') return;
- var event = new CustomEvent(type, {
- bubbles: true,
- detail: {
- anchor: anchor,
- toggle: toggle
- }
- });
- document.dispatchEvent(event);
- };
-
-
- //
- // SmoothScroll Constructor
- //
-
- var SmoothScroll = function (selector, options) {
-
- //
- // Variables
- //
-
- var smoothScroll = {}; // Object for public APIs
- var settings, anchor, toggle, fixedHeader, headerHeight, eventTimeout, animationInterval;
-
-
- //
- // Methods
- //
-
- /**
- * Cancel a scroll-in-progress
- */
- smoothScroll.cancelScroll = function (noEvent) {
- cancelAnimationFrame(animationInterval);
- animationInterval = null;
- if (noEvent) return;
- emitEvent('scrollCancel', settings);
- };
-
- /**
- * Start/stop the scrolling animation
- * @param {Node|Number} anchor The element or position to scroll to
- * @param {Element} toggle The element that toggled the scroll event
- * @param {Object} options
- */
- smoothScroll.animateScroll = function (anchor, toggle, options) {
-
- // Local settings
- var animateSettings = extend(settings || defaults, options || {}); // Merge user options with defaults
-
- // Selectors and variables
- var isNum = Object.prototype.toString.call(anchor) === '[object Number]' ? true : false;
- var anchorElem = isNum || !anchor.tagName ? null : anchor;
- if (!isNum && !anchorElem) return;
- var startLocation = window.pageYOffset; // Current location on the page
- if (animateSettings.header && !fixedHeader) {
- // Get the fixed header if not already set
- fixedHeader = document.querySelector(animateSettings.header);
- }
- if (!headerHeight) {
- // Get the height of a fixed header if one exists and not already set
- headerHeight = getHeaderHeight(fixedHeader);
- }
- var endLocation = isNum ? anchor : getEndLocation(anchorElem, headerHeight, parseInt((typeof animateSettings.offset === 'function' ? animateSettings.offset(anchor, toggle) : animateSettings.offset), 10), animateSettings.clip); // Location to scroll to
- var distance = endLocation - startLocation; // distance to travel
- var documentHeight = getDocumentHeight();
- var timeLapsed = 0;
- var start, percentage, position;
-
- /**
- * Stop the scroll animation when it reaches its target (or the bottom/top of page)
- * @param {Number} position Current position on the page
- * @param {Number} endLocation Scroll to location
- * @param {Number} animationInterval How much to scroll on this loop
- */
- var stopAnimateScroll = function (position, endLocation) {
-
- // Get the current location
- var currentLocation = window.pageYOffset;
-
- // Check if the end location has been reached yet (or we've hit the end of the document)
- if (position == endLocation || currentLocation == endLocation || ((startLocation < endLocation && window.innerHeight + currentLocation) >= documentHeight)) {
-
- // Clear the animation timer
- smoothScroll.cancelScroll(true);
-
- // Bring the anchored element into focus
- adjustFocus(anchor, endLocation, isNum);
-
- // Emit a custom event
- emitEvent('scrollStop', animateSettings, anchor, toggle);
-
- // Reset start
- start = null;
- animationInterval = null;
-
- return true;
-
- }
- };
-
- /**
- * Loop scrolling animation
- */
- var loopAnimateScroll = function (timestamp) {
- if (!start) { start = timestamp; }
- timeLapsed += timestamp - start;
- percentage = (timeLapsed / parseInt(animateSettings.speed, 10));
- percentage = (percentage > 1) ? 1 : percentage;
- position = startLocation + (distance * easingPattern(animateSettings, percentage));
- window.scrollTo(0, Math.floor(position));
- if (!stopAnimateScroll(position, endLocation)) {
- animationInterval = window.requestAnimationFrame(loopAnimateScroll);
- start = timestamp;
- }
- };
-
- /**
- * Reset position to fix weird iOS bug
- * @link https://github.com/cferdinandi/smooth-scroll/issues/45
- */
- if (window.pageYOffset === 0) {
- window.scrollTo(0, 0);
- }
-
- // Update the URL
- updateURL(anchor, isNum, animateSettings);
-
- // Emit a custom event
- emitEvent('scrollStart', animateSettings, anchor, toggle);
-
- // Start scrolling animation
- smoothScroll.cancelScroll(true);
- window.requestAnimationFrame(loopAnimateScroll);
-
- };
-
- /**
- * If smooth scroll element clicked, animate scroll
- */
- var clickHandler = function (event) {
-
- // Don't run if the user prefers reduced motion
- if (reduceMotion(settings)) return;
-
- // Don't run if right-click or command/control + click
- if (event.button !== 0 || event.metaKey || event.ctrlKey) return;
-
- // Check if event.target has closest() method
- // By @totegi - https://github.com/cferdinandi/smooth-scroll/pull/401/
- if(!('closest' in event.target))return;
-
- // Check if a smooth scroll link was clicked
- toggle = event.target.closest(selector);
- if (!toggle || toggle.tagName.toLowerCase() !== 'a' || event.target.closest(settings.ignore)) return;
-
- // Only run if link is an anchor and points to the current page
- if (toggle.hostname !== window.location.hostname || toggle.pathname !== window.location.pathname || !/#/.test(toggle.href)) return;
-
- // Get an escaped version of the hash
- var hash = escapeCharacters(decode(toggle.hash));
-
- // Get the anchored element
- var anchor = settings.topOnEmptyHash && hash === '#' ? document.documentElement : document.querySelector(hash);
- anchor = !anchor && hash === '#top' ? document.documentElement : anchor;
-
- // If anchored element exists, scroll to it
- if (!anchor) return;
- event.preventDefault();
- smoothScroll.animateScroll(anchor, toggle);
-
- };
-
- /**
- * Animate scroll on popstate events
- */
- var popstateHandler = function (event) {
- // Stop if history.state doesn't exist (ex. if clicking on a broken anchor link).
- // fixes `Cannot read property 'smoothScroll' of null` error getting thrown.
- if (history.state === null) return;
-
- // Only run if state is a popstate record for this instantiation
- if (!history.state.smoothScroll || history.state.smoothScroll !== JSON.stringify(settings)) return;
-
- // Only run if state includes an anchor
- if (!history.state.anchor) return;
-
- // Get the anchor
- var anchor = document.querySelector(escapeCharacters(decode(history.state.anchor)));
- if (!anchor) return;
-
- // Animate scroll to anchor link
- smoothScroll.animateScroll(anchor, null, {updateURL: false});
-
- };
-
- /**
- * On window scroll and resize, only run events at a rate of 15fps for better performance
- */
- var resizeThrottler = function (event) {
- if (!eventTimeout) {
- eventTimeout = setTimeout((function() {
- eventTimeout = null; // Reset timeout
- headerHeight = getHeaderHeight(fixedHeader); // Get the height of a fixed header if one exists
- }), 66);
- }
- };
-
- /**
- * Destroy the current initialization.
- */
- smoothScroll.destroy = function () {
-
- // If plugin isn't already initialized, stop
- if (!settings) return;
-
- // Remove event listeners
- document.removeEventListener('click', clickHandler, false);
- window.removeEventListener('resize', resizeThrottler, false);
- window.removeEventListener('popstate', popstateHandler, false);
-
- // Cancel any scrolls-in-progress
- smoothScroll.cancelScroll();
-
- // Reset variables
- settings = null;
- anchor = null;
- toggle = null;
- fixedHeader = null;
- headerHeight = null;
- eventTimeout = null;
- animationInterval = null;
-
- };
-
- /**
- * Initialize Smooth Scroll
- * @param {Object} options User settings
- */
- smoothScroll.init = function (options) {
-
- // feature test
- if (!supports()) throw 'Smooth Scroll: This browser does not support the required JavaScript methods and browser APIs.';
-
- // Destroy any existing initializations
- smoothScroll.destroy();
-
- // Selectors and variables
- settings = extend(defaults, options || {}); // Merge user options with defaults
- fixedHeader = settings.header ? document.querySelector(settings.header) : null; // Get the fixed header
- headerHeight = getHeaderHeight(fixedHeader);
-
- // When a toggle is clicked, run the click handler
- document.addEventListener('click', clickHandler, false);
-
- // If window is resized and there's a fixed header, recalculate its size
- if (fixedHeader) {
- window.addEventListener('resize', resizeThrottler, false);
- }
-
- // If updateURL and popState are enabled, listen for pop events
- if (settings.updateURL && settings.popstate) {
- window.addEventListener('popstate', popstateHandler, false);
- }
-
- };
-
-
- //
- // Initialize plugin
- //
-
- smoothScroll.init(options);
-
-
- //
- // Public APIs
- //
-
- return smoothScroll;
-
- };
-
- return SmoothScroll;
-
-}));
diff --git a/docs/dist/smooth-scroll.polyfills.min.js b/docs/dist/smooth-scroll.polyfills.min.js
deleted file mode 100644
index 4ba1334..0000000
--- a/docs/dist/smooth-scroll.polyfills.min.js
+++ /dev/null
@@ -1,2 +0,0 @@
-/*! smooth-scroll v14.2.1 | (c) 2018 Chris Ferdinandi | MIT License | http://github.com/cferdinandi/smooth-scroll */
-window.Element&&!Element.prototype.closest&&(Element.prototype.closest=function(e){var t,n=(this.document||this.ownerDocument).querySelectorAll(e),o=this;do{for(t=n.length;--t>=0&&n.item(t)!==o;);}while(t<0&&(o=o.parentElement));return o}),(function(){function e(e,t){t=t||{bubbles:!1,cancelable:!1,detail:void 0};var n=document.createEvent("CustomEvent");return n.initCustomEvent(e,t.bubbles,t.cancelable,t.detail),n}if("function"==typeof window.CustomEvent)return!1;e.prototype=window.Event.prototype,window.CustomEvent=e})(),(function(){for(var e=0,t=["ms","moz","webkit","o"],n=0;n=1&&t<=31||127==t||0===i&&t>=48&&t<=57||1===i&&t>=48&&t<=57&&45===a?r+="\\"+t.toString(16)+" ":r+=t>=128||45===t||95===t||t>=48&&t<=57||t>=65&&t<=90||t>=97&&t<=122?n.charAt(i):"\\"+n.charAt(i)}var u;try{u=decodeURIComponent("#"+r)}catch(e){u="#"+r}return u},c=function(e,t){var n;return"easeInQuad"===e.easing&&(n=t*t),"easeOutQuad"===e.easing&&(n=t*(2-t)),"easeInOutQuad"===e.easing&&(n=t<.5?2*t*t:(4-2*t)*t-1),"easeInCubic"===e.easing&&(n=t*t*t),"easeOutCubic"===e.easing&&(n=--t*t*t+1),"easeInOutCubic"===e.easing&&(n=t<.5?4*t*t*t:(t-1)*(2*t-2)*(2*t-2)+1),"easeInQuart"===e.easing&&(n=t*t*t*t),"easeOutQuart"===e.easing&&(n=1- --t*t*t*t),"easeInOutQuart"===e.easing&&(n=t<.5?8*t*t*t*t:1-8*--t*t*t*t),"easeInQuint"===e.easing&&(n=t*t*t*t*t),"easeOutQuint"===e.easing&&(n=1+--t*t*t*t*t),"easeInOutQuint"===e.easing&&(n=t<.5?16*t*t*t*t*t:1+16*--t*t*t*t*t),e.customEasing&&(n=e.customEasing(t)),n||t},s=function(){return Math.max(document.body.scrollHeight,document.documentElement.scrollHeight,document.body.offsetHeight,document.documentElement.offsetHeight,document.body.clientHeight,document.documentElement.clientHeight)},l=function(t,n,o,i){var r=0;if(t.offsetParent)do{r+=t.offsetTop,t=t.offsetParent}while(t);return r=Math.max(r-n-o,0),i&&(r=Math.min(r,s()-e.innerHeight)),r},m=function(e){return e?r(e)+e.offsetTop:0},d=function(e,t,n){t||history.pushState&&n.updateURL&&history.pushState({smoothScroll:JSON.stringify(n),anchor:e.id},document.title,e===document.documentElement?"#top":"#"+e.id)},f=function(t,n,o){0===t&&document.body.focus(),o||(t.focus(),document.activeElement!==t&&(t.setAttribute("tabindex","-1"),t.focus(),t.style.outline="none"),e.scrollTo(0,n))},h=function(t,n,o,i){if(n.emitEvents&&"function"==typeof e.CustomEvent){var r=new CustomEvent(t,{bubbles:!0,detail:{anchor:o,toggle:i}});document.dispatchEvent(r)}};return function(r,p){var g,v,w,y,E,b,S,A={};A.cancelScroll=function(e){cancelAnimationFrame(S),S=null,e||h("scrollCancel",g)},A.animateScroll=function(n,i,r){var a=o(g||t,r||{}),u="[object Number]"===Object.prototype.toString.call(n),p=u||!n.tagName?null:n;if(u||p){var v=e.pageYOffset;a.header&&!y&&(y=document.querySelector(a.header)),E||(E=m(y));var w,b,C,O=u?n:l(p,E,parseInt("function"==typeof a.offset?a.offset(n,i):a.offset,10),a.clip),I=O-v,q=s(),F=0,L=function(t,o){var r=e.pageYOffset;if(t==o||r==o||(v=q)return A.cancelScroll(!0),f(n,o,u),h("scrollStop",a,n,i),w=null,S=null,!0},H=function(t){w||(w=t),F+=t-w,b=F/parseInt(a.speed,10),b=b>1?1:b,C=v+I*c(a,b),e.scrollTo(0,Math.floor(C)),L(C,O)||(S=e.requestAnimationFrame(H),w=t)};0===e.pageYOffset&&e.scrollTo(0,0),d(n,u,a),h("scrollStart",a,n,i),A.cancelScroll(!0),e.requestAnimationFrame(H)}};var C=function(t){if(!i()&&0===t.button&&!t.metaKey&&!t.ctrlKey&&"closest"in t.target&&(w=t.target.closest(r))&&"a"===w.tagName.toLowerCase()&&!t.target.closest(g.ignore)&&w.hostname===e.location.hostname&&w.pathname===e.location.pathname&&/#/.test(w.href)){var n=u(a(w.hash)),o=g.topOnEmptyHash&&"#"===n?document.documentElement:document.querySelector(n);o=o||"#top"!==n?o:document.documentElement,o&&(t.preventDefault(),A.animateScroll(o,w))}},O=function(e){if(null!==history.state&&history.state.smoothScroll&&history.state.smoothScroll===JSON.stringify(g)&&history.state.anchor){var t=document.querySelector(u(a(history.state.anchor)));t&&A.animateScroll(t,null,{updateURL:!1})}},I=function(e){b||(b=setTimeout((function(){b=null,E=m(y)}),66))};return A.destroy=function(){g&&(document.removeEventListener("click",C,!1),e.removeEventListener("resize",I,!1),e.removeEventListener("popstate",O,!1),A.cancelScroll(),g=null,v=null,w=null,y=null,E=null,b=null,S=null)},A.init=function(i){if(!n())throw"Smooth Scroll: This browser does not support the required JavaScript methods and browser APIs.";A.destroy(),g=o(t,i||{}),y=g.header?document.querySelector(g.header):null,E=m(y),document.addEventListener("click",C,!1),y&&e.addEventListener("resize",I,!1),g.updateURL&&g.popstate&&e.addEventListener("popstate",O,!1)},A.init(p),A}}));
\ No newline at end of file
diff --git a/docs/index.html b/docs/index.html
deleted file mode 100755
index 8d01595..0000000
--- a/docs/index.html
+++ /dev/null
@@ -1,130 +0,0 @@
-
-
-
-
-
- Smooth Scroll
-
-
-
-
-
-
-
-
-
-
-
-
-
-