PageSourceSearch

https://www.brightful.me/assets/built/sticky-sidebar.js?v=nLZ9L46nEbKJpczR

js brightful.me collected 2026-10-03 21:37:08 UTC 14,647 bytes, 320 lines download raw bytes

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