UNPKG

devextreme

Version:

HTML5 JavaScript Component Suite for Responsive Web Development

1,049 lines (1,046 loc) • 40.2 kB
/** * DevExtreme (cjs/__internal/ui/gallery.js) * Version: 25.1.5 * Build date: Wed Sep 03 2025 * * Copyright (c) 2012 - 2025 Developer Express Inc. ALL RIGHTS RESERVED * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/ */ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _animation = require("../../common/core/animation"); var _translator = require("../../common/core/animation/translator"); var _click = require("../../common/core/events/click"); var _events_engine = _interopRequireDefault(require("../../common/core/events/core/events_engine")); var _swipeable = _interopRequireDefault(require("../../common/core/events/gesture/swipeable")); var _utils = require("../../common/core/events/utils"); var _visibility_change = require("../../common/core/events/visibility_change"); var _message = _interopRequireDefault(require("../../common/core/localization/message")); var _component_registrator = _interopRequireDefault(require("../../core/component_registrator")); var _devices = _interopRequireDefault(require("../../core/devices")); var _element = require("../../core/element"); var _renderer = _interopRequireDefault(require("../../core/renderer")); var _bindable_template = require("../../core/templates/bindable_template"); var _common = require("../../core/utils/common"); var _deferred = require("../../core/utils/deferred"); var _size = require("../../core/utils/size"); var _type = require("../../core/utils/type"); var _window = require("../../core/utils/window"); var _widget = _interopRequireDefault(require("../core/widget/widget")); var _collection_widget = _interopRequireDefault(require("../ui/collection/collection_widget.edit")); function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e } } function _extends() { return _extends = Object.assign ? Object.assign.bind() : function(n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) { ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]) } } return n }, _extends.apply(null, arguments) } const GALLERY_CLASS = "dx-gallery"; const GALLERY_INDICATOR_VISIBLE_CLASS = "dx-gallery-indicator-visible"; const GALLERY_WRAPPER_CLASS = "dx-gallery-wrapper"; const GALLERY_LOOP_CLASS = "dx-gallery-loop"; const GALLERY_ITEM_CONTAINER_CLASS = "dx-gallery-container"; const GALLERY_ACTIVE_CLASS = "dx-gallery-active"; const GALLERY_ITEM_CLASS = "dx-gallery-item"; const GALLERY_INVISIBLE_ITEM_CLASS = "dx-gallery-item-invisible"; const GALLERY_LOOP_ITEM_CLASS = "dx-gallery-item-loop"; const GALLERY_ITEM_SELECTOR = ".dx-gallery-item"; const GALLERY_ITEM_SELECTED_CLASS = "dx-gallery-item-selected"; const GALLERY_INDICATOR_CLASS = "dx-gallery-indicator"; const GALLERY_INDICATOR_ITEM_CLASS = "dx-gallery-indicator-item"; const GALLERY_INDICATOR_ITEM_SELECTOR = ".dx-gallery-indicator-item"; const GALLERY_INDICATOR_ITEM_SELECTED_CLASS = "dx-gallery-indicator-item-selected"; const ITEM_CONTENT_SELECTOR = ".dx-item-content"; const GALLERY_IMAGE_CLASS = "dx-gallery-item-image"; const GALLERY_ITEM_DATA_KEY = "dxGalleryItemData"; const MAX_CALC_ERROR = 1; class GalleryNavButton extends _widget.default { _supportedKeys() { return _extends({}, super._supportedKeys(), { pageUp: _common.noop, pageDown: _common.noop }) } _getDefaultOptions() { return _extends({}, super._getDefaultOptions(), { direction: "next", onClick: null, hoverStateEnabled: true, activeStateEnabled: true }) } _render() { super._render(); const $element = this.$element(); const eventName = (0, _utils.addNamespace)(_click.name, this.NAME); const { direction: direction } = this.option(); $element.addClass(`dx-gallery-nav-button-${direction}`); _events_engine.default.off($element, eventName); _events_engine.default.on($element, eventName, (e => { this._createActionByOption("onClick")({ event: e }) })) } _optionChanged(args) { switch (args.name) { case "onClick": case "direction": this._invalidate(); break; default: super._optionChanged(args) } } } class Gallery extends _collection_widget.default { _getDefaultOptions() { return _extends({}, super._getDefaultOptions(), { activeStateEnabled: false, animationDuration: 400, animationEnabled: true, loop: false, swipeEnabled: true, indicatorEnabled: true, showIndicator: true, selectedIndex: 0, slideshowDelay: 0, showNavButtons: false, wrapAround: false, stretchImages: false, loopItemFocus: false, selectOnFocus: true, selectionMode: "single", selectionRequired: true, selectByClick: false, _itemAttributes: { role: "option", "aria-label": _message.default.format("dxGallery-itemName") } }) } _defaultOptionsRules() { return [...super._defaultOptionsRules(), { device: () => "desktop" === _devices.default.real().deviceType && !_devices.default.isSimulator(), options: { focusStateEnabled: true } }] } _init() { super._init(); const { loop: loop } = this.option(); this._activeStateUnit = ".dx-gallery-item"; this.option("loopItemFocus", loop) } _initTemplates() { super._initTemplates(); this._templateManager.addDefaultTemplates({ item: new _bindable_template.BindableTemplate((($container, data) => { const $img = (0, _renderer.default)("<img>").addClass(GALLERY_IMAGE_CLASS); if ((0, _type.isPlainObject)(data)) { this._prepareDefaultItemTemplate(data, $container); $img.attr({ src: data.imageSrc, alt: data.imageAlt }).appendTo($container) } else { $img.attr("src", String(data)).appendTo($container) } }), ["imageSrc", "imageAlt", "text", "html"], this.option("integrationOptions.watchMethod")) }) } _dataSourceOptions() { return { paginate: false } } _itemContainer() { return this._$container } _itemClass() { return "dx-gallery-item" } _itemDataKey() { return "dxGalleryItemData" } _actualItemWidth() { const { wrapAround: wrapAround, stretchImages: stretchImages } = this.option(); if (stretchImages) { const itemPerPage = wrapAround ? this._itemsPerPage() + 1 : this._itemsPerPage(); return 1 / itemPerPage } if (wrapAround) { return this._itemPercentWidth() * this._itemsPerPage() / (this._itemsPerPage() + 1) } return this._itemPercentWidth() } _itemPercentWidth() { const elementWidth = (0, _size.getOuterWidth)(this.$element()); const { initialItemWidth: initialItemWidth } = this.option(); if (initialItemWidth && initialItemWidth <= elementWidth) { return initialItemWidth / elementWidth } return 1 } _itemsPerPage() { const itemsPerPage = (0, _window.hasWindow)() ? Math.floor(1 / this._itemPercentWidth()) : 1; return Math.min(itemsPerPage, this._itemsCount()) } _pagesCount() { return Math.ceil(this._itemsCount() / this._itemsPerPage()) } _itemsCount() { const { items: items = [] } = this.option(); return items.length } _offsetDirection() { const { rtlEnabled: rtlEnabled } = this.option(); return rtlEnabled ? -1 : 1 } _initMarkup() { this._renderWrapper(); this._renderItemsContainer(); this.$element().addClass("dx-gallery"); const { loop: loop } = this.option(); this.$element().toggleClass("dx-gallery-loop", loop); super._initMarkup(); const useListBoxRole = this._itemsCount() > 0; const ariaAttrs = { role: useListBoxRole ? "listbox" : void 0, label: "gallery" }; this.setAria(ariaAttrs) } _render() { this._renderDragHandler(); this._renderContainerPosition(); this._renderItemSizes(); this._renderItemPositions(); this._renderNavButtons(); this._renderIndicator(); this._renderSelectedItem(); this._renderItemVisibility(); this._renderUserInteraction(); this._setupSlideShow(); this._reviseDimensions(); super._render() } _dimensionChanged() { const { selectedIndex: selectedIndex = 0 } = this.option(); this._stopItemAnimations(); this._clearCacheWidth(); this._cloneDuplicateItems(); this._renderItemSizes(); this._renderItemPositions(); this._renderIndicator(); this._renderContainerPosition(this._calculateIndexOffset(selectedIndex), true); this._renderItemVisibility() } _renderDragHandler() { const eventName = (0, _utils.addNamespace)("dragstart", this.NAME); _events_engine.default.off(this.$element(), eventName); _events_engine.default.on(this.$element(), eventName, "img", (() => false)) } _renderWrapper() { if (this._$wrapper) { return } this._$wrapper = (0, _renderer.default)("<div>").addClass("dx-gallery-wrapper").appendTo(this.$element()) } _renderItems(items) { if (!(0, _window.hasWindow)()) { const { selectedIndex: selectedIndex = 0 } = this.option(); items = items.length > selectedIndex ? items.slice(selectedIndex, selectedIndex + 1) : items.slice(0, 1) } super._renderItems(items); this._loadNextPageIfNeeded() } _onItemTemplateRendered() { return () => { if (!Gallery._wasAnyItemTemplateRendered) { Gallery._wasAnyItemTemplateRendered = true; (0, _visibility_change.triggerResizeEvent)(this.$element()) } } } _renderItemsContainer() { if (this._$container) { return } this._$container = (0, _renderer.default)("<div>").addClass("dx-gallery-container").appendTo(this._$wrapper) } _cloneDuplicateItems() { const { loop: loop, items: items = [] } = this.option(); const itemsCount = items.length; if (!loop || !itemsCount) { return } this._getLoopedItems().remove(); const lastItemIndex = itemsCount - 1; const duplicateCount = Math.min(this._itemsPerPage(), itemsCount); const $items = this._getRealItems(); const $container = this._itemContainer(); for (let i = 0; i < duplicateCount; i += 1) { this._cloneItemForDuplicate($items[i], $container) } for (let i = 0; i < duplicateCount; i += 1) { this._cloneItemForDuplicate($items[lastItemIndex - i], $container) } } _cloneItemForDuplicate(item, $container) { if (item) { const $clonedItem = (0, _renderer.default)(item).clone(false).addClass("dx-gallery-item-loop").removeAttr("id").css("margin", 0).appendTo($container); this.setAria({ hidden: true }, $clonedItem) } } _getRealItems() { return this.$element().find(".dx-gallery-item:not(.dx-gallery-item-loop)") } _getLoopedItems() { return this.$element().find(".dx-gallery-item-loop") } _emptyMessageContainer() { return this._$wrapper } _renderItemSizes(startIndex) { let $items = this._itemElements(); const itemWidth = this._actualItemWidth(); if (void 0 !== startIndex) { $items = $items.slice(startIndex) } $items.each(((_index, element) => { (0, _size.setOuterWidth)((0, _renderer.default)(element), 100 * itemWidth + "%"); return true })) } _renderItemPositions() { const { rtlEnabled: rtlEnabled, wrapAround: wrapAround, selectedIndex: selectedIndex = 0 } = this.option(); const itemWidth = this._actualItemWidth(); const itemsCount = this._itemsCount(); const itemsPerPage = this._itemsPerPage(); const loopItemsCount = this.$element().find(".dx-gallery-item-loop").length; const lastItemDuplicateIndex = itemsCount + loopItemsCount - 1; const offsetRatio = wrapAround ? .5 : 0; const freeSpace = this._itemFreeSpace(); const isGapBetweenImages = !!freeSpace; const side = rtlEnabled ? "Right" : "Left"; this._itemElements().each(((index, item) => { let realIndex = index; const isLoopItem = (0, _renderer.default)(item).hasClass("dx-gallery-item-loop"); if (index > itemsCount + itemsPerPage - 1) { realIndex = lastItemDuplicateIndex - realIndex - itemsPerPage } if (!isLoopItem && 0 !== realIndex) { if (isGapBetweenImages) { (0, _renderer.default)(item).css(`margin${side}`, 100 * freeSpace + "%") } return true } const itemPosition = itemWidth * (realIndex + offsetRatio) + freeSpace * (realIndex + 1 - offsetRatio); const property = isLoopItem ? side.toLowerCase() : `margin${side}`; (0, _renderer.default)(item).css(property, 100 * itemPosition + "%"); return true })); this._relocateItems(selectedIndex, selectedIndex, true) } _itemFreeSpace() { const { wrapAround: wrapAround } = this.option(); const itemsPerPage = wrapAround ? this._itemsPerPage() + 1 : this._itemsPerPage(); return (1 - this._actualItemWidth() * itemsPerPage) / (itemsPerPage + 1) } _renderContainerPosition() { let offset = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : 0; let hideItems = arguments.length > 1 ? arguments[1] : void 0; let animate = arguments.length > 2 ? arguments[2] : void 0; this._releaseInvisibleItems(); const itemWidth = this._actualItemWidth(); const targetPosition = this._offsetDirection() * offset * (itemWidth + this._itemFreeSpace()); let showAnimation = animate; let positionReady; if ((0, _type.isDefined)(this._animationOverride)) { showAnimation = this._animationOverride; delete this._animationOverride } if (showAnimation) { this._startSwipe(); positionReady = this._animate(targetPosition).done(this._endSwipe) } else { (0, _translator.move)(this._$container, { left: targetPosition * this._elementWidth(), top: 0 }); positionReady = (0, _deferred.Deferred)().resolveWith(this) } positionReady.done((() => { var _this$_deferredAnimat; null === (_this$_deferredAnimat = this._deferredAnimate) || void 0 === _this$_deferredAnimat || _this$_deferredAnimat.resolveWith(this); if (hideItems) { this._renderItemVisibility() } })); return positionReady.promise() } _startSwipe() { this.$element().addClass("dx-gallery-active") } _endSwipe() { this.$element().removeClass("dx-gallery-active") } _animate(targetPosition) { let extraConfig = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : {}; const $container = this._$container; const animationComplete = (0, _deferred.Deferred)(); const { animationDuration: animationDuration } = this.option(); const that = this; _animation.fx.animate(this._$container.get(0), _extends({ type: "slide", to: { left: targetPosition * (this._elementWidth() ?? 0) }, duration: animationDuration, complete() { if (that._needMoveContainerForward()) { (0, _translator.move)($container, { left: 0, top: 0 }) } if (that._needMoveContainerBack()) { (0, _translator.move)($container, { left: that._maxContainerOffset() * (that._elementWidth() ?? 0), top: 0 }) } animationComplete.resolveWith(that) } }, extraConfig)); return animationComplete } _needMoveContainerForward() { var _this$_$container$pos; const expectedPosition = ((null === (_this$_$container$pos = this._$container.position()) || void 0 === _this$_$container$pos ? void 0 : _this$_$container$pos.left) ?? 0) * this._offsetDirection(); const actualPosition = -this._maxItemWidth() * (this._elementWidth() ?? 0) * this._itemsCount(); return expectedPosition <= actualPosition + 1 } _needMoveContainerBack() { var _this$_$container$pos2; const expectedPosition = ((null === (_this$_$container$pos2 = this._$container.position()) || void 0 === _this$_$container$pos2 ? void 0 : _this$_$container$pos2.left) ?? 0) * this._offsetDirection(); const actualPosition = this._actualItemWidth() * (this._elementWidth() ?? 0); return expectedPosition >= actualPosition - 1 } _maxContainerOffset() { const itemOutPageCount = this._itemsCount() - this._itemsPerPage(); return -this._maxItemWidth() * itemOutPageCount * this._offsetDirection() } _maxItemWidth() { return this._actualItemWidth() + this._itemFreeSpace() } _reviseDimensions() { const $firstItem = this._itemElements().first().find(".dx-item-content"); if (!$firstItem || $firstItem.is(":hidden")) { return } const { height: height, width: width } = this.option(); if (!height) { this.option("height", (0, _size.getOuterHeight)($firstItem)) } if (!width) { this.option("width", (0, _size.getOuterWidth)($firstItem)) } this._dimensionChanged() } _renderIndicator() { const { showIndicator: showIndicator } = this.option(); this._cleanIndicators(); this.$element().toggleClass("dx-gallery-indicator-visible", showIndicator); if (!showIndicator) { return } this._$indicator = (0, _renderer.default)("<div>").addClass("dx-gallery-indicator").appendTo(this._$wrapper); const { indicatorEnabled: indicatorEnabled } = this.option(); for (let i = 0; i < this._pagesCount(); i += 1) { const $indicatorItem = (0, _renderer.default)("<div>").addClass("dx-gallery-indicator-item").appendTo(this._$indicator); if (indicatorEnabled) { this._attachIndicatorClickHandler($indicatorItem, i) } } this._renderSelectedPageIndicator() } _attachIndicatorClickHandler($element, index) { _events_engine.default.on($element, (0, _utils.addNamespace)(_click.name, this.NAME), (event => { this._indicatorSelectHandler(event, index) })) } _detachIndicatorClickHandler($element) { _events_engine.default.off($element, (0, _utils.addNamespace)(_click.name, this.NAME)) } _toggleIndicatorInteraction(clickEnabled) { var _this$_$indicator; const $indicatorItems = (null === (_this$_$indicator = this._$indicator) || void 0 === _this$_$indicator ? void 0 : _this$_$indicator.find(".dx-gallery-indicator-item")) ?? (0, _renderer.default)(); if ($indicatorItems.length) { $indicatorItems.each(((index, element) => { if (clickEnabled) { this._attachIndicatorClickHandler((0, _renderer.default)(element), index) } else { this._detachIndicatorClickHandler((0, _renderer.default)(element)) } return true })) } } _cleanIndicators() { if (this._$indicator) { this._$indicator.remove() } } _renderSelectedItem() { const { selectedIndex: selectedIndex } = this.option(); this._itemElements().removeClass("dx-gallery-item-selected"); if ((0, _type.isDefined)(selectedIndex)) { this._itemElements().eq(selectedIndex).addClass("dx-gallery-item-selected") } } _renderItemVisibility() { const { initialItemWidth: initialItemWidth, wrapAround: wrapAround, selectedIndex: selectedIndex } = this.option(); if (initialItemWidth || wrapAround) { this._releaseInvisibleItems(); return } this._itemElements().each(((index, item) => { if (selectedIndex !== index) { (0, _renderer.default)(item).find(".dx-item-content").addClass("dx-gallery-item-invisible") } return true })) } _releaseInvisibleItems() { this._itemElements().find(".dx-item-content").removeClass("dx-gallery-item-invisible") } _renderSelectedPageIndicator() { if (!this._$indicator) { return } const { selectedIndex: selectedIndex = 0 } = this.option(); const lastIndex = this._pagesCount() - 1; let pageIndex = Math.ceil(selectedIndex / this._itemsPerPage()); pageIndex = Math.min(lastIndex, pageIndex); this._$indicator.find(".dx-gallery-indicator-item").removeClass("dx-gallery-indicator-item-selected").eq(pageIndex).addClass("dx-gallery-indicator-item-selected") } _renderUserInteraction() { const { swipeEnabled: swipeEnabledOption, disabled: disabled } = this.option(); const rootElement = this.$element(); const swipeEnabled = swipeEnabledOption && this._itemsCount() > 1; this._createComponent(rootElement, _swipeable.default, { disabled: !!disabled || !swipeEnabled, onStart: e => { const { event: event } = e; this._swipeStartHandler(event) }, onUpdated: e => { const { event: event } = e; this._swipeUpdateHandler(event) }, onEnd: e => { const { event: event } = e; this._swipeEndHandler(event) }, itemSizeFunc: this._elementWidth.bind(this) }) } _indicatorSelectHandler(_e, indicatorIndex) { const { indicatorEnabled: indicatorEnabled } = this.option(); if (!indicatorEnabled) { return } const itemIndex = this._fitPaginatedIndex(indicatorIndex * this._itemsPerPage()); this._needLongMove = true; this.option("selectedIndex", itemIndex); this._loadNextPageIfNeeded(itemIndex) } _renderNavButtons() { const { showNavButtons: showNavButtons } = this.option(); if (!showNavButtons) { this._cleanNavButtons(); return } const nextPage = this._nextPage.bind(this); const prevPage = this._prevPage.bind(this); this._prevNavButton = (0, _renderer.default)("<div>").appendTo(this._$wrapper); this._createComponent(this._prevNavButton, GalleryNavButton, { direction: "prev", onClick() { prevPage() } }); this._nextNavButton = (0, _renderer.default)("<div>").appendTo(this._$wrapper); this._createComponent(this._nextNavButton, GalleryNavButton, { direction: "next", onClick() { nextPage() } }); this._renderNavButtonsVisibility() } _prevPage() { const visiblePageSize = this._itemsPerPage(); const { selectedIndex: selectedIndex = 0 } = this.option(); const newSelectedIndex = selectedIndex - visiblePageSize; if (newSelectedIndex === -visiblePageSize && visiblePageSize === this._itemsCount()) { return this._relocateItems(newSelectedIndex, 0) } return this.goToItem(this._fitPaginatedIndex(newSelectedIndex)) } _nextPage() { const visiblePageSize = this._itemsPerPage(); const { selectedIndex: selectedIndex = 0 } = this.option(); const newSelectedIndex = selectedIndex + visiblePageSize; if (newSelectedIndex === visiblePageSize && visiblePageSize === this._itemsCount()) { return this._relocateItems(newSelectedIndex, 0) } return this.goToItem(this._fitPaginatedIndex(newSelectedIndex)).done(this._loadNextPageIfNeeded) } _loadNextPageIfNeeded(index) { var _this$_dataSource; const { selectedIndex: selectedIndexOption = 0 } = this.option(); const selectedIndex = index ?? selectedIndexOption; if (null !== (_this$_dataSource = this._dataSource) && void 0 !== _this$_dataSource && _this$_dataSource.paginate() && this._shouldLoadNextPage(selectedIndex) && !this._isDataSourceLoading() && !this._isLastPage()) { this._loadNextPage().done((() => { this._renderIndicator(); this._cloneDuplicateItems(); this._renderItemPositions(); this._renderNavButtonsVisibility(); this._renderItemSizes(selectedIndex) })) } } _shouldLoadNextPage(selectedIndex) { const visiblePageSize = this._itemsPerPage(); const { items: items = [] } = this.option(); return selectedIndex + 2 * visiblePageSize > items.length } _allowDynamicItemsAppend() { return true } _fitPaginatedIndex(itemIndex) { const itemsPerPage = this._itemsPerPage(); const restItemsCount = itemIndex < 0 ? itemsPerPage + itemIndex : this._itemsCount() - itemIndex; if (itemIndex > this._itemsCount() - 1) { this._goToGhostItem = true; return 0 } if (restItemsCount < itemsPerPage && restItemsCount > 0) { if (itemIndex > 0) { return itemIndex - itemsPerPage + restItemsCount } return itemIndex + itemsPerPage - restItemsCount } return itemIndex } _cleanNavButtons() { if (this._prevNavButton) { this._prevNavButton.remove(); delete this._prevNavButton } if (this._nextNavButton) { this._nextNavButton.remove(); delete this._nextNavButton } } _renderNavButtonsVisibility() { var _this$_dataSource2; const { showNavButtons: showNavButtons, selectedIndex: selectedIndex, loop: loop } = this.option(); if (!showNavButtons || !this._prevNavButton || !this._nextNavButton) { return } const itemsCount = this._itemsCount(); this._prevNavButton.show(); this._nextNavButton.show(); if (0 === itemsCount) { this._prevNavButton.hide(); this._nextNavButton.hide() } if (loop) { return } let nextHidden = selectedIndex === itemsCount - this._itemsPerPage(); const prevHidden = itemsCount < 2 || 0 === selectedIndex; if (null !== (_this$_dataSource2 = this._dataSource) && void 0 !== _this$_dataSource2 && _this$_dataSource2.paginate()) { nextHidden = nextHidden && this._isLastPage() } else { nextHidden = nextHidden || itemsCount < 2 } if (prevHidden) { this._prevNavButton.hide() } if (nextHidden) { this._nextNavButton.hide() } } _getUserInteraction() { return this._userInteraction } _setupSlideShow() { const { slideshowDelay: slideshowDelay } = this.option(); clearTimeout(this._slideshowTimer); if (!slideshowDelay) { return } const getUserInteraction = this._getUserInteraction.bind(this); const setupSlideShow = this._setupSlideShow.bind(this); const nextItem = this.nextItem.bind(this); this._slideshowTimer = setTimeout((() => { if (getUserInteraction()) { setupSlideShow(); return } nextItem(true).done(setupSlideShow) }), slideshowDelay) } _elementWidth() { if (!this._cacheElementWidth) { this._cacheElementWidth = (0, _size.getWidth)(this.$element()) } return this._cacheElementWidth } _clearCacheWidth() { delete this._cacheElementWidth } _swipeStartHandler(event) { this._releaseInvisibleItems(); this._clearCacheWidth(); this._elementWidth(); const itemsCount = this._itemsCount(); if (!itemsCount) { event.cancel = true; return } this._stopItemAnimations(); this._startSwipe(); this._userInteraction = true; const { selectedIndex: selectedIndex = 0, rtlEnabled: rtlEnabled, loop: loop } = this.option(); if (!loop) { const startOffset = itemsCount - selectedIndex - this._itemsPerPage(); const endOffset = selectedIndex; event.maxLeftOffset = rtlEnabled ? endOffset : startOffset; event.maxRightOffset = rtlEnabled ? startOffset : endOffset } } _stopItemAnimations() { _animation.fx.stop(this._$container.get(0), true) } _swipeUpdateHandler(event) { const { selectedIndex: selectedIndex = 0, wrapAround: wrapAround } = this.option(); const wrapAroundRatio = wrapAround ? 1 : 0; const itemsPerPage = this._itemsPerPage() + wrapAroundRatio; const offset = this._offsetDirection() * event.offset * itemsPerPage - selectedIndex; if (offset < 0) { this._loadNextPageIfNeeded(Math.ceil(Math.abs(offset))) } this._renderContainerPosition(offset) } _swipeEndHandler(event) { const targetOffset = event.targetOffset * this._offsetDirection() * this._itemsPerPage(); const { selectedIndex: selectedIndex = 0 } = this.option(); const newIndex = this._fitIndex(selectedIndex - targetOffset); const paginatedIndex = this._fitPaginatedIndex(newIndex); if (Math.abs(targetOffset) < this._itemsPerPage()) { this._relocateItems(selectedIndex); return } if (this._itemsPerPage() === this._itemsCount()) { if (targetOffset > 0) { this._relocateItems(-targetOffset) } else { this._relocateItems(0) } return } this.option("selectedIndex", paginatedIndex) } _setFocusOnSelect() { this._userInteraction = true; const selectedItem = this._getRealItems().filter(".dx-gallery-item-selected"); this.option("focusedElement", (0, _element.getPublicElement)(selectedItem)); this._userInteraction = false } _fitIndex(index) { const { loop: loop } = this.option(); if (!loop) { return index } const itemsCount = this._itemsCount(); let fittedIndex = index; if (fittedIndex >= itemsCount || fittedIndex < 0) { this._goToGhostItem = true } if (fittedIndex >= itemsCount) { fittedIndex = itemsCount - fittedIndex } fittedIndex %= itemsCount; if (fittedIndex < 0) { fittedIndex += itemsCount } return fittedIndex } _clean() { super._clean(); this._cleanIndicators(); this._cleanNavButtons() } _dispose() { Gallery._wasAnyItemTemplateRendered = null; clearTimeout(this._slideshowTimer); super._dispose() } _updateSelection(addedSelection, removedSelection) { this._stopItemAnimations(); this._renderNavButtonsVisibility(); this._renderSelectedItem(); this._relocateItems(addedSelection[0], removedSelection[0]); this._renderSelectedPageIndicator() } _relocateItems(newIndex, prevIndex, withoutAnimation) { const indexOffset = this._calculateIndexOffset(newIndex, prevIndex ?? newIndex); const { animationEnabled: animationEnabled } = this.option(); this._renderContainerPosition(indexOffset, true, animationEnabled && !withoutAnimation).done((function() { this._setFocusOnSelect(); this._userInteraction = false; this._setupSlideShow() })) } _focusInHandler(e) { if (_animation.fx.isAnimating(this._$container.get(0)) || this._userInteraction) { return } super._focusInHandler(e) } _focusOutHandler(e) { if (_animation.fx.isAnimating(this._$container.get(0)) || this._userInteraction) { return } super._focusOutHandler(e) } _selectFocusedItem() {} _moveFocus(location, e) { this._stopItemAnimations(); super._moveFocus(location, e); const { focusedElement: focusedElement, animationEnabled: animationEnabled } = this.option(); const index = this.itemElements().index((0, _renderer.default)(focusedElement)); this.goToItem(index, animationEnabled) } _visibilityChanged(visible) { if (visible) { this._reviseDimensions() } } _calculateIndexOffset(newIndex, lastIndex) { const { loop: loop } = this.option(); const prevIndex = lastIndex ?? newIndex; let indexOffset = prevIndex - newIndex; if (loop && !this._needLongMove && this._goToGhostItem) { if (this._isItemOnFirstPage(newIndex) && this._isItemOnLastPage(prevIndex)) { indexOffset = -this._itemsPerPage() } else if (this._isItemOnLastPage(newIndex) && this._isItemOnFirstPage(prevIndex)) { indexOffset = this._itemsPerPage() } this._goToGhostItem = false } this._needLongMove = false; indexOffset -= prevIndex; return indexOffset } _isItemOnLastPage(itemIndex) { return itemIndex >= this._itemsCount() - this._itemsPerPage() } _isItemOnFirstPage(itemIndex) { return itemIndex <= this._itemsPerPage() } _optionChanged(args) { const { name: name, value: value } = args; switch (name) { case "width": case "initialItemWidth": super._optionChanged(args); this._dimensionChanged(); break; case "animationDuration": this._renderNavButtonsVisibility(); break; case "animationEnabled": break; case "loop": this.$element().toggleClass("dx-gallery-loop", value); this.option("loopItemFocus", value); if ((0, _window.hasWindow)()) { this._cloneDuplicateItems(); this._renderItemPositions(); this._renderNavButtonsVisibility() } break; case "showIndicator": this._renderIndicator(); break; case "showNavButtons": this._renderNavButtons(); break; case "slideshowDelay": this._setupSlideShow(); break; case "wrapAround": case "stretchImages": if ((0, _window.hasWindow)()) { this._renderItemSizes(); this._renderItemPositions(); this._renderItemVisibility() } break; case "swipeEnabled": this._renderUserInteraction(); break; case "indicatorEnabled": this._toggleIndicatorInteraction(value); break; default: super._optionChanged(args) } } goToItem(itemIndex, animation) { const { selectedIndex: selectedIndex } = this.option(); const itemsCount = this._itemsCount(); if (void 0 !== animation) { this._animationOverride = animation } const fittedIndex = this._fitIndex(itemIndex); this._deferredAnimate = (0, _deferred.Deferred)(); if (fittedIndex > itemsCount - 1 || fittedIndex < 0 || selectedIndex === fittedIndex) { return this._deferredAnimate.resolveWith(this).promise() } this.option("selectedIndex", fittedIndex); return this._deferredAnimate.promise() } prevItem(animation) { const { selectedIndex: selectedIndex = 0 } = this.option(); return this.goToItem(selectedIndex - 1, animation) } nextItem(animation) { const { selectedIndex: selectedIndex = 0 } = this.option(); return this.goToItem(selectedIndex + 1, animation) } } Gallery._wasAnyItemTemplateRendered = false; (0, _component_registrator.default)("dxGallery", Gallery); var _default = exports.default = Gallery;