[ Index ] |
PHP Cross Reference of Joomla 4.2.2 documentation |
[Summary view] [Print] [Text view]
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 };
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Wed Sep 7 05:41:13 2022 | Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer |