PageSourceSearch

https://www.iitc.org/wp-content/plugins/bb-sticky-column/js/sticky-column.js?ver=7.1.2

js iitc.org collected 2026-10-02 05:34:22 UTC 16,311 bytes, 514 lines download raw bytes

1
2/**
3  stickybits - Stickybits is a lightweight alternative to `position: sticky` polyfills
4  @version v3.6.1
5  @link https://github.com/dollarshaveclub/stickybits#readme
6  @author Jeff Wainwright <[email protected]> (https://jeffry.in)
7  @license MIT
8**/
9(function (global, factory) {
10  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
11  typeof define === 'function' && define.amd ? define(factory) :
12  (global = global || self, global.stickybits = factory());
13}(this, function () { 'use strict';
14
15  /*
16    STICKYBITS 💉
17    --------
18    > a lightweight alternative to `position: sticky` polyfills 🍬
19    --------
20    - each method is documented above it our view the readme
21    - Stickybits does not manage polymorphic functionality (position like properties)
22    * polymorphic functionality: (in the context of describing Stickybits)
23      means making things like `position: sticky` be loosely supported with position fixed.
24      It also means that features like `useStickyClasses` takes on styles like `position: fixed`.
25    --------
26    defaults 🔌
27    --------
28    - version = `package.json` version
29    - userAgent = viewer browser agent
30    - target = DOM element selector
31    - noStyles = boolean
32    - offset = number
33    - parentClass = 'string'
34    - scrollEl = window || DOM element selector || DOM element
35    - stickyClass = 'string'
36    - stuckClass = 'string'
37    - useStickyClasses = boolean
38    - useFixed = boolean
39    - useGetBoundingClientRect = boolean
40    - verticalPosition = 'string'
41    --------
42    props🔌
43    --------
44    - p = props {object}
45    --------
46    instance note
47    --------
48    - stickybits parent methods return this
49    - stickybits instance methods return an instance item
50    --------
51    nomenclature
52    --------
53    - target => el => e
54    - props => o || p
55    - instance => item => it
56    --------
57    methods
58    --------
59    - .definePosition = defines sticky or fixed
60    - .addInstance = an array of objects for each Stickybits Target
61    - .getClosestParent = gets the parent for non-window scroll
62    - .getTopPosition = gets the element top pixel position from the viewport
63    - .computeScrollOffsets = computes scroll position
64    - .toggleClasses = older browser toggler
65    - .manageState = manages sticky state
66    - .removeClass = older browser support class remover
67    - .removeInstance = removes an instance
68    - .cleanup = removes all Stickybits instances and cleans up dom from stickybits
69  */
70  var Stickybits =
71  /*#__PURE__*/
72  function () {
73    function Stickybits(target, obj) {
74      var o = typeof obj !== 'undefined' ? obj : {};
75      this.version = '3.6.1';
76      this.userAgent = window.navigator.userAgent || 'no `userAgent` provided by the browser';
77      this.props = {
78        customStickyChangeNumber: o.customStickyChangeNumber || null,
79        noStyles: o.noStyles || false,
80        stickyBitStickyOffset: o.stickyBitStickyOffset || 0,
81        parentClass: o.parentClass || 'js-stickybit-parent',
82        scrollEl: typeof o.scrollEl === 'string' ? document.querySelector(o.scrollEl) : o.scrollEl || window,
83        stickyClass: o.stickyClass || 'js-is-sticky',
84        stuckClass: o.stuckClass || 'js-is-stuck',
85        stickyChangeClass: o.stickyChangeClass || 'js-is-sticky--change',
86        useStickyClasses: o.useStickyClasses || false,
87        useFixed: o.useFixed || false,
88        useGetBoundingClientRect: o.useGetBoundingClientRect || false,
89        verticalPosition: o.verticalPosition || 'top'
90        /*
91          define positionVal
92          ----
93          -  uses a computed (`.definePosition()`)
94          -  defined the position
95        */
96
97      };
98      this.props.positionVal = this.definePosition() || 'fixed';
99      this.instances = [];
100      var _this$props = this.props,
101          positionVal = _this$props.positionVal,
102          verticalPosition = _this$props.verticalPosition,
103          noStyles = _this$props.noStyles,
104          stickyBitStickyOffset = _this$props.stickyBitStickyOffset,
105          useStickyClasses = _this$props.useStickyClasses;
106      var verticalPositionStyle = verticalPosition === 'top' && !noStyles ? stickyBitStickyOffset + "px" : '';
107      var positionStyle = positionVal !== 'fixed' ? positionVal : '';
108      this.els = typeof target === 'string' ? document.querySelectorAll(target) : target;
109      if (!('length' in this.els)) this.els = [this.els];
110
111      for (var i = 0; i < this.els.length; i++) {
112        var el = this.els[i]; // set vertical position
113
114        el.style[verticalPosition] = verticalPositionStyle;
115        el.style.position = positionStyle;
116
117        if (positionVal === 'fixed' || useStickyClasses) {
118          var instance = this.addInstance(el, this.props); // instances are an array of objects
119
120          this.instances.push(instance);
121        }
122      }
123    }
124    /*
125      setStickyPosition ✔️
126      --------
127      —  most basic thing stickybits does
128      => checks to see if position sticky is supported
129      => defined the position to be used
130      => stickybits works accordingly
131    */
132
133
134    var _proto = Stickybits.prototype;
135
136    _proto.definePosition = function definePosition() {
137      var stickyProp;
138
139      if (this.props.useFixed) {
140        stickyProp = 'fixed';
141      } else {
142        var prefix = ['', '-o-', '-webkit-', '-moz-', '-ms-'];
143        var test = document.head.style;
144
145        for (var i = 0; i < prefix.length; i += 1) {
146          test.position = prefix[i] + "sticky";
147        }
148
149        stickyProp = test.position ? test.position : 'fixed';
150        test.position = '';
151      }
152
153      return stickyProp;
154    }
155    /*
156      addInstance ✔️
157      --------
158      — manages instances of items
159      - takes in an el and props
160      - returns an item object
161      ---
162      - target = el
163      - o = {object} = props
164        - scrollEl = 'string' | object
165        - verticalPosition = number
166        - off = boolean
167        - parentClass = 'string'
168        - stickyClass = 'string'
169        - stuckClass = 'string'
170      ---
171      - defined later
172        - parent = dom element
173        - state = 'string'
174        - offset = number
175        - stickyStart = number
176        - stickyStop = number
177      - returns an instance object
178    */
179    ;
180
181    _proto.addInstance = function addInstance(el, props) {
182      var _this = this;
183
184      var item = {
185        el: el,
186        parent: el.parentNode,
187        props: props
188      };
189      this.isWin = this.props.scrollEl === window;
190      var se = this.isWin ? window : this.getClosestParent(item.el, item.props.scrollEl);
191      this.computeScrollOffsets(item);
192      item.parent.className += " " + props.parentClass;
193      item.state = 'default';
194
195      item.stateContainer = function () {
196        return _this.manageState(item);
197      };
198
199      se.addEventListener('scroll', item.stateContainer);
200      return item;
201    }
202    /*
203      --------
204      getParent 👨‍
205      --------
206      - a helper function that gets the target element's parent selected el
207      - only used for non `window` scroll elements
208      - supports older browsers
209    */
210    ;
211
212    _proto.getClosestParent = function getClosestParent(el, match) {
213      // p = parent element
214      var p = match;
215      var e = el;
216      if (e.parentElement === p) return p; // traverse up the dom tree until we get to the parent
217
218      while (e.parentElement !== p) {
219        e = e.parentElement;
220      } // return parent element
221
222
223      return p;
224    }
225    /*
226      --------
227      getTopPosition
228      --------
229      - a helper function that gets the topPosition of a Stickybit element
230      - from the top level of the DOM
231    */
232    ;
233
234    _proto.getTopPosition = function getTopPosition(el) {
235      if (this.props.useGetBoundingClientRect) {
236        return el.getBoundingClientRect().top + (this.props.scrollEl.pageYOffset || document.documentElement.scrollTop);
237      }
238
239      var topPosition = 0;
240
241      do {
242        topPosition = el.offsetTop + topPosition;
243      } while (el = el.offsetParent);
244
245      return topPosition;
246    }
247    /*
248      computeScrollOffsets 📊
249      ---
250      computeScrollOffsets for Stickybits
251      - defines
252        - offset
253        - start
254        - stop
255    */
256    ;
257
258    _proto.computeScrollOffsets = function computeScrollOffsets(item) {
259      var it = item;
260      var p = it.props;
261      var el = it.el;
262      var parent = it.parent;
263      var isCustom = !this.isWin && p.positionVal === 'fixed';
264      var isTop = p.verticalPosition !== 'bottom';
265      var scrollElOffset = isCustom ? this.getTopPosition(p.scrollEl) : 0;
266      var stickyStart = isCustom ? this.getTopPosition(parent) - scrollElOffset : this.getTopPosition(parent);
267      var stickyChangeOffset = p.customStickyChangeNumber !== null ? p.customStickyChangeNumber : el.offsetHeight;
268      var parentBottom = stickyStart + parent.offsetHeight;
269      it.offset = scrollElOffset + p.stickyBitStickyOffset;
270      it.stickyStart = isTop ? stickyStart - it.offset : 0;
271      it.stickyChange = it.stickyStart + stickyChangeOffset;
272      it.stickyStop = isTop ? parentBottom - (el.offsetHeight + it.offset) : parentBottom - window.innerHeight;
273      return it;
274    }
275    /*
276      toggleClasses ⚖️
277      ---
278      toggles classes (for older browser support)
279      r = removed class
280      a = added class
281    */
282    ;
283
284    _proto.toggleClasses = function toggleClasses(el, r, a) {
285      var e = el;
286      var cArray = e.className.split(' ');
287      if (a && cArray.indexOf(a) === -1) cArray.push(a);
288      var rItem = cArray.indexOf(r);
289      if (rItem !== -1) cArray.splice(rItem, 1);
290      e.className = cArray.join(' ');
291    }
292    /*
293      manageState 📝
294      ---
295      - defines the state
296        - normal
297        - sticky
298        - stuck
299    */
300    ;
301
302    _proto.manageState = function manageState(item) {
303      // cache object
304      var it = item;
305      var e = it.el;
306      var p = it.props;
307      var state = it.state;
308      var start = it.stickyStart;
309      var change = it.stickyChange;
310      var stop = it.stickyStop;
311      var stl = e.style; // cache props
312
313      var ns = p.noStyles;
314      var pv = p.positionVal;
315      var se = p.scrollEl;
316      var sticky = p.stickyClass;
317      var stickyChange = p.stickyChangeClass;
318      var stuck = p.stuckClass;
319      var vp = p.verticalPosition;
320      var isTop = vp !== 'bottom';
321      /*
322        requestAnimationFrame
323        ---
324        - use rAF
325        - or stub rAF
326      */
327
328      var rAFStub = function rAFDummy(f) {
329        f();
330      };
331
332      var rAF = !this.isWin ? rAFStub : window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame || rAFStub;
333      /*
334        define scroll vars
335        ---
336        - scroll
337        - notSticky
338        - isSticky
339        - isStuck
340      */
341
342      var tC = this.toggleClasses;
343      var scroll = this.isWin ? window.scrollY || window.pageYOffset : se.scrollTop;
344      var notSticky = scroll > start && scroll < stop && (state === 'default' || state === 'stuck');
345      var isSticky = isTop && scroll <= start && (state === 'sticky' || state === 'stuck');
346      var isStuck = scroll >= stop && state === 'sticky';
347      /*
348        Unnamed arrow functions within this block
349        ---
350        - help wanted or discussion
351        - view test.stickybits.js
352          - `stickybits .manageState  `position: fixed` interface` for more awareness 👀
353      */
354
355      if (notSticky) {
356        it.state = 'sticky';
357        rAF(function () {
358          tC(e, stuck, sticky);
359          stl.position = pv;
360          if (ns) return;
361          stl.bottom = '';
362          stl[vp] = p.stickyBitStickyOffset + "px";
363        });
364      } else if (isSticky) {
365        it.state = 'default';
366        rAF(function () {
367          tC(e, sticky);
368          tC(e, stuck);
369          if (pv === 'fixed') stl.position = '';
370        });
371      } else if (isStuck) {
372        it.state = 'stuck';
373        rAF(function () {
374          tC(e, sticky, stuck);
375          if (pv !== 'fixed' || ns) return;
376          stl.top = '';
377          stl.bottom = '0';
378          stl.position = 'absolute';
379        });
380      }
381
382      var isStickyChange = scroll >= change && scroll <= stop;
383      var isNotStickyChange = scroll < change / 2 || scroll > stop;
384      var stub = 'stub'; // a stub css class to remove
385
386      if (isNotStickyChange) {
387        rAF(function () {
388          tC(e, stickyChange);
389        });
390      } else if (isStickyChange) {
391        rAF(function () {
392          tC(e, stub, stickyChange);
393        });
394      }
395
396      return it;
397    };
398
399    _proto.update = function update(updatedProps) {
400      if (updatedProps === void 0) {
401        updatedProps = null;
402      }
403
404      for (var i = 0; i < this.instances.length; i += 1) {
405        var instance = this.instances[i];
406        this.computeScrollOffsets(instance);
407
408        if (updatedProps) {
409          for (var updatedProp in updatedProps) {
410            instance.props[updatedProp] = updatedProps[updatedProp];
411          }
412        }
413      }
414
415      return this;
416    }
417    /*
418      removes an instance 👋
419      --------
420      - cleanup instance
421    */
422    ;
423
424    _proto.removeInstance = function removeInstance(instance) {
425      var e = instance.el;
426      var p = instance.props;
427      var tC = this.toggleClasses;
428      e.style.position = '';
429      e.style[p.verticalPosition] = '';
430      tC(e, p.stickyClass);
431      tC(e, p.stuckClass);
432      tC(e.parentNode, p.parentClass);
433    }
434    /*
435      cleanup 🛁
436      --------
437      - cleans up each instance
438      - clears instance
439    */
440    ;
441
442    _proto.cleanup = function cleanup() {
443      for (var i = 0; i < this.instances.length; i += 1) {
444        var instance = this.instances[i];
445        instance.props.scrollEl.removeEventListener('scroll', instance.stateContainer);
446        this.removeInstance(instance);
447      }
448
449      this.manageState = false;
450      this.instances = [];
451    };
452
453    return Stickybits;
454  }();
455  /*
456    export
457    --------
458    exports StickBits to be used 🏁
459  */
460
461
462  function stickybits(target, o) {
463    return new Stickybits(target, o);
464  }
465
466  return stickybits;
467
468}));
469
470
471jQuery(function() {
472
473  var stickybit = [];
474  //dont enable when page builder is active, and check that there is a data-sticky attribute
475  if(!jQuery('body').hasClass('fl-builder-edit') && jQuery("[bt-sticky='true']").length)
476  {
477    var stickyItems = jQuery("[bt-sticky='true']");
478
479    if(stickyItems.length !== 0){
480      //check for overflow visible on all parents and fix
481      jQuery('[bt-sticky]').parents().each(function(){
482        if(jQuery(this).css("overflow") != "visible")
483        {
484          console.log("Sticky Column Notice: CSS Sticky position requires all parent elements to have overflow:visible. We detected one below that does not have that setting. Not to worry, we have updated them automatically.");
485          console.log(jQuery(this));
486          console.log("overflow: " + jQuery(this).css('overflow') + ", changed to...  overflow:visible");
487          jQuery(this).css("overflow","visible");
488        }
489      });
490
491      stickyItems.each(function(index, item){
492        
493        // get the offset
494        var topPadding = parseInt(jQuery(item).attr('bt-sticky-top-margin'));
495        var stickyItem = jQuery(item);
496        
497        //target the parent if its a nested col, then we target the parent
498        if(stickyItem.parent().hasClass('fl-col-group-nested'))
499          stickyItem = stickyItem.parent();
500
501        stickybit[jQuery(item).attr('data-node')] = stickybits(stickyItem,{
502          stickyBitStickyOffset: topPadding,
503          useStickyClasses: true,
504          stickyClass: 'bt-sticking',
505          stuckClass: 'bt-stuck',
506        });
507      });
508    }
509  }
510});
511
512
513
514

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.