PageSourceSearch

https://amazonklubben.nu/wp-content/themes/sparkling/assets/js/functions.js?ver=2.6.11

js amazonklubben.nu collected 2026-10-09 05:15:51 UTC 6,129 bytes, 250 lines download raw bytes

1/**
2 * Sparkling theme scripts.
3 *
4 * Plain DOM APIs -- no jQuery. The two globals (SparklingIsMobile and
5 * generateMobileMenu) are kept on window because child themes may call them.
6 */
7( function () {
8	'use strict';
9
10	/**
11	 * Run a callback once the DOM is ready.
12	 *
13	 * @param {Function} fn Callback.
14	 */
15	function ready( fn ) {
16		if ( document.readyState !== 'loading' ) {
17			fn();
18		} else {
19			document.addEventListener( 'DOMContentLoaded', fn );
20		}
21	}
22
23	/**
24	 * Add class names to every element matching a selector.
25	 *
26	 * @param {string} selector CSS selector.
27	 * @param {Array}  classes  Class names to add.
28	 */
29	function addClasses( selector, classes ) {
30		document.querySelectorAll( selector ).forEach( function ( el ) {
31			el.classList.add.apply( el.classList, classes );
32		} );
33	}
34
35	/**
36	 * jQuery's "swing" easing, so the scroll-to-top motion is unchanged.
37	 *
38	 * @param {number} p Progress from 0 to 1.
39	 * @return {number} Eased progress.
40	 */
41	function swing( p ) {
42		return 0.5 - Math.cos( p * Math.PI ) / 2;
43	}
44
45	function prefersReducedMotion() {
46		return window.matchMedia && window.matchMedia( '(prefers-reduced-motion: reduce)' ).matches;
47	}
48
49	/**
50	 * Fade an element in or out, matching jQuery's default 400ms fade.
51	 *
52	 * @param {Element} el   Target element.
53	 * @param {boolean} into True to fade in, false to fade out.
54	 */
55	function fade( el, into ) {
56		if ( ! el || el.dataset.sparklingFading === String( into ) ) {
57			return;
58		}
59
60		el.dataset.sparklingFading = String( into );
61
62		if ( prefersReducedMotion() ) {
63			el.style.opacity = into ? '1' : '';
64			el.style.display = into ? 'block' : 'none';
65			return;
66		}
67
68		var duration = 400;
69		var start    = null;
70		var from     = parseFloat( window.getComputedStyle( el ).opacity );
71
72		if ( isNaN( from ) ) {
73			from = into ? 0 : 1;
74		}
75
76		if ( into ) {
77			el.style.display = 'block';
78		}
79
80		function step( ts ) {
81			if ( start === null ) {
82				start = ts;
83			}
84
85			var p = Math.min( ( ts - start ) / duration, 1 );
86			var v = from + ( ( into ? 1 : 0 ) - from ) * swing( p );
87
88			el.style.opacity = String( v );
89
90			if ( p < 1 ) {
91				window.requestAnimationFrame( step );
92			} else if ( ! into ) {
93				el.style.display = 'none';
94				el.style.opacity = '';
95			}
96		}
97
98		window.requestAnimationFrame( step );
99	}
100
101	/**
102	 * Detect a mobile user agent.
103	 *
104	 * Kept as-is (including the UA sniff) because the mobile menu styling below
105	 * depends on it and child themes may override this function.
106	 *
107	 * @return {boolean} True on a mobile user agent.
108	 */
109	window.SparklingIsMobile = function () {
110		return (
111			navigator.userAgent.match( /Android/i ) ||
112			navigator.userAgent.match( /webOS/i ) ||
113			navigator.userAgent.match( /iPhone/i ) ||
114			navigator.userAgent.match( /iPod/i ) ||
115			navigator.userAgent.match( /iPad/i ) ||
116			navigator.userAgent.match( /BlackBerry/ )
117		);
118	};
119
120	/**
121	 * Toggle the tap-friendly menu class on touch devices at tablet width and up.
122	 */
123	window.generateMobileMenu = function () {
124		var menu = document.querySelector( '#masthead .site-navigation-inner .navbar-collapse > ul.nav' );
125
126		if ( ! menu ) {
127			return;
128		}
129
130		if ( window.SparklingIsMobile() && window.innerWidth > 767 ) {
131			menu.classList.add( 'sparkling-mobile-menu' );
132		} else {
133			menu.classList.remove( 'sparkling-mobile-menu' );
134		}
135	};
136
137	/**
138	 * Apply Bootstrap classes to markup WordPress generates.
139	 */
140	function styleCoreMarkup() {
141		addClasses( '.comment-reply-link', [ 'btn', 'btn-sm', 'btn-default' ] );
142		addClasses(
143			'#submit, button[type=submit], html input[type=button], input[type=reset], input[type=submit]',
144			[ 'btn', 'btn-default' ]
145		);
146		addClasses( '.widget_rss ul', [ 'media-list' ] );
147		addClasses( '.postform', [ 'form-control' ] );
148		addClasses( 'table#wp-calendar', [ 'table', 'table-striped' ] );
149	}
150
151	/**
152	 * Scroll-to-top button: reveal past 100px, and smooth-scroll on click.
153	 */
154	function initScrollToTop() {
155		var button = document.querySelector( '.scroll-to-top' );
156
157		if ( ! button ) {
158			return;
159		}
160
161		function onScroll() {
162			fade( button, ( window.pageYOffset || document.documentElement.scrollTop ) > 100 );
163		}
164
165		window.addEventListener( 'scroll', onScroll, { passive: true } );
166		onScroll();
167
168		button.addEventListener( 'click', function ( event ) {
169			event.preventDefault();
170
171			var from = window.pageYOffset || document.documentElement.scrollTop;
172
173			if ( ! from ) {
174				return;
175			}
176
177			if ( prefersReducedMotion() ) {
178				window.scrollTo( 0, 0 );
179				return;
180			}
181
182			var duration = 800;
183			var start    = null;
184
185			function step( ts ) {
186				if ( start === null ) {
187					start = ts;
188				}
189
190				var p = Math.min( ( ts - start ) / duration, 1 );
191
192				window.scrollTo( 0, from * ( 1 - swing( p ) ) );
193
194				if ( p < 1 ) {
195					window.requestAnimationFrame( step );
196				}
197			}
198
199			window.requestAnimationFrame( step );
200		} );
201	}
202
203	/**
204	 * Dropdown toggles in the navbar.
205	 */
206	function initDropdowns() {
207		document.querySelectorAll( '.sparkling-dropdown' ).forEach( function ( el ) {
208			el.addEventListener( 'click', function () {
209				if ( el.parentNode ) {
210					el.parentNode.classList.toggle( 'open' );
211				}
212			} );
213		} );
214	}
215
216	/**
217	 * Reserve space under a fixed navbar so content is not hidden behind it.
218	 */
219	function initStickyHeader() {
220		var navbar = document.querySelector( '.navbar-fixed-top' );
221
222		if ( ! navbar ) {
223			return;
224		}
225
226		var header = navbar.closest( 'header' );
227
228		if ( ! header ) {
229			return;
230		}
231
232		// getComputedStyle().height resolves to the content box, matching the
233		// jQuery .height() this replaced.
234		var adminbar    = document.getElementById( 'wpadminbar' );
235		var navHeight   = parseFloat( window.getComputedStyle( navbar ).height ) || 0;
236		var adminHeight = adminbar ? parseFloat( window.getComputedStyle( adminbar ).height ) || 0 : 0;
237
238		header.style.marginBottom = ( adminbar ? Math.abs( navHeight - adminHeight ) : navHeight ) + 'px';
239	}
240
241	ready( function () {
242		styleCoreMarkup();
243		initScrollToTop();
244		initDropdowns();
245		initStickyHeader();
246		window.generateMobileMenu();
247
248		window.addEventListener( 'resize', window.generateMobileMenu );
249	} );
250}() );

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.