PageSourceSearch

https://corridadethiais.com/assets/js/smooth-scroll.js

js corridadethiais.com collected 2026-10-08 07:35:50 UTC 14,262 bytes, 426 lines download raw bytes

1(function (root, factory) {
2	if ( typeof define === 'function' && define.amd ) {
3		define([], factory(root));
4	} else if ( typeof exports === 'object' ) {
5		module.exports = factory(root);
6	} else {
7		root.smoothScroll = factory(root);
8	}
9})(this, function (root) {
10
11	'use strict';
12
13	//
14	// Variables
15	//
16
17	var smoothScroll = {}; // Object for public APIs
18	var supports = !!document.querySelector && !!root.addEventListener; // Feature test
19	var settings, eventTimeout, fixedHeader, headerHeight;
20
21	// Default settings
22	var defaults = {
23		speed: 500,
24		easing: 'easeInOutCubic',
25		offset: 0,
26		updateURL: true,
27		callbackBefore: function () {},
28		callbackAfter: function () {}
29	};
30
31
32	//
33	// Methods
34	//
35
36	/**
37	 * A simple forEach() implementation for Arrays, Objects and NodeLists
38	 * @private
39	 * @param {Array|Object|NodeList} collection Collection of items to iterate
40	 * @param {Function} callback Callback function for each iteration
41	 * @param {Array|Object|NodeList} scope Object/NodeList/Array that forEach is iterating over (aka `this`)
42	 */
43	var forEach = function (collection, callback, scope) {
44		if (Object.prototype.toString.call(collection) === '[object Object]') {
45			for (var prop in collection) {
46				if (Object.prototype.hasOwnProperty.call(collection, prop)) {
47					callback.call(scope, collection[prop], prop, collection);
48				}
49			}
50		} else {
51			for (var i = 0, len = collection.length; i < len; i++) {
52				callback.call(scope, collection[i], i, collection);
53			}
54		}
55	};
56
57	/**
58	 * Merge defaults with user options
59	 * @private
60	 * @param {Object} defaults Default settings
61	 * @param {Object} options User options
62	 * @returns {Object} Merged values of defaults and options
63	 */
64	var extend = function ( defaults, options ) {
65		var extended = {};
66		forEach(defaults, function (value, prop) {
67			extended[prop] = defaults[prop];
68		});
69		forEach(options, function (value, prop) {
70			extended[prop] = options[prop];
71		});
72		return extended;
73	};
74
75	/**
76	 * Get the closest matching element up the DOM tree
77	 * @param {Element} elem Starting element
78	 * @param {String} selector Selector to match against (class, ID, or data attribute)
79	 * @return {Boolean|Element} Returns false if not match found
80	 */
81	var getClosest = function (elem, selector) {
82		var firstChar = selector.charAt(0);
83		for ( ; elem && elem !== document; elem = elem.parentNode ) {
84			if ( firstChar === '.' ) {
85				if ( elem.classList.contains( selector.substr(1) ) ) {
86					return elem;
87				}
88			} else if ( firstChar === '#' ) {
89				if ( elem.id === selector.substr(1) ) {
90					return elem;
91				}
92			} else if ( firstChar === '[' ) {
93				if ( elem.hasAttribute( selector.substr(1, selector.length - 2) ) ) {
94					return elem;
95				}
96			}
97		}
98		return false;
99	};
100
101	/**
102	 * Get the height of an element
103	 * @private
104	 * @param  {Node]} elem The element
105	 * @return {Number}     The element's height
106	 */
107	var getHeight = function (elem) {
108		return Math.max( elem.scrollHeight, elem.offsetHeight, elem.clientHeight );
109	};
110
111	/**
112	 * Escape special characters for use with querySelector
113	 * @private
114	 * @param {String} id The anchor ID to escape
115	 * @author Mathias Bynens
116	 * @link https://github.com/mathiasbynens/CSS.escape
117	 */
118	var escapeCharacters = function ( id ) {
119		var string = String(id);
120		var length = string.length;
121		var index = -1;
122		var codeUnit;
123		var result = '';
124		var firstCodeUnit = string.charCodeAt(0);
125		while (++index < length) {
126			codeUnit = string.charCodeAt(index);
127			// Note: there’s no need to special-case astral symbols, surrogate
128			// pairs, or lone surrogates.
129
130			// If the character is NULL (U+0000), then throw an
131			// `InvalidCharacterError` exception and terminate these steps.
132			if (codeUnit === 0x0000) {
133				throw new InvalidCharacterError(
134					'Invalid character: the input contains U+0000.'
135				);
136			}
137
138			if (
139				// If the character is in the range [\1-\1F] (U+0001 to U+001F) or is
140				// U+007F, […]
141				(codeUnit >= 0x0001 && codeUnit <= 0x001F) || codeUnit == 0x007F ||
142				// If the character is the first character and is in the range [0-9]
143				// (U+0030 to U+0039), […]
144				(index === 0 && codeUnit >= 0x0030 && codeUnit <= 0x0039) ||
145				// If the character is the second character and is in the range [0-9]
146				// (U+0030 to U+0039) and the first character is a `-` (U+002D), […]
147				(
148					index === 1 &&
149					codeUnit >= 0x0030 && codeUnit <= 0x0039 &&
150					firstCodeUnit === 0x002D
151				)
152			) {
153				// http://dev.w3.org/csswg/cssom/#escape-a-character-as-code-point
154				result += '\\' + codeUnit.toString(16) + ' ';
155				continue;
156			}
157
158			// If the character is not handled by one of the above rules and is
159			// greater than or equal to U+0080, is `-` (U+002D) or `_` (U+005F), or
160			// is in one of the ranges [0-9] (U+0030 to U+0039), [A-Z] (U+0041 to
161			// U+005A), or [a-z] (U+0061 to U+007A), […]
162			if (
163				codeUnit >= 0x0080 ||
164				codeUnit === 0x002D ||
165				codeUnit === 0x005F ||
166				codeUnit >= 0x0030 && codeUnit <= 0x0039 ||
167				codeUnit >= 0x0041 && codeUnit <= 0x005A ||
168				codeUnit >= 0x0061 && codeUnit <= 0x007A
169			) {
170				// the character itself
171				result += string.charAt(index);
172				continue;
173			}
174
175			// Otherwise, the escaped character.
176			// http://dev.w3.org/csswg/cssom/#escape-a-character
177			result += '\\' + string.charAt(index);
178
179		}
180		return result;
181	};
182
183	/**
184	 * Calculate the easing pattern
185	 * @private
186	 * @link https://gist.github.com/gre/1650294
187	 * @param {String} type Easing pattern
188	 * @param {Number} time Time animation should take to complete
189	 * @returns {Number}
190	 */
191	var easingPattern = function ( type, time ) {
192		var pattern;
193		if ( type === 'easeInQuad' ) pattern = time * time; // accelerating from zero velocity
194		if ( type === 'easeOutQuad' ) pattern = time * (2 - time); // decelerating to zero velocity
195		if ( type === 'easeInOutQuad' ) pattern = time < 0.5 ? 2 * time * time : -1 + (4 - 2 * t
195ime) * time; // acceleration until halfway, then deceleration
196		if ( type === 'easeInCubic' ) pattern = time * time * time; // accelerating from zero velocity
197		if ( type === 'easeOutCubic' ) pattern = (--time) * time * time + 1; // decelerating to zero velocity
198		if ( type === 'easeInOutCubic' ) pattern = time < 0.5 ? 4 * time * time * time : (time - 1) * (2 * time - 2) * (2 * time - 2) + 1; // acceleration until halfway, then deceleration
199		if ( type === 'easeInQuart' ) pattern = time * time * time * time; // accelerating from zero velocity
200		if ( type === 'easeOutQuart' ) pattern = 1 - (--time) * time * time * time; // decelerating to zero velocity
201		if ( type === 'easeInOutQuart' ) pattern = time < 0.5 ? 8 * time * time * time * time : 1 - 8 * (--time) * time * time * time; // acceleration until halfway, then deceleration
202		if ( type === 'easeInQuint' ) pattern = time * time * time * time * time; // accelerating from zero velocity
203		if ( type === 'easeOutQuint' ) pattern = 1 + (--time) * time * time * time * time; // decelerating to zero velocity
204		if ( type === 'easeInOutQuint' ) pattern = time < 0.5 ? 16 * time * time * time * time * time : 1 + 16 * (--time) * time * time * time * time; // acceleration until halfway, then deceleration
205		return pattern || time; // no easing, no acceleration
206	};
207
208	/**
209	 * Calculate how far to scroll
210	 * @private
211	 * @param {Element} anchor The anchor element to scroll to
212	 * @param {Number} headerHeight Height of a fixed header, if any
213	 * @param {Number} offset Number of pixels by which to offset scroll
214	 * @returns {Number}
215	 */
216	var getEndLocation = function ( anchor, headerHeight, offset ) {
217		var location = 0;
218		if (anchor.offsetParent) {
219			do {
220				location += anchor.offsetTop;
221				anchor = anchor.offsetParent;
222			} while (anchor);
223		}
224		location = location - headerHeight - offset;
225		return location >= 0 ? location : 0;
226	};
227
228	/**
229	 * Determine the document's height
230	 * @private
231	 * @returns {Number}
232	 */
233	var getDocumentHeight = function () {
234		return Math.max(
235			document.body.scrollHeight, document.documentElement.scrollHeight,
236			document.body.offsetHeight, document.documentElement.offsetHeight,
237			document.body.clientHeight, document.documentElement.clientHeight
238		);
239	};
240
241	/**
242	 * Convert data-options attribute into an object of key/value pairs
243	 * @private
244	 * @param {String} options Link-specific options as a data attribute string
245	 * @returns {Object}
246	 */
247	var getDataOptions = function ( options ) {
248		return !options || !(typeof JSON === 'object' && typeof JSON.parse === 'function') ? {} : JSON.parse( options );
249	};
250
251	/**
252	 * Update the URL
253	 * @private
254	 * @param {Element} anchor The element to scroll to
255	 * @param {Boolean} url Whether or not to update the URL history
256	 */
257	var updateUrl = function ( anchor, url ) {
258		if ( history.pushState && (url || url === 'true') ) {
259			history.pushState( null, null, [root.location.protocol, '//', root.location.host, root.location.pathname, root.location.search, anchor].join('') );
260		}
261	};
262
263	var getHeaderHeight = function ( header ) {
264		return header === null ? 0 : ( getHeight( header ) + header.offsetTop );
265	};
266
267	/**
268	 * Start/stop the scrolling animation
269	 * @public
270	 * @param {Element} toggle The element that toggled the scroll event
271	 * @param {Element} anchor The element to scroll to
272	 * @param {Object} options
273	 */
274	smoothScroll.animateScroll = function ( toggle, anchor, options ) {
275
276		// Options and overrides
277		var settings = extend( settings || defaults, options || {} );  // Merge user options with defaults
278		var overrides = getDataOptions( toggle ? toggle.getAttribute('data-options') : null );
279		settings = extend( settings, overrides );
280		anchor = '#' + escapeCharacters(anchor.substr(1)); // Escape special characters and leading numbers
281
282		// Selectors and variables
283		var anchorElem = anchor === '#' ? document.documentElement : document.querySelector(anchor);
284		var startLocation = root.pageYOffset; // Current location on the page
285		if ( !fixedHeader ) { fixedHeader = document.querySelector('[data-scroll-header]'); }  // Get the fixed header if not already set
286		if ( !headerHeight ) { headerHeight = getHeaderHeight( fixedHeader ); } // Get the height of a fixed header if one exists and not already set
287		var endLocation = getEndLocation( anchorElem, headerHeight, parseInt(settings.offset, 10) ); // Scroll to location
288		var animationInterval; // interval timer
289		var distance = endLocation - startLocation; // distance to travel
290		var documentHeight = getDocumentHeight();
291		var timeLapsed = 0;
292		var percentage, position;
293
294		// Update URL
295		updateUrl(anchor, settings.updateURL);
296
297		/**
298		 * Stop the scroll animation when it reaches its target (or the bottom/top of page)
299		 * @private
300		 * @param {Number} position Current position on the page
301		 * @param {Number} endLocation Scroll to location
302		 * @param {Number} animationInterval How much to scroll on this loop
303		 */
304		var stopAnimateScroll = function (position, endLocation, animationInterval) {
305			var currentLocation = root.pageYOffset;
306			if ( position == endLocation || currentLocation == endLocation || ( (root.innerHe
306ight + currentLocation) >= documentHeight ) ) {
307				clearInterval(animationInterval);
308				anchorElem.focus();
309				settings.callbackAfter( toggle, anchor ); // Run callbacks after animation complete
310			}
311		};
312
313		/**
314		 * Loop scrolling animation
315		 * @private
316		 */
317		var loopAnimateScroll = function () {
318			timeLapsed += 16;
319			percentage = ( timeLapsed / parseInt(settings.speed, 10) );
320			percentage = ( percentage > 1 ) ? 1 : percentage;
321			position = startLocation + ( distance * easingPattern(settings.easing, percentage) );
322			root.scrollTo( 0, Math.floor(position) );
323			stopAnimateScroll(position, endLocation, animationInterval);
324		};
325
326		/**
327		 * Set interval timer
328		 * @private
329		 */
330		var startAnimateScroll = function () {
331			settings.callbackBefore( toggle, anchor ); // Run callbacks before animating scroll
332			animationInterval = setInterval(loopAnimateScroll, 16);
333		};
334
335		/**
336		 * Reset position to fix weird iOS bug
337		 * @link https://github.com/cferdinandi/smooth-scroll/issues/45
338		 */
339		if ( root.pageYOffset === 0 ) {
340			root.scrollTo( 0, 0 );
341		}
342
343		// Start scrolling animation
344		startAnimateScroll();
345
346	};
347
348	/**
349	 * If smooth scroll element clicked, animate scroll
350	 * @private
351	 */
352	var eventHandler = function (event) {
353		var toggle = getClosest(event.target, '[data-scroll]');
354		if ( toggle && toggle.tagName.toLowerCase() === 'a' ) {
355			event.preventDefault(); // Prevent default click event
356			smoothScroll.animateScroll( toggle, toggle.hash, settings); // Animate scroll
357		}
358	};
359
360	/**
361	 * On window scroll and resize, only run events at a rate of 15fps for better performance
362	 * @private
363	 * @param  {Function} eventTimeout Timeout function
364	 * @param  {Object} settings
365	 */
366	var eventThrottler = function (event) {
367		if ( !eventTimeout ) {
368			eventTimeout = setTimeout(function() {
369				eventTimeout = null; // Reset timeout
370				headerHeight = getHeaderHeight( fixedHeader ); // Get the height of a fixed header if one exists
371			}, 66);
372		}
373	};
374
375	/**
376	 * Destroy the current initialization.
377	 * @public
378	 */
379	smoothScroll.destroy = function () {
380
381		// If plugin isn't already initialized, stop
382		if ( !settings ) return;
383
384		// Remove event listeners
385		document.removeEventListener( 'click', eventHandler, false );
386		root.removeEventListener( 'resize', eventThrottler, false );
387
388		// Reset varaibles
389		settings = null;
390		eventTimeout = null;
391		fixedHeader = null;
392		headerHeight = null;
393	};
394
395	/**
396	 * Initialize Smooth Scroll
397	 * @public
398	 * @param {Object} options User settings
399	 */
400	smoothScroll.init = function ( options ) {
401
402		// feature test
403		if ( !supports ) return;
404
405		// Destroy any existing initializations
406		smoothScroll.destroy();
407
408		// Selectors and variables
409		settings = extend( defaults, options || {} ); // Merge user options with defaults
410		fixedHeader = document.querySelector('[data-scroll-header]'); // Get the fixed header
411		headerHeight = getHeaderHeight( fixedHeader );
412
413		// When a toggle is clicked, run the click handler
414		document.addEventListener('click', eventHandler, false );
415		if ( fixedHeader ) { root.addEventListener( 'resize', eventThrottler, false ); }
416
417	};
418
419
420	//
421	// Public APIs
422	//
423
424	return smoothScroll;
425
426});

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.