Skip to content

Commit 9e3728c

Browse files
committed
Merge pull request cferdinandi#226 from cferdinandi/development
v9.0.0
2 parents 930d5ca + 7fbdcae commit 9e3728c

File tree

11 files changed

+153
-251
lines changed

11 files changed

+153
-251
lines changed

README.md

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,8 @@ smoothScroll.init({
8383
speed: 500, // Integer. How fast to complete the scroll in milliseconds
8484
easing: 'easeInOutCubic', // Easing pattern to use
8585
offset: 0, // Integer. How far to offset the scrolling anchor location in pixels
86-
scrollOnLoad: true, // Boolean. If true, animate to anchor on page load if URL has a hash
87-
callback: function ( toggle, anchor ) {} // Function to run after scrolling
86+
updateURL: true, // Boolean. If true, update the URL hash on scroll
87+
callback: function ( anchor, toggle ) {} // Function to run after scrolling
8888
});
8989
```
9090

@@ -203,9 +203,29 @@ Add a `[data-scroll-header]` data attribute to fixed headers. Smooth Scroll will
203203
</nav>
204204
```
205205

206-
### Animating links to other pages [NEW in v10]
206+
### Animating links to other pages
207207

208-
Smooth Scroll now supports animating anchor links to other pages. Simply make sure that `scrollOnLoad` is set to `true` (the default) and point your link to the anchor on the page as normal.
208+
This is an often requested feature, but Smooth Scroll does not include an option to animate scrolling to links on other pages.
209+
210+
You can attempt to implement it using the API, but it's very difficult to prevent the automatic browser jump when the page loads, and anything I've done to work around it results in weird, janky issues, so I've decided to leave this out of the core. Here's a potential workaround...
211+
212+
1. Do *not* add the `data-scroll` attribute to links to other pages. Treat them like normal links, and include your anchor link hash as normal.
213+
214+
```html
215+
<a href="some-page.html#example">
216+
```
217+
2. Add the following script to the footer of your page, after the `smoothScroll.init()` function.
218+
219+
```html
220+
<script>
221+
if ( window.location.hash ) {
222+
var hash = smoothScroll.escapeCharacters( window.location.hash ); // Escape the hash
223+
var toggle = document.querySelector( 'a[href*="' + hash + '"]' ); // Get the toggle (if one exists)
224+
var options = {}; // Any custom options you want to use would go here
225+
smoothScroll.animateScroll( hash, toggle, options );
226+
}
227+
</script>
228+
```
209229

210230

211231
## Browser Compatibility

dist/js/smooth-scroll.js

Lines changed: 40 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*!
2-
* smooth-scroll v8.1.0: Animate scrolling to anchor links
2+
* smooth-scroll v9.0.0: Animate scrolling to anchor links
33
* (c) 2016 Chris Ferdinandi
44
* MIT License
55
* http://github.com/cferdinandi/smooth-scroll
@@ -22,8 +22,8 @@
2222
//
2323

2424
var smoothScroll = {}; // Object for public APIs
25-
var supports = 'querySelector' in document && 'addEventListener' in root && 'onhashchange' in root; // Feature test
26-
var settings, eventTimeout, fixedHeader, headerHeight, anchor;
25+
var supports = 'querySelector' in document && 'addEventListener' in root; // Feature test
26+
var settings, eventTimeout, fixedHeader, headerHeight;
2727

2828
// Default settings
2929
var defaults = {
@@ -32,7 +32,7 @@
3232
speed: 500,
3333
easing: 'easeInOutCubic',
3434
offset: 0,
35-
scrollOnLoad: true,
35+
updateURL: true,
3636
callback: function () {}
3737
};
3838

@@ -317,19 +317,26 @@
317317
};
318318

319319
/**
320-
* Get the height of a fixed header in pixels
321-
* @param {Node} header The header
322-
* @return {Integer} The header height in pixels
320+
* Update the URL
321+
* @private
322+
* @param {Element} anchor The element to scroll to
323+
* @param {Boolean} url Whether or not to update the URL history
323324
*/
325+
var updateUrl = function ( anchor, url ) {
326+
if ( root.history.pushState && (url || url === 'true') && root.location.protocol !== 'file:' ) {
327+
root.history.pushState( null, null, [root.location.protocol, '//', root.location.host, root.location.pathname, root.location.search, anchor].join('') );
328+
}
329+
};
330+
324331
var getHeaderHeight = function ( header ) {
325332
return header === null ? 0 : ( getHeight( header ) + header.offsetTop );
326333
};
327334

