PageSourceSearch

https://www.rewriting-the-rules.com/wp-content/themes/artmag/js/theia-sticky-sidebar.js?ver=6.9.9

js rewriting-the-rules.com collected 2026-10-02 04:42:26 UTC 10,590 bytes, 322 lines download raw bytes

1/*!
2 * Theia Sticky Sidebar v1.3.0
3 * https://github.com/WeCodePixels/theia-sticky-sidebar
4 *
5 * Glues your website's sidebars, making them permanently visible while scrolling.
6 *
7 * Copyright 2013-2014 WeCodePixels and other contributors
8 * Released under the MIT license
9 */
10
11(function ($) {
12	$.fn.theiaStickySidebar = function (options) {
13		var defaults = {
14			'containerSelector': '',
15			'additionalMarginTop': 0,
16			'additionalMarginBottom': 0,
17			'updateSidebarHeight': true,
18			'minWidth': 0,
19			'sidebarBehavior': 'modern'
20		};
21		options = $.extend(defaults, options);
22
23		// Validate options
24		options.additionalMarginTop = parseInt(options.additionalMarginTop) || 0;
25		options.additionalMarginBottom = parseInt(options.additionalMarginBottom) || 0;
26
27		tryInitOrHookIntoEvents(options, this);
28
29		// Try doing init, otherwise hook into window.resize and document.scroll and try again then.
30		function tryInitOrHookIntoEvents(options, $that) {
31			var success = tryInit(options, $that);
32
33			if (!success) {
34				console.log('TST: Body width smaller than options.minWidth. Init is delayed.');
35
36				$(document).scroll(function (options, $that) {
37					return function (evt) {
38						var success = tryInit(options, $that);
39
40						if (success) {
41							$(this).unbind(evt);
42						}
43					};
44				}(options, $that));
45				$(window).resize(function (options, $that) {
46					return function (evt) {
47						var success = tryInit(options, $that);
48
49						if (success) {
50							$(this).unbind(evt);
51						}
52					};
53				}(options, $that))
54			}
55		}
56
57		// Try doing init if proper conditions are met.
58		function tryInit(options, $that) {
59			if (options.initialized === true) {
60				return true;
61			}
62
63			if ($('body').width() < options.minWidth) {
64				return false;
65			}
66
67			init(options, $that);
68
69			return true;
70		}
71
72		// Init the sticky sidebar(s).
73		function init(options, $that) {
74			options.initialized = true;
75
76			// Add CSS
77			$('head').append($('<style>.theiaStickySidebar:after {content: ""; display: table; clear: both;}</style>'));
78
79			$that.each(function () {
80				var o = {};
81
82				o.sidebar = $(this);
83
84				// Save options
85				o.options = options || {};
86
87				// Get container
88				o.container = $(o.options.containerSelector);
89				if (o.container.size() == 0) {
90					o.container = o.sidebar.parent();
91				}
92
93				// Create sticky sidebar
94				o.sidebar.parents().css('-webkit-transform', 'none'); // Fix for WebKit bug - https://code.google.com/p/chromium/issues/detail?id=20574
95				o.sidebar.css({
96					'position': 'relative',
97					'overflow': 'visible',
98					// The "box-sizing" must be set to "content-box" because we set a fixed height to this element when the sticky 
98sidebar has a fixed position.
99					'-webkit-box-sizing': 'border-box',
100					'-moz-box-sizing': 'border-box',
101					'box-sizing': 'border-box'
102				});
103
104				// Get the sticky sidebar element. If none has been found, then create one.
105				o.stickySidebar = o.sidebar.find('.theiaStickySidebar');
106				if (o.stickySidebar.length == 0) {
107					o.sidebar.find('script').remove(); // Remove <script> tags, otherwise they will be run again on the next line.
108					o.stickySidebar = $('<div>').addClass('theiaStickySidebar').append(o.sidebar.children());
109					o.sidebar.append(o.stickySidebar);
110				}
111
112				// Get existing top and bottom margins and paddings
113				o.marginTop = parseInt(o.sidebar.css('margin-top'));
114				o.marginBottom = parseInt(o.sidebar.css('margin-bottom'));
115				o.paddingTop = parseInt(o.sidebar.css('padding-top'));
116				o.paddingBottom = parseInt(o.sidebar.css('padding-bottom'));
117
118				// Add a temporary padding rule to check for collapsable margins.
119				var collapsedTopHeight = o.stickySidebar.offset().top;
120				var collapsedBottomHeight = o.stickySidebar.outerHeight();
121				o.stickySidebar.css('padding-top', 1);
122				o.stickySidebar.css('padding-bottom', 1);
123				collapsedTopHeight -= o.stickySidebar.offset().top;
124				collapsedBottomHeight = o.stickySidebar.outerHeight() - collapsedBottomHeight - collapsedTopHeight;
125				if (collapsedTopHeight == 0) {
126					o.stickySidebar.css('padding-top', 0);
127					o.stickySidebarPaddingTop = 0;
128				}
129				else {
130					o.stickySidebarPaddingTop = 1;
131				}
132
133				if (collapsedBottomHeight == 0) {
134					o.stickySidebar.css('padding-bottom', 0);
135					o.stickySidebarPaddingBottom = 0;
136				}
137				else {
138					o.stickySidebarPaddingBottom = 1;
139				}
140
141				// We use this to know whether the user is scrolling up or down.
142				o.previousScrollTop = null;
143
144				// Scroll top (value) when the sidebar has fixed position.
145				o.fixedScrollTop = 0;
146
147				// Set sidebar to default values.
148				resetSidebar();
149
150				o.onScroll = function (o) {
151					// Stop if the sidebar isn't visible.
152					if (!o.stickySidebar.is(":visible")) {
153						return;
154					}
155
156					// Stop if the window is too small.
157					if ($('body').width() < o.options.minWidth) {
158						resetSidebar();
159						return;
160					}
161
162					// Stop if the sidebar width is larger than the container width (e.g. the theme is responsive and the sidebar is now below the content)
163					if (o.sidebar.outerWidth(true) + 50 > o.container.width()) {
164						resetSidebar();
165						return;
166					}
167
168					var scrollTop = $(document).scrollTop();
169					var position = 'static';
170
171					// If the user has scrolled down enough for the sidebar to be clipped at the top, then we can consider changing its position.
172					if (scrollTop >= o.container.offset().top + (o.paddingTop + o.marginTop - o.options.additionalMarginTop)) {
173						// The top and bottom offsets, used in various calculations.
174						var offsetTop = o.paddingTop + o.marginTop + options.additionalMarginTop;
175						var offsetBottom = o.paddingBottom + o.marginBottom + options.additionalMarginBottom;
176
177						// All top and bottom positions are relative to the window, not to the parent elemnts.
178						var containerTop = o.container.offset().top;
179						var containerBottom = o.container.offset().top + getClearedHeight(o.container);
180
181						// The top and bottom offsets relative to the window screen top (zero) and bottom (window height).
182						var windowOffsetTop = 0 + options.additionalMarginTop;
183						var windowOffsetBottom;
184
185						var sidebarSmallerThanWindow = (o.stickySidebar.outerHeight() + offsetTop + offsetBottom) < $(window).height();
186						if (sidebarSmallerThanWindow) {
187							windowOffsetBottom = windowOffsetTop + o.stickySidebar.outerHeight();
188						}
189						else {
190							windowOffsetBottom = $(window).height() - o.marginBottom - o.paddingBottom - options.additionalMarginBottom;
191						}
192
193						var staticLimitTop = containerTop - scrollTop + o.paddingTop + o.marginTop;
194						var staticLimitBottom = containerBottom - scrollTop - o.paddingBottom - o.marginBottom;
195
196						var top = o.stickySidebar.offset().top - scrollTop;
197						var scrollTopDiff = o.previousScrollTop - scrollTop;
198
199						// If the sidebar position is fixed, then it won't move up or down by itself. So, we manually adjust the top coordinate.
200						if (o.stickySidebar.css('position') == 'fixed') {
201							if (o.options.sidebarBehavior == 'modern') {
202								top += scrollTopDiff;
203							}
204						}
205
206						if (o.options.sidebarBehavior == 'legacy') {
207							top = windowOffsetBottom - o.stickySidebar.outerHeight();
208							top = Math.max(top, windowOffsetBottom - o.stickySidebar.outerHeight());
209						}
210
211						if (scrollTopDiff > 0) { // If the user is scrolling up.
212							top = Math.min(top, windowOffsetTop);
213						}
214						else { // If the user is scrolling down.
215							top = Math.max(top, windowOffsetBottom - o.stickySidebar.outerHeight());
216						}
217
218						top = Math.max(top, staticLimitTop);
219
220						top = Math.min(top, staticLimitBottom - o.stickySidebar.outerHeight());
221
222						// If the sidebar is the same height as the container, we won't use fixed positioning.
223						var sidebarSameHeightAsContainer = o.container.height() == o.stickySidebar.outerHeight();
224
225						if (!sidebarSameHeightAsContainer && top == windowOffsetTop) {
226							position = 'fixed';
227						}
228						else if (!sidebarSameHeightAsContainer && top == windowOffsetBottom - o.stickySidebar.outerHeight()) {
229							position = 'fixed';
230						}
231						else if (scrollTop + top - o.sidebar.offset().top - o.paddingTop <= options.additionalMarginTop) {
232							// Stuck to the top of the page. No special behavior.
233							position = 'static';
234						}
235						else {
236							// Stuck to the bottom of the page.
237							position = 'absolute';
238						}
239					}
240
241					/*
242					 * Performance notice: It's OK to set these CSS values at each resize/scroll, even if they don't change.
243					 * It's way slower to first check if the values have changed.
244					 */
245					if (position == 'fixed') {
246						o.stickySidebar.css({
247							'position': 'fixed',
248							'width': o.sidebar.width(),
249							'top': top,
250							'left': o.sidebar.offset().left + parseInt(o.sidebar.css('padding-left'))
251						});
252					}
253					else if (position == 'absolute') {
254						var css = {};
255
256						if (o.stickySidebar.css('position') != 'absolute') {
257							css.position = 'absolute';
258							css.top = scrollTop + top - o.sidebar.offset().top - o.stickySidebarPaddingTop - o.stickySidebarPaddingBottom;
259						}
260
261						css.width = o.sidebar.width();
262						css.left = '';
263
264						o.stickySidebar.css(css);
265					}
266					else if (position == 'static') {
267						resetSidebar();
268					}
269
270					if (position != 'static') {
271						if (o.options.updateSidebarHeight == true) {
272							o.sidebar.css({
273								'min-height': o.stickySidebar.outerHeight() + o.stickySidebar.offset().top - o.sidebar.offset().top + o.paddingBottom
274							});
275						}
276					}
277
278					o.previousScrollTop = scrollTop;
279				};
280
281				// Initialize the sidebar's position.
282				o.onScroll(o);
283
284				// Recalculate the sidebar's position on every scroll and resize.
285				$(document).scroll(function (o) {
286					return function () {
287						o.onScroll(o);
288					};
289				}(o));
290				$(window).resize(function (o) {
291					return function () {
292						o.stickySidebar.css({'position': 'static'});
293						o.onScroll(o);
294					};
295				}(o));
296
297				// Reset the sidebar to its default state
298				function resetSidebar() {
299					o.fixedScrollTop = 0;
300					o.sidebar.css({
301						'min-height': '1px'
302					});
303					o.stickySidebar.css({
304						'position': 'static',
305						'width': ''
306					});
307				}
308
309				// Get the height of a div as if its floated children were cleared. Note that this function fails if the floats are more than one level deep.
310				function getClearedHeight(e) {
311					var height = e.height();
312
313					e.children().each(function () {
314						height = Math.max(height, $(this).height());
315					});
316
317					return height;
318				}
319			});
320		}
321	}
322})(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.