[ Index ]

PHP Cross Reference of Joomla 4.2.2 documentation

title

Body

[close]

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

   1  import { E as EventHandler, S as SelectorEngine, d as defineJQueryPlugin, B as BaseComponent, i as isVisible, t as triggerTransitionEnd, M as Manipulator, a as typeCheckConfig, g as getNextActiveElement, r as reflow, b as isRTL, c as getElementFromSelector } from './dom.js?5.1.3';
   2  
   3  /**
   4   * --------------------------------------------------------------------------
   5   * Bootstrap (v5.1.3): carousel.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 = 'carousel';
  16  const DATA_KEY = 'bs.carousel';
  17  const EVENT_KEY = `.$DATA_KEY}`;
  18  const DATA_API_KEY = '.data-api';
  19  const ARROW_LEFT_KEY = 'ArrowLeft';
  20  const ARROW_RIGHT_KEY = 'ArrowRight';
  21  const TOUCHEVENT_COMPAT_WAIT = 500; // Time for mouse compat events to fire after touch
  22  
  23  const SWIPE_THRESHOLD = 40;
  24  const Default = {
  25    interval: 5000,
  26    keyboard: true,
  27    slide: false,
  28    pause: 'hover',
  29    wrap: true,
  30    touch: true
  31  };
  32  const DefaultType = {
  33    interval: '(number|boolean)',
  34    keyboard: 'boolean',
  35    slide: '(boolean|string)',
  36    pause: '(string|boolean)',
  37    wrap: 'boolean',
  38    touch: 'boolean'
  39  };
  40  const ORDER_NEXT = 'next';
  41  const ORDER_PREV = 'prev';
  42  const DIRECTION_LEFT = 'left';
  43  const DIRECTION_RIGHT = 'right';
  44  const KEY_TO_DIRECTION = {
  45    [ARROW_LEFT_KEY]: DIRECTION_RIGHT,
  46    [ARROW_RIGHT_KEY]: DIRECTION_LEFT
  47  };
  48  const EVENT_SLIDE = `slide$EVENT_KEY}`;
  49  const EVENT_SLID = `slid$EVENT_KEY}`;
  50  const EVENT_KEYDOWN = `keydown$EVENT_KEY}`;
  51  const EVENT_MOUSEENTER = `mouseenter$EVENT_KEY}`;
  52  const EVENT_MOUSELEAVE = `mouseleave$EVENT_KEY}`;
  53  const EVENT_TOUCHSTART = `touchstart$EVENT_KEY}`;
  54  const EVENT_TOUCHMOVE = `touchmove$EVENT_KEY}`;
  55  const EVENT_TOUCHEND = `touchend$EVENT_KEY}`;
  56  const EVENT_POINTERDOWN = `pointerdown$EVENT_KEY}`;
  57  const EVENT_POINTERUP = `pointerup$EVENT_KEY}`;
  58  const EVENT_DRAG_START = `dragstart$EVENT_KEY}`;
  59  const EVENT_LOAD_DATA_API = `load$EVENT_KEY}$DATA_API_KEY}`;
  60  const EVENT_CLICK_DATA_API = `click$EVENT_KEY}$DATA_API_KEY}`;
  61  const CLASS_NAME_CAROUSEL = 'carousel';
  62  const CLASS_NAME_ACTIVE = 'active';
  63  const CLASS_NAME_SLIDE = 'slide';
  64  const CLASS_NAME_END = 'carousel-item-end';
  65  const CLASS_NAME_START = 'carousel-item-start';
  66  const CLASS_NAME_NEXT = 'carousel-item-next';
  67  const CLASS_NAME_PREV = 'carousel-item-prev';
  68  const CLASS_NAME_POINTER_EVENT = 'pointer-event';
  69  const SELECTOR_ACTIVE = '.active';
  70  const SELECTOR_ACTIVE_ITEM = '.active.carousel-item';
  71  const SELECTOR_ITEM = '.carousel-item';
  72  const SELECTOR_ITEM_IMG = '.carousel-item img';
  73  const SELECTOR_NEXT_PREV = '.carousel-item-next, .carousel-item-prev';
  74  const SELECTOR_INDICATORS = '.carousel-indicators';
  75  const SELECTOR_INDICATOR = '[data-bs-target]';
  76  const SELECTOR_DATA_SLIDE = '[data-bs-slide], [data-bs-slide-to]';
  77  const SELECTOR_DATA_RIDE = '[data-bs-ride="carousel"]';
  78  const POINTER_TYPE_TOUCH = 'touch';
  79  const POINTER_TYPE_PEN = 'pen';
  80  /**
  81   * ------------------------------------------------------------------------
  82   * Class Definition
  83   * ------------------------------------------------------------------------
  84   */
  85  
  86  class Carousel extends BaseComponent {
  87    constructor(element, config) {
  88      super(element);
  89      this._items = null;
  90      this._interval = null;
  91      this._activeElement = null;
  92      this._isPaused = false;
  93      this._isSliding = false;
  94      this.touchTimeout = null;
  95      this.touchStartX = 0;
  96      this.touchDeltaX = 0;
  97      this._config = this._getConfig(config);
  98      this._indicatorsElement = SelectorEngine.findOne(SELECTOR_INDICATORS, this._element);
  99      this._touchSupported = 'ontouchstart' in document.documentElement || navigator.maxTouchPoints > 0;
 100      this._pointerEvent = Boolean(window.PointerEvent);
 101  
 102      this._addEventListeners();
 103    } // Getters
 104  
 105  
 106    static get Default() {
 107      return Default;
 108    }
 109  
 110    static get NAME() {
 111      return NAME;
 112    } // Public
 113  
 114  
 115    next() {
 116      this._slide(ORDER_NEXT);
 117    }
 118  
 119    nextWhenVisible() {
 120      // Don't call next when the page isn't visible
 121      // or the carousel or its parent isn't visible
 122      if (!document.hidden && isVisible(this._element)) {
 123        this.next();
 124      }
 125    }
 126  
 127    prev() {
 128      this._slide(ORDER_PREV);
 129    }
 130  
 131    pause(event) {
 132      if (!event) {
 133        this._isPaused = true;
 134      }
 135  
 136      if (SelectorEngine.findOne(SELECTOR_NEXT_PREV, this._element)) {
 137        triggerTransitionEnd(this._element);
 138        this.cycle(true);
 139      }
 140  
 141      clearInterval(this._interval);
 142      this._interval = null;
 143    }
 144  
 145    cycle(event) {
 146      if (!event) {
 147        this._isPaused = false;
 148      }
 149  
 150      if (this._interval) {
 151        clearInterval(this._interval);
 152        this._interval = null;
 153      }
 154  
 155      if (this._config && this._config.interval && !this._isPaused) {
 156        this._updateInterval();
 157  
 158        this._interval = setInterval((document.visibilityState ? this.nextWhenVisible : this.next).bind(this), this._config.interval);
 159      }
 160    }
 161  
 162    to(index) {
 163      this._activeElement = SelectorEngine.findOne(SELECTOR_ACTIVE_ITEM, this._element);
 164  
 165      const activeIndex = this._getItemIndex(this._activeElement);
 166  
 167      if (index > this._items.length - 1 || index < 0) {
 168        return;
 169      }
 170  
 171      if (this._isSliding) {
 172        EventHandler.one(this._element, EVENT_SLID, () => this.to(index));
 173        return;
 174      }
 175  
 176      if (activeIndex === index) {
 177        this.pause();
 178        this.cycle();
 179        return;
 180      }
 181  
 182      const order = index > activeIndex ? ORDER_NEXT : ORDER_PREV;
 183  
 184      this._slide(order, this._items[index]);
 185    } // Private
 186  
 187  
 188    _getConfig(config) {
 189      config = { ...Default,
 190        ...Manipulator.getDataAttributes(this._element),
 191        ...(typeof config === 'object' ? config : {})
 192      };
 193      typeCheckConfig(NAME, config, DefaultType);
 194      return config;
 195    }
 196  
 197    _handleSwipe() {
 198      const absDeltax = Math.abs(this.touchDeltaX);
 199  
 200      if (absDeltax <= SWIPE_THRESHOLD) {
 201        return;
 202      }
 203  
 204      const direction = absDeltax / this.touchDeltaX;
 205      this.touchDeltaX = 0;
 206  
 207      if (!direction) {
 208        return;
 209      }
 210  
 211      this._slide(direction > 0 ? DIRECTION_RIGHT : DIRECTION_LEFT);
 212    }
 213  
 214    _addEventListeners() {
 215      if (this._config.keyboard) {
 216        EventHandler.on(this._element, EVENT_KEYDOWN, event => this._keydown(event));
 217      }
 218  
 219      if (this._config.pause === 'hover') {
 220        EventHandler.on(this._element, EVENT_MOUSEENTER, event => this.pause(event));
 221        EventHandler.on(this._element, EVENT_MOUSELEAVE, event => this.cycle(event));
 222      }
 223  
 224      if (this._config.touch && this._touchSupported) {
 225        this._addTouchEventListeners();
 226      }
 227    }
 228  
 229    _addTouchEventListeners() {
 230      const hasPointerPenTouch = event => {
 231        return this._pointerEvent && (event.pointerType === POINTER_TYPE_PEN || event.pointerType === POINTER_TYPE_TOUCH);
 232      };
 233  
 234      const start = event => {
 235        if (hasPointerPenTouch(event)) {
 236          this.touchStartX = event.clientX;
 237        } else if (!this._pointerEvent) {
 238          this.touchStartX = event.touches[0].clientX;
 239        }
 240      };
 241  
 242      const move = event => {
 243        // ensure swiping with one touch and not pinching
 244        this.touchDeltaX = event.touches && event.touches.length > 1 ? 0 : event.touches[0].clientX - this.touchStartX;
 245      };
 246  
 247      const end = event => {
 248        if (hasPointerPenTouch(event)) {
 249          this.touchDeltaX = event.clientX - this.touchStartX;
 250        }
 251  
 252        this._handleSwipe();
 253  
 254        if (this._config.pause === 'hover') {
 255          // If it's a touch-enabled device, mouseenter/leave are fired as
 256          // part of the mouse compatibility events on first tap - the carousel
 257          // would stop cycling until user tapped out of it;
 258          // here, we listen for touchend, explicitly pause the carousel
 259          // (as if it's the second time we tap on it, mouseenter compat event
 260          // is NOT fired) and after a timeout (to allow for mouse compatibility
 261          // events to fire) we explicitly restart cycling
 262          this.pause();
 263  
 264          if (this.touchTimeout) {
 265            clearTimeout(this.touchTimeout);
 266          }
 267  
 268          this.touchTimeout = setTimeout(event => this.cycle(event), TOUCHEVENT_COMPAT_WAIT + this._config.interval);
 269        }
 270      };
 271  
 272      SelectorEngine.find(SELECTOR_ITEM_IMG, this._element).forEach(itemImg => {
 273        EventHandler.on(itemImg, EVENT_DRAG_START, event => event.preventDefault());
 274      });
 275  
 276      if (this._pointerEvent) {
 277        EventHandler.on(this._element, EVENT_POINTERDOWN, event => start(event));
 278        EventHandler.on(this._element, EVENT_POINTERUP, event => end(event));
 279  
 280        this._element.classList.add(CLASS_NAME_POINTER_EVENT);
 281      } else {
 282        EventHandler.on(this._element, EVENT_TOUCHSTART, event => start(event));
 283        EventHandler.on(this._element, EVENT_TOUCHMOVE, event => move(event));
 284        EventHandler.on(this._element, EVENT_TOUCHEND, event => end(event));
 285      }
 286    }
 287  
 288    _keydown(event) {
 289      if (/input|textarea/i.test(event.target.tagName)) {
 290        return;
 291      }
 292  
 293      const direction = KEY_TO_DIRECTION[event.key];
 294  
 295      if (direction) {
 296        event.preventDefault();
 297  
 298        this._slide(direction);
 299      }
 300    }
 301  
 302    _getItemIndex(element) {
 303      this._items = element && element.parentNode ? SelectorEngine.find(SELECTOR_ITEM, element.parentNode) : [];
 304      return this._items.indexOf(element);
 305    }
 306  
 307    _getItemByOrder(order, activeElement) {
 308      const isNext = order === ORDER_NEXT;
 309      return getNextActiveElement(this._items, activeElement, isNext, this._config.wrap);
 310    }
 311  
 312    _triggerSlideEvent(relatedTarget, eventDirectionName) {
 313      const targetIndex = this._getItemIndex(relatedTarget);
 314  
 315      const fromIndex = this._getItemIndex(SelectorEngine.findOne(SELECTOR_ACTIVE_ITEM, this._element));
 316  
 317      return EventHandler.trigger(this._element, EVENT_SLIDE, {
 318        relatedTarget,
 319        direction: eventDirectionName,
 320        from: fromIndex,
 321        to: targetIndex
 322      });
 323    }
 324  
 325    _setActiveIndicatorElement(element) {
 326      if (this._indicatorsElement) {
 327        const activeIndicator = SelectorEngine.findOne(SELECTOR_ACTIVE, this._indicatorsElement);
 328        activeIndicator.classList.remove(CLASS_NAME_ACTIVE);
 329        activeIndicator.removeAttribute('aria-current');
 330        const indicators = SelectorEngine.find(SELECTOR_INDICATOR, this._indicatorsElement);
 331  
 332        for (let i = 0; i < indicators.length; i++) {
 333          if (Number.parseInt(indicators[i].getAttribute('data-bs-slide-to'), 10) === this._getItemIndex(element)) {
 334            indicators[i].classList.add(CLASS_NAME_ACTIVE);
 335            indicators[i].setAttribute('aria-current', 'true');
 336            break;
 337          }
 338        }
 339      }
 340    }
 341  
 342    _updateInterval() {
 343      const element = this._activeElement || SelectorEngine.findOne(SELECTOR_ACTIVE_ITEM, this._element);
 344  
 345      if (!element) {
 346        return;
 347      }
 348  
 349      const elementInterval = Number.parseInt(element.getAttribute('data-bs-interval'), 10);
 350  
 351      if (elementInterval) {
 352        this._config.defaultInterval = this._config.defaultInterval || this._config.interval;
 353        this._config.interval = elementInterval;
 354      } else {
 355        this._config.interval = this._config.defaultInterval || this._config.interval;
 356      }
 357    }
 358  
 359    _slide(directionOrOrder, element) {
 360      const order = this._directionToOrder(directionOrOrder);
 361  
 362      const activeElement = SelectorEngine.findOne(SELECTOR_ACTIVE_ITEM, this._element);
 363  
 364      const activeElementIndex = this._getItemIndex(activeElement);
 365  
 366      const nextElement = element || this._getItemByOrder(order, activeElement);
 367  
 368      const nextElementIndex = this._getItemIndex(nextElement);
 369  
 370      const isCycling = Boolean(this._interval);
 371      const isNext = order === ORDER_NEXT;
 372      const directionalClassName = isNext ? CLASS_NAME_START : CLASS_NAME_END;
 373      const orderClassName = isNext ? CLASS_NAME_NEXT : CLASS_NAME_PREV;
 374  
 375      const eventDirectionName = this._orderToDirection(order);
 376  
 377      if (nextElement && nextElement.classList.contains(CLASS_NAME_ACTIVE)) {
 378        this._isSliding = false;
 379        return;
 380      }
 381  
 382      if (this._isSliding) {
 383        return;
 384      }
 385  
 386      const slideEvent = this._triggerSlideEvent(nextElement, eventDirectionName);
 387  
 388      if (slideEvent.defaultPrevented) {
 389        return;
 390      }
 391  
 392      if (!activeElement || !nextElement) {
 393        // Some weirdness is happening, so we bail
 394        return;
 395      }
 396  
 397      this._isSliding = true;
 398  
 399      if (isCycling) {
 400        this.pause();
 401      }
 402  
 403      this._setActiveIndicatorElement(nextElement);
 404  
 405      this._activeElement = nextElement;
 406  
 407      const triggerSlidEvent = () => {
 408        EventHandler.trigger(this._element, EVENT_SLID, {
 409          relatedTarget: nextElement,
 410          direction: eventDirectionName,
 411          from: activeElementIndex,
 412          to: nextElementIndex
 413        });
 414      };
 415  
 416      if (this._element.classList.contains(CLASS_NAME_SLIDE)) {
 417        nextElement.classList.add(orderClassName);
 418        reflow(nextElement);
 419        activeElement.classList.add(directionalClassName);
 420        nextElement.classList.add(directionalClassName);
 421  
 422        const completeCallBack = () => {
 423          nextElement.classList.remove(directionalClassName, orderClassName);
 424          nextElement.classList.add(CLASS_NAME_ACTIVE);
 425          activeElement.classList.remove(CLASS_NAME_ACTIVE, orderClassName, directionalClassName);
 426          this._isSliding = false;
 427          setTimeout(triggerSlidEvent, 0);
 428        };
 429  
 430        this._queueCallback(completeCallBack, activeElement, true);
 431      } else {
 432        activeElement.classList.remove(CLASS_NAME_ACTIVE);
 433        nextElement.classList.add(CLASS_NAME_ACTIVE);
 434        this._isSliding = false;
 435        triggerSlidEvent();
 436      }
 437  
 438      if (isCycling) {
 439        this.cycle();
 440      }
 441    }
 442  
 443    _directionToOrder(direction) {
 444      if (![DIRECTION_RIGHT, DIRECTION_LEFT].includes(direction)) {
 445        return direction;
 446      }
 447  
 448      if (isRTL()) {
 449        return direction === DIRECTION_LEFT ? ORDER_PREV : ORDER_NEXT;
 450      }
 451  
 452      return direction === DIRECTION_LEFT ? ORDER_NEXT : ORDER_PREV;
 453    }
 454  
 455    _orderToDirection(order) {
 456      if (![ORDER_NEXT, ORDER_PREV].includes(order)) {
 457        return order;
 458      }
 459  
 460      if (isRTL()) {
 461        return order === ORDER_PREV ? DIRECTION_LEFT : DIRECTION_RIGHT;
 462      }
 463  
 464      return order === ORDER_PREV ? DIRECTION_RIGHT : DIRECTION_LEFT;
 465    } // Static
 466  
 467  
 468    static carouselInterface(element, config) {
 469      const data = Carousel.getOrCreateInstance(element, config);
 470      let {
 471        _config
 472      } = data;
 473  
 474      if (typeof config === 'object') {
 475        _config = { ..._config,
 476          ...config
 477        };
 478      }
 479  
 480      const action = typeof config === 'string' ? config : _config.slide;
 481  
 482      if (typeof config === 'number') {
 483        data.to(config);
 484      } else if (typeof action === 'string') {
 485        if (typeof data[action] === 'undefined') {
 486          throw new TypeError(`No method named "$action}"`);
 487        }
 488  
 489        data[action]();
 490      } else if (_config.interval && _config.ride) {
 491        data.pause();
 492        data.cycle();
 493      }
 494    }
 495  
 496    static jQueryInterface(config) {
 497      return this.each(function () {
 498        Carousel.carouselInterface(this, config);
 499      });
 500    }
 501  
 502    static dataApiClickHandler(event) {
 503      const target = getElementFromSelector(this);
 504  
 505      if (!target || !target.classList.contains(CLASS_NAME_CAROUSEL)) {
 506        return;
 507      }
 508  
 509      const config = { ...Manipulator.getDataAttributes(target),
 510        ...Manipulator.getDataAttributes(this)
 511      };
 512      const slideIndex = this.getAttribute('data-bs-slide-to');
 513  
 514      if (slideIndex) {
 515        config.interval = false;
 516      }
 517  
 518      Carousel.carouselInterface(target, config);
 519  
 520      if (slideIndex) {
 521        Carousel.getInstance(target).to(slideIndex);
 522      }
 523  
 524      event.preventDefault();
 525    }
 526  
 527  }
 528  /**
 529   * ------------------------------------------------------------------------
 530   * Data Api implementation
 531   * ------------------------------------------------------------------------
 532   */
 533  
 534  
 535  EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_SLIDE, Carousel.dataApiClickHandler);
 536  EventHandler.on(window, EVENT_LOAD_DATA_API, () => {
 537    const carousels = SelectorEngine.find(SELECTOR_DATA_RIDE);
 538  
 539    for (let i = 0, len = carousels.length; i < len; i++) {
 540      Carousel.carouselInterface(carousels[i], Carousel.getInstance(carousels[i]));
 541    }
 542  });
 543  /**
 544   * ------------------------------------------------------------------------
 545   * jQuery
 546   * ------------------------------------------------------------------------
 547   * add .Carousel to jQuery only if jQuery is present
 548   */
 549  
 550  defineJQueryPlugin(Carousel);
 551  
 552  window.bootstrap = window.bootstrap || {};
 553  window.bootstrap.Carousel = Carousel;
 554  
 555  if (Joomla && Joomla.getOptions) {
 556    // Get the elements/configurations from the PHP
 557    const carousels = Joomla.getOptions('bootstrap.carousel'); // Initialise the elements
 558  
 559    if (typeof carousels === 'object' && carousels !== null) {
 560      Object.keys(carousels).forEach(carousel => {
 561        const opt = carousels[carousel];
 562        const options = {
 563          interval: opt.interval ? opt.interval : 5000,
 564          keyboard: opt.keyboard ? opt.keyboard : true,
 565          pause: opt.pause ? opt.pause : 'hover',
 566          slide: opt.slide ? opt.slide : false,
 567          wrap: opt.wrap ? opt.wrap : true,
 568          touch: opt.touch ? opt.touch : true
 569        };
 570        const elements = Array.from(document.querySelectorAll(carousel));
 571  
 572        if (elements.length) {
 573          elements.map(el => new window.bootstrap.Carousel(el, options));
 574        }
 575      });
 576    }
 577  }
 578  
 579  export { Carousel as C };


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