328335
/**
329336
* Start/stop the scrolling animation
330337
* @public
331-
* @param {Element} toggle The element that toggled the scroll event
332338
* @param {Element} anchor The element to scroll to
339+
* @param {Element} toggle The element that toggled the scroll event
333340
* @param {Object} options
334341
*/
335342
smoothScroll.animateScroll = function ( anchor, toggle, options ) {
@@ -340,7 +347,8 @@
340347

341348
// Selectors and variables
342349
var isNum = Object.prototype.toString.call( anchor ) === '[object Number]' ? true : false;
343-
var anchorElem = isNum ? null : root.document.querySelector(anchor);
350+
var anchorElem = isNum ? null : anchor === '#' ? root.document.documentElement : root.document.querySelector(anchor);
351+
// var anchorElem = isNum ? null : ( anchor === '#' ? root.document.documentElement : root.document.querySelector(anchor) );
344352
if ( !isNum && !anchorElem ) return;
345353
var startLocation = root.pageYOffset; // Current location on the page
346354
if ( !fixedHeader ) { fixedHeader = root.document.querySelector( settings.selectorHeader ); } // Get the fixed header if not already set
@@ -352,6 +360,11 @@
352360
var timeLapsed = 0;
353361
var percentage, position;
354362

363+
// Update URL
364+
if ( !isNum ) {
365+
updateUrl(anchor, settings.updateURL);
366+
}
367+
355368
/**
356369
* Stop the scroll animation when it reaches its target (or the bottom/top of page)
357370
* @private
@@ -363,7 +376,7 @@
363376
var currentLocation = root.pageYOffset;
364377
if ( position == endLocation || currentLocation == endLocation || ( (root.innerHeight + currentLocation) >= documentHeight ) ) {
365378
clearInterval(animationInterval);
366-
if ( anchorElem ) {
379+
if ( !isNum ) {
367380
anchorElem.focus();
368381
}
369382
settings.callback( anchor, toggle ); // Run callbacks after animation complete
@@ -405,65 +418,25 @@
405418
};
406419

407420
/**
408-
* Handle has change event
421+
* If smooth scroll element clicked, animate scroll
409422
* @private
410423
*/
411-
var hashChangeHandler = function () {
412-
413-
// Get hash from URL
414-
var hash = root.location.hash;
415-
416-
// If anchor target is cached, reset it's ID
417-
if ( anchor ) {
418-
anchor.id = anchor.getAttribute( 'data-scroll-id' );
419-
anchor = null;
420-
}
421-
422-
// If there's a URL hash, animate scrolling to the matching ID
423-
if ( !hash ) return;
424-
hash = smoothScroll.escapeCharacters( hash ); // Escape special characters and leading numbers
425-
var toggle = document.querySelector( settings.select + '[href*="' + hash + '"]');
426-
smoothScroll.animateScroll( hash, toggle, settings); // Animate scroll
427-
428-
};
429-
430-
/**
431-
* Handle toggle click events
432-
* @private
433-
* @param {Event} event
434-
*/
435-
var clickHandler = function (event) {
436-
437-
// Check if event target is a smooth scroll link and has a hash
424+
var eventHandler = function (event) {
438425
var toggle = getClosest( event.target, settings.selector );
439-
if ( !toggle || !toggle.hash ) return;
440-
441-
// Escape the hash characters
442-
var hash = smoothScroll.escapeCharacters( toggle.hash ); // Escape special characters and leading numbers
443-
444-
// If hash is already active, animate immediately (no hash change will fire)
445-
if ( hash === ( root.location.hash || '#top' ) ) {
446-
smoothScroll.animateScroll( hash, toggle, settings);
447-
return;
448-
}
449-
450-
// Get the anchor target
451-
anchor = document.querySelector( hash );
452-
453-
// If anchor exists, save the ID as a data attribute and remove it (prevents scroll jump)
454-
if ( anchor ) {
455-
anchor.setAttribute( 'data-scroll-id', anchor.id );
456-
anchor.id = '';
426+
if ( toggle && toggle.tagName.toLowerCase() === 'a' ) {
427+
event.preventDefault(); // Prevent default click event
428+
var hash = smoothScroll.escapeCharacters( toggle.hash ); // Escape hash characters
429+
smoothScroll.animateScroll( hash, toggle, settings); // Animate scroll
457430
}
458-
459431
};
460432

461433
/**
462-
* On window resize, only run events at a rate of 15fps for better performance
434+
* On window scroll and resize, only run events at a rate of 15fps for better performance
463435
* @private
464-
* @param {Event} event
436+
* @param {Function} eventTimeout Timeout function
437+
* @param {Object} settings
465438
*/
466-
var resizeThrottler = function (event) {
439+
var eventThrottler = function (event) {
467440
if ( !eventTimeout ) {
468441
eventTimeout = setTimeout(function() {
469442
eventTimeout = null; // Reset timeout
@@ -482,16 +455,14 @@
482455
if ( !settings ) return;
483456

484457
// Remove event listeners
485-
document.removeEventListener( 'click', clickHandler, false );
486-
root.removeEventListener( 'hashchange', hashChangeHandler, false );
487-
root.removeEventListener( 'resize', resizeThrottler, false );
458+
root.document.removeEventListener( 'click', eventHandler, false );
459+
root.removeEventListener( 'resize', eventThrottler, false );
488460

489-
// Reset variables
461+
// Reset varaibles
490462
settings = null;
491463
eventTimeout = null;
492464
fixedHeader = null;
493465
headerHeight = null;
494-
anchor = null;
495466
};
496467

497468
/**
@@ -512,18 +483,9 @@
512483
fixedHeader = root.document.querySelector( settings.selectorHeader ); // Get the fixed header
513484
headerHeight = getHeaderHeight( fixedHeader );
514485

515-
// Event listeners
516-
document.addEventListener('click', clickHandler, false);
517-
root.addEventListener('hashchange', hashChangeHandler, false);
518-
if ( fixedHeader ) { root.addEventListener( 'resize', resizeThrottler, false ); }
519-
520-
// Scroll on load
521-
if ( settings.scrollOnLoad ) {
522-
setTimeout(function() {
523-
window.scrollTo(0, 0);
524-
}, 1);
525-
hashChangeHandler();
526-
}
486+
// When a toggle is clicked, run the click handler
487+
root.document.addEventListener('click', eventHandler, false );
488+
if ( fixedHeader ) { root.addEventListener( 'resize', eventThrottler, false ); }
527489

528490
};
529491

@@ -534,4 +496,4 @@
534496

535497
return smoothScroll;
536498

537-
});
499+
});

dist/js/smooth-scroll.min.js

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)