PageSourceSearch

https://accessnepaltour.com/wp-content/themes/accessnepaltour/js/jquery.hc-sticky.js?ver=1.0

js accessnepaltour.com collected 2026-10-02 16:33:24 UTC 22,636 bytes, 743 lines download raw bytes

1/*
2 * HC-Sticky
3 * =========
4 * Version: 2.2.7
5 * Author: Some Web Media
6 * Author URL: https://github.com/somewebmedia
7 * Plugin URL: https://github.com/somewebmedia/hc-sticky
8 * Description: JavaScript library that makes any element on your page visible while you scroll
9 * License: MIT
10 */
11
12'use strict';
13
14(function(global, factory) {
15  if (typeof module === 'object' && typeof module.exports === 'object') {
16    if (global.document) {
17      module.exports = factory(global);
18    }
19    else {
20      throw new Error('HC-Sticky requires a browser to run.');
21    }
22  }
23  else if (typeof define === 'function' && define.amd) {
24    define('hcSticky', [], factory(global));
25  }
26  else {
27    factory(global);
28  }
29})(typeof window !== 'undefined' ? window : this, (window) => {
30  const document = window.document;
31
32  const DEFAULT_OPTIONS = {
33    top: 0,
34    bottom: 0,
35    bottomEnd: 0,
36    innerTop: 0,
37    innerSticker: null,
38    stickyClass: 'sticky',
39    stickTo: null,
40    followScroll: true,
41    responsive: null,
42    mobileFirst: false,
43    onStart: null,
44    onStop: null,
45    onBeforeResize: null,
46    onResize: null,
47    resizeDebounce: 100,
48    disable: false
49  };
50
51  const deprecated = (() => {
52    const pluginName = 'HC Sticky';
53
54    return (what, instead, type) => {
55      console.warn(
56        '%c' + pluginName + ':'
57        + '%c ' + type
58        + "%c '"+ what + "'"
59        + '%c is now deprecated and will be removed. Use'
60        + "%c '" + instead + "'"
61        + '%c instead.',
62        'color: #fa253b',
63        'color: default',
64        'color: #5595c6',
65        'color: default',
66        'color: #5595c6',
67        'color: default');
68    };
69  })();
70
71  const hcSticky = function(elem, userSettings) {
72    userSettings = userSettings || {};
73
74    // use querySeletor if string is passed
75    if (typeof elem === 'string') {
76      elem = document.querySelector(elem);
77    }
78
79    // check if element exist
80    if (!elem) return false;
81
82    if (userSettings.queries) {
83      deprecated('queries', 'responsive', 'option');
84    }
85
86    if (userSettings.queryFlow) {
87      deprecated('queryFlow', 'mobileFirst', 'option');
88    }
89
90    let STICKY_OPTIONS = {};
91    const Helpers = hcSticky.Helpers;
92    const elemParent = elem.parentNode;
93
94    // parent can't be static
95    if (Helpers.getStyle(elemParent, 'position') === 'static') {
96      elemParent.style.position = 'relative';
97    }
98
99    const setOptions = (options) => {
100      options = options || {};
101
102      if (Helpers.isEmptyObject(options) && !Helpers.isEmptyObject(STICKY_OPTIONS)) {
103        // nothing to set
104        return;
105      }
106
107      // extend options
108      STICKY_OPTIONS = Object.assign({}, DEFAULT_OPTIONS, STICKY_OPTIONS, options);
109    };
110
111    const resetOptions = (options) => {
112      STICKY_OPTIONS = Object.assign({}, DEFAULT_OPTIONS, options || {});
113    };
114
115    const getOptions = (option) => {
116      return option ? STICKY_OPTIONS[option] : Object.assign({}, STICKY_OPTIONS);
117    };
118
119    const isDisabled = () => {
120      return STICKY_OPTIONS.disable;
121    };
122
123    const applyQueries = () => {
124      const mediaQueries = STICKY_OPTIONS.responsive || STICKY_OPTIONS.queries;
125
126      if (mediaQueries) {
127        const window_width = window.innerWidth;
128
129        // reset settings
130        resetOptions(userSettings);
131
132        if (STICKY_OPTIONS.mobileFirst) {
133          for (const width in mediaQueries) {
134            if (window_width >= width && !Helpers.isEmptyObject(mediaQueries[width])) {
135              setOptions(mediaQueries[width]);
136            }
137          }
138        }
139        else {
140          const queriesArr = [];
141
142          // convert to array so we can reverse loop it
143          for (const b in mediaQueries) {
144            const q = {};
145
146            q[b] = mediaQueries[b];
147            queriesArr.push(q);
148          }
149
150          for (let i = queriesArr.length - 1; i >= 0; i--) {
151            const query = queriesArr[i];
152            const breakpoint = Object.keys(query)[0];
153
154            if (window_width <= breakpoint && !Helpers.isEmptyObject(query[breakpoint])) {
155              setOptions(query[breakpoint]);
156            }
157          }
158        }
159      }
160    };
161
162    // our helper function for getting necessary styles
163    const getStickyCss = (el) => {
164      const cascadedStyle = Helpers.getCascadedStyle(el);
165      const computedStyle = Helpers.getStyle(el);
166
167      const css = {
168        height: el.offsetHeight + 'px',
169        left: cascadedStyle.left,
170        right: cascadedStyle.right,
171        top: cascadedStyle.top,
172        bottom: cascadedStyle.bottom,
173        position: computedStyle.position,
174        display: computedStyle.display,
175        verticalAlign: computedStyle.verticalAlign,
176        boxSizing: computedStyle.boxSizing,
177        marginLeft: cascadedStyle.marginLeft,
178        marginRight: cascadedStyle.marginRight,
179        marginTop: cascadedStyle.marginTop,
180        marginBottom: cascadedStyle.marginBottom,
181        paddingLeft: cascadedStyle.paddingLeft,
182        paddingRight: cascadedStyle.paddingRight
183      };
184
185      if (cascadedStyle['float']) {
186        css['float'] = cascadedStyle['float'] || 'none';
187      }
188
189      if (cascadedStyle.cssFloat) {
190        css['cssFloat'] = cascadedStyle.cssFloat || 'none';
191      }
192
193      // old firefox box-sizing
194      if (computedStyle.MozBoxSizing) {
195        css['MozBoxSizing'] = computedStyle.MozBoxSizing;
196      }
197
198      css['width'] = cascadedStyle.width !== 'auto' ? cascadedStyle.width : (css.boxSizing === 'border-box' || css.MozBoxSizing === 'border-box' ? el.offsetWidth + 'px' : computedStyle.width);
199
200      return css;
201    };
202
203    const Sticky = {
204      css: {},
205      position: null, // so we don't need to check css all the time
206      stick: (args) => {
207        args = args || {};
208
209        // check if element is already sticky
210        if (Helpers.hasClass(elem, STICKY_OPTIONS.stickyClass)) {
211          return;
212        }
213
214        if (Spacer.isAttached === false) {
215          Spacer.attach();
216        }
217
218        Sticky.position = 'fixed';
219
220        // apply styles
221        elem.style.position = 'fixed';
222        elem.style.left = Spacer.offsetLeft + 'px';
223        elem.style.width = Spacer.width;
224
225        if (typeof args.bottom === 'undefined') {
226          elem.style.bottom = 'auto';
227        }
228        else {
229          elem.style.bottom = args.bottom + 'px';
230        }
231
232        if (typeof args.top === 'undefined') {
233          elem.style.top = 'auto';
234        }
235        else {
236          elem.style.top = args.top + 'px';
237        }
238
239        // add sticky class
240        if (elem.classList) {
241          elem.classList.add(STICKY_OPTIONS.stickyClass);
242        }
243        else {
244          elem.className += ' ' + STICKY_OPTIONS.stickyClass;
245        }
246
247        // fire 'start' event
248        if (STICKY_OPTIONS.onStart) {
249          STICKY_OPTIONS.onStart.call(elem, Object.assign({}, STICKY_OPTIONS));
250        }
251      },
252      release: (args) => {
253        args = args || {};
254        args.stop = args.stop || false;
255
256        // check if we've already done this
257        if (args.stop !== true && Sticky.position !== 'fixed' && Sticky.position !== null && (
258          (typeof args.top === 'undefined' && typeof args.bottom === 'undefined') ||
259          (typeof args.top !== 'undefined' && (parseInt(Helpers.getStyle(elem, 'top')) || 0) === args.top) ||
260          (typeof args.bottom !== 'undefined' && (parseInt(Helpers.getStyle(elem, 'bottom')) || 0) === args.bottom)
261        )) {
262          return;
263        }
264
265        if (args.stop === true) {
266          // remove spacer
267          if (Spacer.isAttached === true) {
268            Spacer.detach();
269          }
270        }
271        else {
272          // check spacer
273          if (Spacer.isAttached === false) {
274            Spacer.attach();
275          }
276        }
277
278        const position = args.position || Sticky.css.position;
279
280        // remember position
281        Sticky.position = position;
282
283        // apply styles
284        elem.style.position = position;
285        elem.style.left = args.stop === true ? Sticky.css.left : Spacer.positionLeft + 'px';
286        elem.style.width = position !== 'absolute' ? Sticky.css.width : Spacer.width;
287
288        if (typeof args.bottom === 'undefined') {
289          elem.style.bottom = args.stop === true ? '' : 'auto';
290        }
291        else {
292          elem.style.bottom = args.bottom + 'px';
293        }
294
295        if (typeof args.top === 'undefined') {
296          elem.style.top = args.stop === true ? '' : 'auto';
297        }
298        else {
299          elem.style.top = args.top + 'px';
300        }
301
302        // remove sticky class
303        if (elem.classList) {
304          elem.classList.remove(STICKY_OPTIONS.stickyClass);
305        }
306        else {
307          elem.className = elem.className.replace(new RegExp('(^|\\b)' + STICKY_OPTIONS.stickyClass.split(' ').join('|') + '(\\b|$)', 'gi'), ' ');
308        }
309
310        // fire 'stop' event
311        if (STICKY_OPTIONS.onStop) {
312          STICKY_OPTIONS.onStop.call(elem, Object.assign({}, STICKY_OPTIONS));
313        }
314      }
315    };
316
317    const Spacer = {
318      el: document.createElement('div'),
319      offsetLeft: null,
320      positionLeft: null,
321      width: null,
322      isAttached: false,
323      init: () => {
324        Spacer.el.className = 'sticky-spacer';
325
326        // copy styles from sticky element
327        for (const prop in Sticky.css) {
328          Spacer.el.style[prop] = Sticky.css[prop];
329        }
330
331        // just to be sure the spacer is behind everything
332        Spacer.el.style['z-index'] = '-1';
333
334        const elemStyle = Helpers.getStyle(elem);
335
336        // get spacer offset and position
337        Spacer.offsetLeft = Helpers.offset(elem).left - (parseInt(elemStyle.marginLeft) || 0);
338        Spacer.positionLeft = Helpers.position(elem).left;
339
340        // get spacer width
341        Spacer.width = Helpers.getStyle(elem, 'width');
342      },
343      attach: () => {
344        // insert spacer to DOM
345        elemParent.insertBefore(Spacer.el, elem);
346        Spacer.isAttached = true;
347      },
348      detach: () => {
349        // remove spacer from DOM
350        Spacer.el = elemParent.removeChild(Spacer.el);
351        Spacer.isAttached = false;
352      }
353    };
354
355    // define our private variables
356    let stickTo_document;
357    let container;
358    let inner_sticker;
359
360    let container_height;
361    let container_offsetTop;
362
363    let elemParent_offsetTop;
364
365    let window_height;
366
367    let options_top;
368    let options_bottom;
369
370    let stick_top;
371    let stick_bottom;
372
373    let top_limit;
374    let bottom_limit;
375
376    let largerSticky;
377    let sticky_height;
378    let sticky_offsetTop;
379
380    let calcContainerHeight;
381    let calcStickyHeight;
382
383    const calcSticky = () => {
384      // get/set element styles
385      Sticky.css = getStickyCss(elem);
386
387      // init or reinit spacer
388      Spacer.init();
389
390      // check if referring element is document
391      stickTo_document = STICKY_OPTIONS.stickTo && (STICKY_OPTIONS.stickTo === 'document'
392        || (STICKY_OPTIONS.stickTo.nodeType && STICKY_OPTIONS.stickTo.nodeType === 9)
393        || (typeof STICKY_OPTIONS.stickTo === 'object' && STICKY_OPTIONS.stickTo instanceof (typeof HTMLDocument !== 'undefined' ? HTMLDocument : Document)))
394      ? true : false;
395
396      // select referred container
397      container = STICKY_OPTIONS.stickTo
398        ? stickTo_document
399          ? document
400          : Helpers.getElement(STICKY_OPTIONS.stickTo)
401        : elemParent;
402
403      // get sticky height
404      calcStickyHeight = () => {
405        const height = elem.offsetHeight + (parseInt(Sticky.css.marginTop) || 0) + (parseInt(Sticky.css.marginBottom) || 0);
406        const h_diff = (sticky_height || 0) - height;
407
408        if (h_diff >= -1 && h_diff <= 1) {
409          // sometimes element height changes by 1px when it get fixed position, so don't return new value
410          return sticky_height;
411        }
412        else {
413          return height;
414        }
415      };
416
417      sticky_height = calcStickyHeight();
418
419      // get container height
420      calcContainerHeight = () => {
421        return !stickTo_document ? container.offsetHeight : Math.max(document.documentElement.clientHeight, document.body.scrollHeight, document.documentElement.scrollHeight, document.body.offsetHeight, document.documentElement.offsetHeight);
422      };
423
424      container_height = calcContainerHeight();
425
426      container_offsetTop = !stickTo_document ? Helpers.offset(container).top : 0;
427      elemParent_offsetTop = !STICKY_OPTIONS.stickTo
428        ? container_offsetTop // parent is container
429        : !stickTo_document
430          ? Helpers.offset(elemParent).top
431          : 0;
432      window_height = window.innerHeight;
433      sticky_offsetTop = elem.offsetTop - (parseInt(Sticky.css.marginTop) || 0);
434
435      // get inner sticker element
436      inner_sticker = Helpers.getElement(STICKY_OPTIONS.innerSticker);
437
438      // top
439      options_top = isNaN(STICKY_OPTIONS.top) && STICKY_OPTIONS.top.indexOf('%') > -1
440        ? (parseFloat(STICKY_OPTIONS.top) / 100) * window_height
441        : STICKY_OPTIONS.top;
442
443      // bottom
444      options_bottom = isNaN(STICKY_OPTIONS.bottom) && STICKY_OPTIONS.bottom.indexOf('%') > -1
445        ? (parseFloat(STICKY_OPTIONS.bottom) / 100) * window_height
446        : STICKY_OPTIONS.bottom;
447
448      // calculate sticky breakpoints
449      stick_top = inner_sticker
450        ? inner_sticker.offsetTop
451        : STICKY_OPTIONS.innerTop
452          ? STICKY_OPTIONS.innerTop
453          : 0;
454
455      stick_bottom = isNaN(STICKY_OPTIONS.bottomEnd) && STICKY_OPTIONS.bottomEnd.indexOf('%') > -1
456        ? (parseFloat(STICKY_OPTIONS.bottomEnd) / 100) * window_height
457        : STICKY_OPTIONS.bottomEnd;
458
459      top_limit = container_offsetTop - options_top + stick_top + sticky_offsetTop;
460    };
461
462    // store scroll position so we can determine scroll direction
463    let last_pos = window.pageYOffset || document.documentElement.scrollTop;
464    let diff_y = 0;
465    let scroll_dir;
466
467    const runSticky = () => {
468      // always calculate sticky and container height in case of DOM change
469      sticky_height = calcStickyHeight();
470      container_height = calcContainerHeight();
471
472      bottom_limit = container_offsetTop + container_height - options_top - stick_bottom;
473
474      // check if sticky is bigger than container
475      largerSticky = sticky_height > window_height;
476
477      const offset_top = window.pageYOffset || document.documentElement.scrollTop;
478      const sticky_top = Helpers.offset(elem).top;
479      const sticky_window_top = sticky_top - offset_top;
480      let bottom_distance;
481
482      // get scroll direction
483      scroll_dir = offset_top < last_pos ? 'up' : 'down';
484      diff_y = offset_top - last_pos;
485      last_pos = offset_top;
486
487      if (offset_top > top_limit) {
488        // http://geek-and-poke.com/geekandpoke/2012/7/27/simply-explained.html
489        if (bottom_limit + options_top + (largerSticky ? options_bottom : 0) - (STICKY_OPTIONS.followScroll && largerSticky ? 0 : options_top) <= offset_top + sticky_height - stick_top - ((sticky_height - stick_top > window_height - (top_limit - stick_top) && STICKY_OPTIONS.followScroll) ? (((bottom_distance = sticky_height - window_height - stick_top) > 0) ? bottom_distance : 0) : 0)) { // bottom reached end
490          Sticky.release({
491            position: 'absolute',
492            //top: bottom_limit - sticky_height - top_limit + stick_top + sticky_offsetTop
493            bottom: elemParent_offsetTop + elemParent.offsetHeight - bottom_limit - options_top
494          });
495        }
496        else if (largerSticky && STICKY_OPTIONS.followScroll) { // sticky is bigger than container and follows scroll
497          if (scroll_dir === 'down') { // scroll down
498            if (sticky_window_top + sticky_height + options_bottom <= window_height + .9) { // stick on bottom
499              // fix subpixel precision with adding .9 pixels
500              Sticky.stick({
501                //top: window_height - sticky_height - options_bottom
502                bottom: options_bottom
503              });
504            }
505            else if (Sticky.position === 'fixed') { // bottom reached window bottom
506              Sticky.release({
507                position: 'absolute',
508                top: sticky_top - options_top - top_limit - diff_y + stick_top
509              });
510            }
511          }
512          else { // scroll up
513            if (Math.ceil(sticky_window_top + stick_top) < 0 && Sticky.position === 'fixed') { // top reached window top
514              Sticky.release({
515                position: 'absolute',
516                top: sticky_top - options_top - top_limit + stick_top - diff_y
517              });
518            }
519            else if (sticky_top >= offset_top + options_top - stick_top) { // stick on top
520              Sticky.stick({
521                top: options_top - stick_top
522              });
523            }
524          }
525        }
526        else { // stick on top
527          Sticky.stick({
528            top: options_top - stick_top
529          });
530        }
531      }
532      else { // starting point
533        Sticky.release({
534          stop: true
535        });
536      }
537    };
538
539    let scrollAttached = false;
540    let resizeAttached = false;
541
542    const disableSticky = () => {
543      if (scrollAttached) {
544        // detach sticky from scroll
545        window.removeEventListener('scroll', runSticky, Helpers.supportsPassive);
546
547        // sticky is not attached to scroll anymore
548        scrollAttached = false;
549      }
550    };
551
552    const initSticky = () => {
553      // check if element or it's parents are visible
554      if (elem.offsetParent === null || Helpers.getStyle(elem, 'display') === 'none') {
555        disableSticky();
556        return;
557      }
558
559      // calculate stuff
560      calcSticky();
561
562      // check if sticky is bigger than reffering container
563      if (sticky_height > container_height) {
564        disableSticky();
565        return;
566      }
567
568      // run
569      runSticky();
570
571      if (!scrollAttached) {
572        // attach sticky to scroll
573        window.addEventListener('scroll', runSticky, Helpers.supportsPassive);
574
575        // sticky is attached to scroll
576        scrollAttached = true;
577      }
578    };
579
580    const resetSticky = () => {
581      // remove inline styles
582      elem.style.position = '';
583      elem.style.left = '';
584      elem.style.top = '';
585      elem.style.bottom = '';
586      elem.style.width = '';
587
588      // remove sticky class
589      if (elem.classList) {
590        elem.classList.remove(STICKY_OPTIONS.stickyClass);
591      }
592      else {
593        elem.className = elem.className.replace(new RegExp('(^|\\b)' + STICKY_OPTIONS.stickyClass.split(' ').join('|') + '(\\b|$)', 'gi'), ' ');
594      }
595
596      // reset sticky object data
597      Sticky.css = {};
598      Sticky.position = null;
599
600      // remove spacer
601      if (Spacer.isAttached === true) {
602        Spacer.detach();
603      }
604    };
605
606    const reinitSticky = () => {
607      resetSticky();
608      applyQueries();
609
610      if (isDisabled()) {
611        disableSticky();
612        return;
613      }
614
615      // restart sticky
616      initSticky();
617    };
618
619    const resizeSticky = () => {
620      // fire 'beforeResize' event
621      if (STICKY_OPTIONS.onBeforeResize) {
622        STICKY_OPTIONS.onBeforeResize.call(elem, Object.assign({}, STICKY_OPTIONS));
623      }
624
625      // reinit sticky
626      reinitSticky();
627
628      // fire 'resize' event
629      if (STICKY_OPTIONS.onResize) {
630        STICKY_OPTIONS.onResize.call(elem, Object.assign({}, STICKY_OPTIONS));
631      }
632    };
633
634    const resize_cb = !STICKY_OPTIONS.resizeDebounce ? resizeSticky : Helpers.debounce(resizeSticky, STICKY_OPTIONS.resizeDebounce);
635
636    // Method for updating options
637    const Update = (options) => {
638      setOptions(options);
639
640      // also update user settings
641      userSettings = Object.assign({}, userSettings, options || {});
642
643      reinitSticky();
644    };
645
646    const Detach = () => {
647      // detach resize reinit
648      if (resizeAttached) {
649        window.removeEventListener('resize', resize_cb, Helpers.supportsPassive);
650        resizeAttached = false;
651      }
652
653      disableSticky();
654    };
655
656    const Destroy = () => {
657      Detach();
658      resetSticky();
659    };
660
661    const Attach = () => {
662      // attach resize reinit
663      if (!resizeAttached) {
664        window.addEventListener('resize', resize_cb, Helpers.supportsPassive);
665        resizeAttached = true;
666      }
667
668      applyQueries();
669
670      if (isDisabled()) {
671        disableSticky();
672        return;
673      }
674
675      initSticky();
676    };
677
678    this.options = getOptions;
679    this.refresh = reinitSticky;
680    this.update = Update;
681    this.attach = Attach;
682    this.detach = Detach;
683    this.destroy = Destroy;
684
685    // jQuery methods
686    this.triggerMethod = (method, options) => {
687      if (typeof this[method] === 'function') {
688        this[method](options);
689      }
690    };
691
692    this.reinit = () => {
693      deprecated('reinit', 'refresh', 'method');
694      reinitSticky();
695    };
696
697    // init settings
698    setOptions(userSettings);
699
700    // start sticky
701    Attach();
702
703    // reinit on complete page load
704    window.addEventListener('load', reinitSticky);
705  };
706
707  // jQuery Plugin
708  if (typeof window.jQuery !== 'undefined') {
709    const $ = window.jQuery;
710    const namespace = 'hcSticky';
711
712    $.fn.extend({
713      hcSticky: function(args, update) {
714        // check if selected element exist
715        if (!this.length) return this;
716
717        // we need to return options
718        if (args === 'options') {
719          return $.data(this.get(0), namespace).options();
720        }
721
722        return this.each(function() {
723          let instance = $.data(this, namespace);
724
725          if (instance) {
726            // already created, trigger method
727            instance.triggerMethod(args, update);
728          }
729          else {
730            // create new instance
731            instance = new hcSticky(this, args);
732            $.data(this, namespace, instance);
733          }
734        });
735      }
736    });
737  }
738
739  // browser global
740  window.hcSticky = window.hcSticky || hcSticky;
741
742  return hcSticky;
743});

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.