[ Index ]

PHP Cross Reference of Joomla 4.2.2 documentation

title

Body

[close]

/media/vendor/bootstrap/js/ -> scrollspy.js (source)

   1  import { E as EventHandler, S as SelectorEngine, d as defineJQueryPlugin, B as BaseComponent, f as getSelectorFromElement, M as Manipulator, h as getElement, a as typeCheckConfig } from './dom.js?5.1.3';
   2  
   3  /**
   4   * --------------------------------------------------------------------------
   5   * Bootstrap (v5.1.3): scrollspy.js
   6   * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
   7   * --------------------------------------------------------------------------
   8   */
   9  /**
  10   * ------------------------------------------------------------------------
  11   * Constants
  12   * ------------------------------------------------------------------------
  13   */
  14  
  15  const NAME = 'scrollspy';
  16  const DATA_KEY = 'bs.scrollspy';
  17  const EVENT_KEY = `.$DATA_KEY}`;
  18  const DATA_API_KEY = '.data-api';
  19  const Default = {
  20    offset: 10,
  21    method: 'auto',
  22    target: ''
  23  };
  24  const DefaultType = {
  25    offset: 'number',
  26    method: 'string',
  27    target: '(string|element)'
  28  };
  29  const EVENT_ACTIVATE = `activate$EVENT_KEY}`;
  30  const EVENT_SCROLL = `scroll$EVENT_KEY}`;
  31  const EVENT_LOAD_DATA_API = `load$EVENT_KEY}$DATA_API_KEY}`;
  32  const CLASS_NAME_DROPDOWN_ITEM = 'dropdown-item';
  33  const CLASS_NAME_ACTIVE = 'active';
  34  const SELECTOR_DATA_SPY = '[data-bs-spy="scroll"]';
  35  const SELECTOR_NAV_LIST_GROUP = '.nav, .list-group';
  36  const SELECTOR_NAV_LINKS = '.nav-link';
  37  const SELECTOR_NAV_ITEMS = '.nav-item';
  38  const SELECTOR_LIST_ITEMS = '.list-group-item';
  39  const SELECTOR_LINK_ITEMS = `$SELECTOR_NAV_LINKS}, $SELECTOR_LIST_ITEMS}, .$CLASS_NAME_DROPDOWN_ITEM}`;
  40  const SELECTOR_DROPDOWN = '.dropdown';
  41  const SELECTOR_DROPDOWN_TOGGLE = '.dropdown-toggle';
  42  const METHOD_OFFSET = 'offset';
  43  const METHOD_POSITION = 'position';
  44  /**
  45   * ------------------------------------------------------------------------
  46   * Class Definition
  47   * ------------------------------------------------------------------------
  48   */
  49  
  50  class ScrollSpy extends BaseComponent {
  51    constructor(element, config) {
  52      super(element);
  53      this._scrollElement = this._element.tagName === 'BODY' ? window : this._element;
  54      this._config = this._getConfig(config);
  55      this._offsets = [];
  56      this._targets = [];
  57      this._activeTarget = null;
  58      this._scrollHeight = 0;
  59      EventHandler.on(this._scrollElement, EVENT_SCROLL, () => this._process());
  60      this.refresh();
  61  
  62      this._process();
  63    } // Getters
  64  
  65  
  66    static get Default() {
  67      return Default;
  68    }
  69  
  70    static get NAME() {
  71      return NAME;
  72    } // Public
  73  
  74  
  75    refresh() {
  76      const autoMethod = this._scrollElement === this._scrollElement.window ? METHOD_OFFSET : METHOD_POSITION;
  77      const offsetMethod = this._config.method === 'auto' ? autoMethod : this._config.method;
  78      const offsetBase = offsetMethod === METHOD_POSITION ? this._getScrollTop() : 0;
  79      this._offsets = [];
  80      this._targets = [];
  81      this._scrollHeight = this._getScrollHeight();
  82      const targets = SelectorEngine.find(SELECTOR_LINK_ITEMS, this._config.target);
  83      targets.map(element => {
  84        const targetSelector = getSelectorFromElement(element);
  85        const target = targetSelector ? SelectorEngine.findOne(targetSelector) : null;
  86  
  87        if (target) {
  88          const targetBCR = target.getBoundingClientRect();
  89  
  90          if (targetBCR.width || targetBCR.height) {
  91            return [Manipulator[offsetMethod](target).top + offsetBase, targetSelector];
  92          }
  93        }
  94  
  95        return null;
  96      }).filter(item => item).sort((a, b) => a[0] - b[0]).forEach(item => {
  97        this._offsets.push(item[0]);
  98  
  99        this._targets.push(item[1]);
 100      });
 101    }
 102  
 103    dispose() {
 104      EventHandler.off(this._scrollElement, EVENT_KEY);
 105      super.dispose();
 106    } // Private
 107  
 108  
 109    _getConfig(config) {
 110      config = { ...Default,
 111        ...Manipulator.getDataAttributes(this._element),
 112        ...(typeof config === 'object' && config ? config : {})
 113      };
 114      config.target = getElement(config.target) || document.documentElement;
 115      typeCheckConfig(NAME, config, DefaultType);
 116      return config;
 117    }
 118  
 119    _getScrollTop() {
 120      return this._scrollElement === window ? this._scrollElement.pageYOffset : this._scrollElement.scrollTop;
 121    }
 122  
 123    _getScrollHeight() {
 124      return this._scrollElement.scrollHeight || Math.max(document.body.scrollHeight, document.documentElement.scrollHeight);
 125    }
 126  
 127    _getOffsetHeight() {
 128      return this._scrollElement === window ? window.innerHeight : this._scrollElement.getBoundingClientRect().height;
 129    }
 130  
 131    _process() {
 132      const scrollTop = this._getScrollTop() + this._config.offset;
 133  
 134      const scrollHeight = this._getScrollHeight();
 135  
 136      const maxScroll = this._config.offset + scrollHeight - this._getOffsetHeight();
 137  
 138      if (this._scrollHeight !== scrollHeight) {
 139        this.refresh();
 140      }
 141  
 142      if (scrollTop >= maxScroll) {
 143        const target = this._targets[this._targets.length - 1];
 144  
 145        if (this._activeTarget !== target) {
 146          this._activate(target);
 147        }
 148  
 149        return;
 150      }
 151  
 152      if (this._activeTarget && scrollTop < this._offsets[0] && this._offsets[0] > 0) {
 153        this._activeTarget = null;
 154  
 155        this._clear();
 156  
 157        return;
 158      }
 159  
 160      for (let i = this._offsets.length; i--;) {
 161        const isActiveTarget = this._activeTarget !== this._targets[i] && scrollTop >= this._offsets[i] && (typeof this._offsets[i + 1] === 'undefined' || scrollTop < this._offsets[i + 1]);
 162  
 163        if (isActiveTarget) {
 164          this._activate(this._targets[i]);
 165        }
 166      }
 167    }
 168  
 169    _activate(target) {
 170      this._activeTarget = target;
 171  
 172      this._clear();
 173  
 174      const queries = SELECTOR_LINK_ITEMS.split(',').map(selector => `$selector}[data-bs-target="$target}"],$selector}[href="$target}"]`);
 175      const link = SelectorEngine.findOne(queries.join(','), this._config.target);
 176      link.classList.add(CLASS_NAME_ACTIVE);
 177  
 178      if (link.classList.contains(CLASS_NAME_DROPDOWN_ITEM)) {
 179        SelectorEngine.findOne(SELECTOR_DROPDOWN_TOGGLE, link.closest(SELECTOR_DROPDOWN)).classList.add(CLASS_NAME_ACTIVE);
 180      } else {
 181        SelectorEngine.parents(link, SELECTOR_NAV_LIST_GROUP).forEach(listGroup => {
 182          // Set triggered links parents as active
 183          // With both <ul> and <nav> markup a parent is the previous sibling of any nav ancestor
 184          SelectorEngine.prev(listGroup, `$SELECTOR_NAV_LINKS}, $SELECTOR_LIST_ITEMS}`).forEach(item => item.classList.add(CLASS_NAME_ACTIVE)); // Handle special case when .nav-link is inside .nav-item
 185  
 186          SelectorEngine.prev(listGroup, SELECTOR_NAV_ITEMS).forEach(navItem => {
 187            SelectorEngine.children(navItem, SELECTOR_NAV_LINKS).forEach(item => item.classList.add(CLASS_NAME_ACTIVE));
 188          });
 189        });
 190      }
 191  
 192      EventHandler.trigger(this._scrollElement, EVENT_ACTIVATE, {
 193        relatedTarget: target
 194      });
 195    }
 196  
 197    _clear() {
 198      SelectorEngine.find(SELECTOR_LINK_ITEMS, this._config.target).filter(node => node.classList.contains(CLASS_NAME_ACTIVE)).forEach(node => node.classList.remove(CLASS_NAME_ACTIVE));
 199    } // Static
 200  
 201  
 202    static jQueryInterface(config) {
 203      return this.each(function () {
 204        const data = ScrollSpy.getOrCreateInstance(this, config);
 205  
 206        if (typeof config !== 'string') {
 207          return;
 208        }
 209  
 210        if (typeof data[config] === 'undefined') {
 211          throw new TypeError(`No method named "$config}"`);
 212        }
 213  
 214        data[config]();
 215      });
 216    }
 217  
 218  }
 219  /**
 220   * ------------------------------------------------------------------------
 221   * Data Api implementation
 222   * ------------------------------------------------------------------------
 223   */
 224  
 225  
 226  EventHandler.on(window, EVENT_LOAD_DATA_API, () => {
 227    SelectorEngine.find(SELECTOR_DATA_SPY).forEach(spy => new ScrollSpy(spy));
 228  });
 229  /**
 230   * ------------------------------------------------------------------------
 231   * jQuery
 232   * ------------------------------------------------------------------------
 233   * add .ScrollSpy to jQuery only if jQuery is present
 234   */
 235  
 236  defineJQueryPlugin(ScrollSpy);
 237  
 238  window.bootstrap = window.bootstrap || {};
 239  window.bootstrap.Scrollspy = ScrollSpy;
 240  
 241  if (Joomla && Joomla.getOptions) {
 242    // Get the elements/configurations from the PHP
 243    const scrollspys = Joomla.getOptions('bootstrap.scrollspy'); // Initialise the elements
 244  
 245    if (typeof scrollspys === 'object' && scrollspys !== null) {
 246      Object.keys(scrollspys).forEach(scrollspy => {
 247        const opt = scrollspys[scrollspy];
 248        const options = {
 249          offset: opt.offset ? opt.offset : 10,
 250          method: opt.method ? opt.method : 'auto'
 251        };
 252  
 253        if (opt.target) {
 254          options.target = opt.target;
 255        }
 256  
 257        const elements = Array.from(document.querySelectorAll(scrollspy));
 258  
 259        if (elements.length) {
 260          elements.map(el => new window.bootstrap.Scrollspy(el, options));
 261        }
 262      });
 263    }
 264  }
 265  
 266  export { ScrollSpy as S };


Generated: Wed Sep 7 05:41:13 2022 Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer