PageSourceSearch

https://www.narconon.ca/theme/js/fixedsticky.js

js narconon.ca collected 2026-09-26 08:28:11 UTC 5,252 bytes, 194 lines download raw bytes

1;(function( win, $ ) {
2
3	function featureTest( property, value, noPrefixes ) {
4
5		if (window.forceFixedStickyNoNative && value == 'sticky') return false;
6
7		// Thanks Modernizr! https://github.com/phistuck/Modernizr/commit/3fb7217f5f8274e2f11fe6cfeda7cfaf9948a1f5
8		var prop = property + ':',
9			el = document.createElement( 'test' ),
10			mStyle = el.style;
11
12		if( !noPrefixes ) {
13			mStyle.cssText = prop + [ '-webkit-', '-moz-', '-ms-', '-o-', '' ].join( value + ';' + prop ) + value + ';';
14		} else {
15			mStyle.cssText = prop + value;
16		}
17		return mStyle[ property ].indexOf( value ) !== -1;
18	}
19
20	function getPx( unit ) {
21		return parseInt( unit, 10 ) || 0;
22	}
23
24	var uniqueIdCounter = 0;
25
26	var S = {
27		classes: {
28			plugin: 'fixedsticky',
29			active: 'fixedsticky-on',
30			inactive: 'fixedsticky-off',
31			clone: 'fixedsticky-dummy',
32			withoutFixedFixed: 'fixedsticky-withoutfixedfixed'
33		},
34		keys: {
35			offset: 'fixedStickyOffset',
36			position: 'fixedStickyPosition',
37			id: 'fixedStickyId'
38		},
39		tests: {
40			sticky: featureTest( 'position', 'sticky' ),
41			fixed: featureTest( 'position', 'fixed', true )
42		},
43		// Thanks jQuery!
44		getScrollTop: function() {
45			var prop = 'pageYOffset',
46				method = 'scrollTop';
47			return win ? (prop in win) ? win[ prop ] :
48				win.document.documentElement[ method ] :
49				win.document.body[ method ];
50		},
51		bypass: function() {
52			// Check native sticky, check fixed and if fixed-fixed is also included on the page and is supported
53			return ( S.tests.sticky && !S.optOut ) ||
54				!S.tests.fixed ||
55				win.FixedFixed && !$( win.document.documentElement ).hasClass( 'fixed-supported' );
56		},
57		update: function( el ) {
58			if( !el.offsetWidth ) { return; }
59
60			var $el = $( el ),
61				height = $el.outerHeight(),
62				initialOffset = $el.data( S.keys.offset ),
63				scroll = S.getScrollTop(),
64				isAlreadyOn = $el.is( '.' + S.classes.active ),
65				toggle = function( turnOn ) {
66					$el[ turnOn ? 'addClass' : 'removeClass' ]( S.classes.active )
67						[ !turnOn ? 'addClass' : 'removeClass' ]( S.classes.inactive );
68				},
69				viewportHeight = $( window ).height(),
70				position = $el.data( S.keys.position ),
71				skipSettingToFixed,
72				elTop,
73				elBottom,
74				$parent = $el.parent(),
75				parentOffset = $parent.offset().top,
76				parentHeight = $parent.outerHeight();
77
78			if( initialOffset === undefined ) {
79				initialOffset = $el.offset().top;
80				$el.data( S.keys.offset, initialOffset );
81				$el.after( $( '<div>' ).addClass( S.classes.clone ).height( height ) );
82			}
83
84			if( !position ) {
85				// Some browsers require fixed/absolute to report accurate top/left values.
86				skipSettingToFixed = $el.css( 'top' ) !== 'auto' || $el.css( 'bottom' ) !== 'auto';
87
88				if( !skipSettingToFixed ) {
89					$el.css( 'position', 'fixed' );
90				}
91
92				position = {
93					top: $el.css( 'top' ) !== 'auto',
94					bottom: $el.css( 'bottom' ) !== 'auto'
95				};
96
97				if( !skipSettingToFixed ) {
98					$el.css( 'position', '' );
99				}
100
101				$el.data( S.keys.position, position );
102			}
103
104			function isFixedToTop() {
105				var offsetTop = scroll + elTop;
106
107				// Initial Offset Top
108				return initialOffset < offsetTop &&
109					// Container Bottom
110					offsetTop + height <= parentOffset + parentHeight;
111			}
112
113			function isFixedToBottom() {
114				// Initial Offset Top + Height
115				return initialOffset + ( height || 0 ) > scroll + viewportHeight - elBottom &&
116					// Container Top
117					scroll + viewportHeight - elBottom >= parentOffset + ( height || 0 );
118			}
119
120			elTop = getPx( $el.css( 'top' ) );
121			elBottom = getPx( $el.css( 'bottom' ) );
122
123			if( position.top && isFixedToTop() || position.bottom && isFixedToBottom() ) {
124				if( !isAlreadyOn ) {
125					toggle( true );
126				}
127			} else {
128				if( isAlreadyOn ) {
129					toggle( false );
130				}
131			}
132		},
133		destroy: function( el ) {
134			var $el = $( el );
135			if (S.bypass()) {
136				return;
137			}
138
139			return $el.each(function() {
140				var $this = $( this );
141				var id = $this.data( S.keys.id );
142				$( win ).unbind( '.fixedsticky' + id );
143
144				$this
145					.removeData( [ S.keys.offset, S.keys.position, S.keys.id ] )
146					.removeClass( S.classes.active )
147					.removeClass( S.classes.inactive )
148					.next( '.' + S.classes.clone ).remove();
149			});
150		},
151		init: function( el ) {
152			var $el = $( el );
153
154			if( S.bypass() ) {
155				return;
156			}
157
158			return $el.each(function() {
159				var _this = this;
160				var id = uniqueIdCounter++;
161				$( this ).data( S.keys.id, id );
162
163				$( win ).bind( 'scroll.fixedsticky' + id, function() {
164					S.update( _this );
165				}).trigger( 'scroll.fixedsticky' + id );
166
167				$( win ).bind( 'resize.fixedsticky' + id , function() {
168					if( $el.is( '.' + S.classes.active ) ) {
169						S.update( _this );
170					}
171				});
172			});
173		}
174	};
175
176	win.FixedSticky = S;
177
178	// Plugin
179	$.fn.fixedsticky = function( method ) {
180		if ( typeof S[ method ] === 'function') {
181			return S[ method ].call( S, this);
182		} else if ( typeof method === 'object' || ! method ) {
183			return S.init.call( S, this );
184		} else {
185			throw new Error( 'Method `' +  method + '` does not exist on jQuery.fixedsticky' );
186		}
187	};
188
189	// Add fallback when fixed-fixed is not available.
190	if( !win.FixedFixed ) {
191		$( win.document.documentElement ).addClass( S.classes.withoutFixedFixed );
192	}
193
194})( window, jQuery );

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.