Skip to content

Commit 5de25a0

Browse files
author
Chris Ferdinandi
committed
Added AMD support
1 parent 58252cf commit 5de25a0

File tree

2 files changed

+112
-55
lines changed

2 files changed

+112
-55
lines changed

README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@ Smooth Scroll is built with modern JavaScript APIs, and uses progressive enhance
173173
* IE10 rounding error fixed by [Luke Siedle](https://github.com/luke-siedle).
174174
* Enhanced callback functions by [Constant Meiring](https://github.com/constantm).
175175
* Scroll-to-top bug for links at the bottom of the page by [Jonas Havers](https://github.com/JonasHavers).
176+
* AMD support and numerous code improvements by [Todd Motto](https://github.com/toddmotto).
176177

177178

178179

@@ -188,6 +189,15 @@ Smooth Scroll is licensed under the [MIT License](http://gomakethings.com/mit/).
188189

189190

190191
## Changelog
192+
* v4.7.0 - June 7, 2014
193+
* Added AMD support.
194+
* Moved public APIs to `exports` variable.
195+
* Improved feature test.
196+
* Replaced `Array.prototype.forEach` hack with proper `forEach` function.
197+
* Added a more well supported `trim` function.
198+
* General code optimizations for better minification and performance.
199+
* Updated to JSDoc documentation (sort of).
200+
* Updated to three number versioning system.
191201
* v4.6 - March 21, 2014
192202
* [Fixed scroll-to-top bug for links at the bottom of the page](https://github.com/cferdinandi/smooth-scroll/issues/49).
193203
* v4.5 - March 20, 2014

smooth-scroll.js

Lines changed: 102 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/* =============================================================
22
3-
Smooth Scroll v4.5
3+
Smooth Scroll v4.7.0
44
Animate scrolling to anchor links, by Chris Ferdinandi.
55
http://gomakethings.com
66
@@ -10,32 +10,30 @@
1010
Free to use under the MIT License.
1111
http://gomakethings.com/mit/
1212
13+
@todo update readme
14+
1315
* ============================================================= */
1416

15-
(function (root, factory) {
16-
if (typeof define === 'function' && define.amd) {
17+
(function (root, factory) {
18+
if ( typeof define === 'function' && define.amd ) {
1719
define(factory);
18-
} else if (typeof exports === 'object') {
20+
} else if ( typeof exports === 'object' ) {
1921
module.exports = factory;
2022
} else {
2123
root.smoothScroll = factory(root);
2224
}
23-
})(this, function (root) {
25+
})(this, function (root) {
2426

2527
'use strict';
2628

27-
var exports = {};
28-
29-
var trim = function (str) {
30-
return str.replace(/^\s+|\s+$/g, '');
31-
};
29+
/*
30+
* Variables
31+
*/
3232

33-
var supports = function () {
34-
return 'querySelector' in document && 'addEventListener' in root && Array.prototype.forEach;
35-
};
33+
var exports = {}; // Object for public APIs
34+
var supports = { html5: !!document.querySelector && !!root.addEventListener }; // Feature test
3635

3736
// Default settings
38-
// Private {object} variable
3937
var defaults = {
4038
speed: 500,
4139
easing: 'easeInOutCubic',
@@ -45,21 +43,49 @@
4543
callbackAfter: function () {}
4644
};
4745

48-
// Merge default settings with user options
49-
// Private method
50-
// Returns an {object}
51-
var extend = function ( target, source ) {
52-
for (var key in source) {
53-
if (Object.prototype.hasOwnProperty.call(source, key)) {
54-
target[key] = source[key];
46+
47+
/*
48+
* Methods
49+
*/
50+
51+
// Merge defaults with user options
52+
// @private
53+
// @param {Object} defaults Default settings
54+
// @param {Object} options User options
55+
// @returns {Object} Merged values of defaults and options
56+
var extend = function ( defaults, options ) {
57+
for ( var key in options ) {
58+
if (Object.prototype.hasOwnProperty.call(options, key)) {
59+
defaults[key] = options[key];
60+
}
61+
}
62+
return defaults;
63+
};
64+
65+
// A simple forEach() implementation for Arrays, Objects and NodeLists
66+
// @private
67+
// @param {Array|Object|NodeList} collection Collection of items to iterate
68+
// @param {Function} callback Callback function for each iteration
69+
// @param {Array|Object|NodeList} scope Object/NodeList/Array that forEach is iterating over (aka `this`)
70+
var forEach = function (collection, callback, scope) {
71+
if (Object.prototype.toString.call(collection) === '[object Object]') {
72+
for (var prop in collection) {
73+
if (Object.prototype.hasOwnProperty.call(collection, prop)) {
74+
callback.call(scope, collection[prop], prop, collection);
75+
}
76+
}
77+
} else {
78+
for (var i = 0, len = collection.length; i < len; i++) {
79+
callback.call(scope, collection[i], i, collection);
5580
}
5681
}
57-
return target;
5882
};
5983

6084
// Calculate the easing pattern
61-
// Private method
62-
// Returns a decimal number
85+
// @private
86+
// @param {String} type Easing pattern
87+
// @param {Number} time Time animation should take to complete
88+
// @returns {Number}
6389
var easingPattern = function ( type, time ) {
6490
var pattern;
6591
if ( type === 'easeInQuad' ) pattern = time * time; // accelerating from zero velocity
@@ -78,8 +104,11 @@
78104
};
79105

80106
// Calculate how far to scroll
81-
// Private method
82-
// Returns an integer
107+
// @private
108+
// @param {Element} anchor The anchor element to scroll to
109+
// @param {Number} headerHeight Height of a fixed header, if any
110+
// @param {Number} offset Number of pixels by which to offset scroll
111+
// @returns {Number}
83112
var getEndLocation = function ( anchor, headerHeight, offset ) {
84113
var location = 0;
85114
if (anchor.offsetParent) {
@@ -93,8 +122,8 @@
93122
};
94123

95124
// Determine the document's height
96-
// Private method
97-
// Returns an integer
125+
// @private
126+
// @returns {Number}
98127
var getDocumentHeight = function () {
99128
return Math.max(
100129
document.body.scrollHeight, document.documentElement.scrollHeight,
@@ -103,9 +132,18 @@
103132
);
104133
};
105134

135+
// Remove whitespace from a string
136+
// @private
137+
// @param {String} string
138+
// @returns {String}
139+
var trim = function ( string ) {
140+
return string.replace(/^\s+|\s+$/g, '');
141+
};
142+
106143
// Convert data-options attribute into an object of key/value pairs
107-
// Private method
108-
// Returns an {object}
144+
// @private
145+
// @param {String} options Link-specific options as a data attribute string
146+
// @returns {Object}
109147
var getDataOptions = function ( options ) {
110148
var settings = {};
111149
// Create a key/value pair for each setting
@@ -123,8 +161,9 @@
123161
};
124162

125163
// Update the URL
126-
// Private method
127-
// Runs functions
164+
// @private
165+
// @param {Element} anchor The element to scroll to
166+
// @param {Boolean} url Whether or not to update the URL history
128167
var updateUrl = function ( anchor, url ) {
129168
if ( history.pushState && (url || url === 'true') ) {
130169
history.pushState( {
@@ -134,17 +173,20 @@
134173
};
135174

136175
// Start/stop the scrolling animation
137-
// Public method
138-
// Runs functions
139-
exports.animateScroll = function ( toggle, anchor, options, event ) {
176+
// @public
177+
// @param {Element} toggle The element that toggled the scroll event
178+
// @param {Element} anchor The element to scroll to
179+
// @param {Object} settings
180+
// @param {Event} event
181+
exports.animateScroll = function ( toggle, anchor, settings, event ) {
140182

141183
// Options and overrides
142-
options = extend( defaults, options || {} ); // Merge user options with defaults
184+
settings = extend( defaults, settings || {} ); // Merge user options with defaults
143185
var overrides = getDataOptions( toggle ? toggle.getAttribute('data-options') : null );
144-
var speed = parseInt(overrides.speed || options.speed, 10);
145-
var easing = overrides.easing || options.easing;
146-
var offset = parseInt(overrides.offset || options.offset, 10);
147-
var updateURL = overrides.updateURL || options.updateURL;
186+
var speed = parseInt(overrides.speed || settings.speed, 10);
187+
var easing = overrides.easing || settings.easing;
188+
var offset = parseInt(overrides.offset || settings.offset, 10);
189+
var updateURL = overrides.updateURL || settings.updateURL;
148190

149191
// Selectors and variables
150192
var fixedHeader = document.querySelector('[data-scroll-header]'); // Get the fixed header
@@ -166,19 +208,20 @@
166208
updateUrl(anchor, updateURL);
167209

168210
// Stop the scroll animation when it reaches its target (or the bottom/top of page)
169-
// Private method
170-
// Runs functions
211+
// @private
212+
// @param {Number} position Current position on the page
213+
// @param {Number} endLocation Scroll to location
214+
// @param {Number} animationInterval How much to scroll on this loop
171215
var stopAnimateScroll = function (position, endLocation, animationInterval) {
172216
var currentLocation = root.pageYOffset;
173217
if ( position == endLocation || currentLocation == endLocation || ( (root.innerHeight + currentLocation) >= documentHeight ) ) {
174218
clearInterval(animationInterval);
175-
options.callbackAfter( toggle, anchor ); // Run callbacks after animation complete
219+
settings.callbackAfter( toggle, anchor ); // Run callbacks after animation complete
176220
}
177221
};
178222

179223
// Loop scrolling animation
180-
// Private method
181-
// Runs functions
224+
// @private
182225
var loopAnimateScroll = function () {
183226
timeLapsed += 16;
184227
percentage = ( timeLapsed / speed );
@@ -189,15 +232,14 @@
189232
};
190233

191234
// Set interval timer
192-
// Private method
193-
// Runs functions
235+
// @private
194236
var startAnimateScroll = function () {
195-
options.callbackBefore( toggle, anchor ); // Run callbacks before animating scroll
237+
settings.callbackBefore( toggle, anchor ); // Run callbacks before animating scroll
196238
animationInterval = setInterval(loopAnimateScroll, 16);
197239
};
198240

199241
// Reset position to fix weird iOS bug
200-
// https://github.com/cferdinandi/smooth-scroll/issues/45
242+
// @link https://github.com/cferdinandi/smooth-scroll/issues/45
201243
if ( root.pageYOffset === 0 ) {
202244
root.scrollTo( 0, 0 );
203245
}
@@ -208,24 +250,29 @@
208250
};
209251

210252
// Initialize Smooth Scroll
211-
// Public method
212-
// Runs functions
253+
// @public
254+
// @param {Object} options User settings
213255
exports.init = function ( options ) {
214256

215257
// feature test
216-
if ( !supports() ) return;
258+
if ( !supports.html5 ) return;
217259

218260
// Selectors and variables
219-
options = extend( defaults, options || {} ); // Merge user options with defaults
261+
var settings = extend( defaults, options || {} ); // Merge user options with defaults
220262
var toggles = document.querySelectorAll('[data-scroll]'); // Get smooth scroll toggles
221263

222264
// When a toggle is clicked, run the click handler
223-
Array.prototype.forEach.call(toggles, function (toggle, index) {
224-
toggle.addEventListener('click', exports.animateScroll.bind( null, toggle, toggle.getAttribute('href'), options ), false);
265+
forEach(toggles, function (toggle) {
266+
toggle.addEventListener('click', exports.animateScroll.bind( null, toggle, toggle.getAttribute('href'), settings ), false);
225267
});
226268

227269
};
228270

271+
272+
/*
273+
* Public APIs
274+
*/
275+
229276
return exports;
230277

231278
});

0 commit comments

Comments
 (0)