devextreme
Version:
HTML5 JavaScript Component Suite for Responsive Web Development
906 lines (905 loc) • 35.1 kB
JavaScript
/**
* DevExtreme (esm/ui/gallery.js)
* Version: 21.1.4
* Build date: Mon Jun 21 2021
*
* Copyright (c) 2012 - 2021 Developer Express Inc. ALL RIGHTS RESERVED
* Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/
*/
import $ from "../core/renderer";
import eventsEngine from "../events/core/events_engine";
import registerComponent from "../core/component_registrator";
import {
noop
} from "../core/utils/common";
import {
isDefined,
isPlainObject
} from "../core/utils/type";
import {
hasWindow
} from "../core/utils/window";
import {
extend
} from "../core/utils/extend";
import {
getPublicElement
} from "../core/element";
import fx from "../animation/fx";
import {
name as clickEventName
} from "../events/click";
import {
move
} from "../animation/translator";
import devices from "../core/devices";
import Widget from "./widget/ui.widget";
import {
addNamespace
} from "../events/utils/index";
import CollectionWidget from "./collection/ui.collection_widget.edit";
import Swipeable from "../events/gesture/swipeable";
import {
BindableTemplate
} from "../core/templates/bindable_template";
import {
Deferred
} from "../core/utils/deferred";
var GALLERY_CLASS = "dx-gallery";
var GALLERY_WRAPPER_CLASS = GALLERY_CLASS + "-wrapper";
var GALLERY_LOOP_CLASS = "dx-gallery-loop";
var GALLERY_ITEM_CONTAINER_CLASS = GALLERY_CLASS + "-container";
var GALLERY_ACTIVE_CLASS = GALLERY_CLASS + "-active";
var GALLERY_ITEM_CLASS = GALLERY_CLASS + "-item";
var GALLERY_INVISIBLE_ITEM_CLASS = GALLERY_CLASS + "-item-invisible";
var GALLERY_LOOP_ITEM_CLASS = GALLERY_ITEM_CLASS + "-loop";
var GALLERY_ITEM_SELECTOR = "." + GALLERY_ITEM_CLASS;
var GALLERY_ITEM_SELECTED_CLASS = GALLERY_ITEM_CLASS + "-selected";
var GALLERY_INDICATOR_CLASS = GALLERY_CLASS + "-indicator";
var GALLERY_INDICATOR_ITEM_CLASS = GALLERY_INDICATOR_CLASS + "-item";
var GALLERY_INDICATOR_ITEM_SELECTOR = "." + GALLERY_INDICATOR_ITEM_CLASS;
var GALLERY_INDICATOR_ITEM_SELECTED_CLASS = GALLERY_INDICATOR_ITEM_CLASS + "-selected";
var GALLERY_IMAGE_CLASS = "dx-gallery-item-image";
var GALLERY_ITEM_DATA_KEY = "dxGalleryItemData";
var MAX_CALC_ERROR = 1;
var GalleryNavButton = Widget.inherit({
_supportedKeys: function() {
return extend(this.callBase(), {
pageUp: noop,
pageDown: noop
})
},
_getDefaultOptions: function() {
return extend(this.callBase(), {
direction: "next",
onClick: null,
hoverStateEnabled: true,
activeStateEnabled: true
})
},
_render: function() {
this.callBase();
var that = this;
var $element = this.$element();
var eventName = addNamespace(clickEventName, this.NAME);
$element.addClass(GALLERY_CLASS + "-nav-button-" + this.option("direction"));
eventsEngine.off($element, eventName);
eventsEngine.on($element, eventName, (function(e) {
that._createActionByOption("onClick")({
event: e
})
}))
},
_optionChanged: function(args) {
switch (args.name) {
case "onClick":
case "direction":
this._invalidate();
break;
default:
this.callBase(args)
}
}
});
var Gallery = CollectionWidget.inherit({
_activeStateUnit: GALLERY_ITEM_SELECTOR,
_getDefaultOptions: function() {
return extend(this.callBase(), {
activeStateEnabled: false,
animationDuration: 400,
animationEnabled: true,
loop: false,
swipeEnabled: true,
indicatorEnabled: true,
showIndicator: true,
selectedIndex: 0,
slideshowDelay: 0,
showNavButtons: false,
wrapAround: false,
initialItemWidth: void 0,
stretchImages: false,
_itemAttributes: {
role: "option"
},
loopItemFocus: false,
selectOnFocus: true,
selectionMode: "single",
selectionRequired: true,
selectionByClick: false
})
},
_defaultOptionsRules: function() {
return this.callBase().concat([{
device: function() {
return "desktop" === devices.real().deviceType && !devices.isSimulator()
},
options: {
focusStateEnabled: true
}
}])
},
_init: function() {
this.callBase();
this.option("loopItemFocus", this.option("loop"))
},
_initTemplates: function() {
this.callBase();
this._templateManager.addDefaultTemplates({
item: new BindableTemplate(function($container, data) {
var $img = $("<img>").addClass(GALLERY_IMAGE_CLASS);
if (isPlainObject(data)) {
this._prepareDefaultItemTemplate(data, $container);
$img.attr({
src: data.imageSrc,
alt: data.imageAlt
}).appendTo($container)
} else {
$img.attr("src", String(data)).appendTo($container)
}
}.bind(this), ["imageSrc", "imageAlt", "text", "html"], this.option("integrationOptions.watchMethod"))
})
},
_dataSourceOptions: function() {
return {
paginate: false
}
},
_itemContainer: function() {
return this._$container
},
_itemClass: function() {
return GALLERY_ITEM_CLASS
},
_itemDataKey: function() {
return GALLERY_ITEM_DATA_KEY
},
_actualItemWidth: function() {
var isWrapAround = this.option("wrapAround");
if (this.option("stretchImages")) {
var itemPerPage = isWrapAround ? this._itemsPerPage() + 1 : this._itemsPerPage();
return 1 / itemPerPage
}
if (isWrapAround) {
return this._itemPercentWidth() * this._itemsPerPage() / (this._itemsPerPage() + 1)
}
return this._itemPercentWidth()
},
_itemPercentWidth: function() {
var percentWidth;
var elementWidth = this.$element().outerWidth();
var initialItemWidth = this.option("initialItemWidth");
if (initialItemWidth && initialItemWidth <= elementWidth) {
percentWidth = initialItemWidth / elementWidth
} else {
percentWidth = 1
}
return percentWidth
},
_itemsPerPage: function() {
var itemsPerPage = hasWindow() ? Math.floor(1 / this._itemPercentWidth()) : 1;
return Math.min(itemsPerPage, this._itemsCount())
},
_pagesCount: function() {
return Math.ceil(this._itemsCount() / this._itemsPerPage())
},
_itemsCount: function() {
return (this.option("items") || []).length
},
_offsetDirection: function() {
return this.option("rtlEnabled") ? -1 : 1
},
_initMarkup: function() {
this._renderWrapper();
this._renderItemsContainer();
this.$element().addClass(GALLERY_CLASS);
this.$element().toggleClass(GALLERY_LOOP_CLASS, this.option("loop"));
this.callBase();
this.setAria({
role: "listbox",
label: "gallery"
})
},
_render: function() {
this._renderDragHandler();
this._renderContainerPosition();
this._renderItemSizes();
this._renderItemPositions();
this._renderNavButtons();
this._renderIndicator();
this._renderSelectedItem();
this._renderItemVisibility();
this._renderUserInteraction();
this._setupSlideShow();
this._reviseDimensions();
this.callBase()
},
_dimensionChanged: function() {
var selectedIndex = this.option("selectedIndex") || 0;
this._stopItemAnimations();
this._clearCacheWidth();
this._cloneDuplicateItems();
this._renderItemSizes();
this._renderItemPositions();
this._renderIndicator();
this._renderContainerPosition(this._calculateIndexOffset(selectedIndex), true);
this._renderItemVisibility()
},
_renderDragHandler: function() {
var eventName = addNamespace("dragstart", this.NAME);
eventsEngine.off(this.$element(), eventName);
eventsEngine.on(this.$element(), eventName, "img", (function() {
return false
}))
},
_renderWrapper: function() {
if (this._$wrapper) {
return
}
this._$wrapper = $("<div>").addClass(GALLERY_WRAPPER_CLASS).appendTo(this.$element())
},
_renderItems: function(items) {
if (!hasWindow()) {
var selectedIndex = this.option("selectedIndex");
items = items.length > selectedIndex ? items.slice(selectedIndex, selectedIndex + 1) : items.slice(0, 1)
}
this.callBase(items);
this._loadNextPageIfNeeded()
},
_renderItemsContainer: function() {
if (this._$container) {
return
}
this._$container = $("<div>").addClass(GALLERY_ITEM_CONTAINER_CLASS).appendTo(this._$wrapper)
},
_cloneDuplicateItems: function() {
if (!this.option("loop")) {
return
}
var items = this.option("items") || [];
var itemsCount = items.length;
var lastItemIndex = itemsCount - 1;
var i;
if (!itemsCount) {
return
}
this._getLoopedItems().remove();
var duplicateCount = Math.min(this._itemsPerPage(), itemsCount);
var $items = this._getRealItems();
var $container = this._itemContainer();
for (i = 0; i < duplicateCount; i++) {
this._cloneItemForDuplicate($items[i], $container)
}
for (i = 0; i < duplicateCount; i++) {
this._cloneItemForDuplicate($items[lastItemIndex - i], $container)
}
},
_cloneItemForDuplicate: function(item, $container) {
if (item) {
$(item).clone(true).addClass(GALLERY_LOOP_ITEM_CLASS).css("margin", 0).appendTo($container)
}
},
_getRealItems: function() {
var selector = "." + GALLERY_ITEM_CLASS + ":not(." + GALLERY_LOOP_ITEM_CLASS + ")";
return this.$element().find(selector)
},
_getLoopedItems: function() {
return this.$element().find("." + GALLERY_LOOP_ITEM_CLASS)
},
_emptyMessageContainer: function() {
return this._$wrapper
},
_renderItemSizes: function(startIndex) {
var $items = this._itemElements();
var itemWidth = this._actualItemWidth();
if (void 0 !== startIndex) {
$items = $items.slice(startIndex)
}
$items.each((function(index) {
$($items[index]).outerWidth(100 * itemWidth + "%")
}))
},
_renderItemPositions: function() {
var itemWidth = this._actualItemWidth();
var itemsCount = this._itemsCount();
var itemsPerPage = this._itemsPerPage();
var loopItemsCount = this.$element().find("." + GALLERY_LOOP_ITEM_CLASS).length;
var lastItemDuplicateIndex = itemsCount + loopItemsCount - 1;
var offsetRatio = this.option("wrapAround") ? .5 : 0;
var freeSpace = this._itemFreeSpace();
var isGapBetweenImages = !!freeSpace;
var rtlEnabled = this.option("rtlEnabled");
var selectedIndex = this.option("selectedIndex");
var side = rtlEnabled ? "Right" : "Left";
this._itemElements().each((function(index) {
var realIndex = index;
var isLoopItem = $(this).hasClass(GALLERY_LOOP_ITEM_CLASS);
if (index > itemsCount + itemsPerPage - 1) {
realIndex = lastItemDuplicateIndex - realIndex - itemsPerPage
}
if (!isLoopItem && 0 !== realIndex) {
if (isGapBetweenImages) {
$(this).css("margin" + side, 100 * freeSpace + "%")
}
return
}
var itemPosition = itemWidth * (realIndex + offsetRatio) + freeSpace * (realIndex + 1 - offsetRatio);
var property = isLoopItem ? side.toLowerCase() : "margin" + side;
$(this).css(property, 100 * itemPosition + "%")
}));
this._relocateItems(selectedIndex, selectedIndex, true)
},
_itemFreeSpace: function() {
var itemsPerPage = this._itemsPerPage();
if (this.option("wrapAround")) {
itemsPerPage += 1
}
return (1 - this._actualItemWidth() * itemsPerPage) / (itemsPerPage + 1)
},
_renderContainerPosition: function(offset, hideItems, animate) {
this._releaseInvisibleItems();
offset = offset || 0;
var that = this;
var itemWidth = this._actualItemWidth();
var targetIndex = offset;
var targetPosition = this._offsetDirection() * targetIndex * (itemWidth + this._itemFreeSpace());
var positionReady;
if (isDefined(this._animationOverride)) {
animate = this._animationOverride;
delete this._animationOverride
}
if (animate) {
that._startSwipe();
positionReady = that._animate(targetPosition).done(that._endSwipe.bind(that))
} else {
move(this._$container, {
left: targetPosition * this._elementWidth(),
top: 0
});
positionReady = (new Deferred).resolveWith(that)
}
positionReady.done((function() {
this._deferredAnimate && that._deferredAnimate.resolveWith(that);
hideItems && this._renderItemVisibility()
}));
return positionReady.promise()
},
_startSwipe: function() {
this.$element().addClass(GALLERY_ACTIVE_CLASS)
},
_endSwipe: function() {
this.$element().removeClass(GALLERY_ACTIVE_CLASS)
},
_animate: function(targetPosition, extraConfig) {
var that = this;
var $container = this._$container;
var animationComplete = new Deferred;
fx.animate(this._$container, extend({
type: "slide",
to: {
left: targetPosition * this._elementWidth()
},
duration: that.option("animationDuration"),
complete: function() {
if (that._needMoveContainerForward()) {
move($container, {
left: 0,
top: 0
})
}
if (that._needMoveContainerBack()) {
move($container, {
left: that._maxContainerOffset() * that._elementWidth(),
top: 0
})
}
animationComplete.resolveWith(that)
}
}, extraConfig || {}));
return animationComplete
},
_needMoveContainerForward: function() {
var expectedPosition = this._$container.position().left * this._offsetDirection();
var actualPosition = -this._maxItemWidth() * this._elementWidth() * this._itemsCount();
return expectedPosition <= actualPosition + MAX_CALC_ERROR
},
_needMoveContainerBack: function() {
var expectedPosition = this._$container.position().left * this._offsetDirection();
var actualPosition = this._actualItemWidth() * this._elementWidth();
return expectedPosition >= actualPosition - MAX_CALC_ERROR
},
_maxContainerOffset: function() {
return -this._maxItemWidth() * (this._itemsCount() - this._itemsPerPage()) * this._offsetDirection()
},
_maxItemWidth: function() {
return this._actualItemWidth() + this._itemFreeSpace()
},
_reviseDimensions: function() {
var $firstItem = this._itemElements().first().find(".dx-item-content");
if (!$firstItem || $firstItem.is(":hidden")) {
return
}
if (!this.option("height")) {
this.option("height", $firstItem.outerHeight())
}
if (!this.option("width")) {
this.option("width", $firstItem.outerWidth())
}
this._dimensionChanged()
},
_renderIndicator: function() {
this._cleanIndicators();
if (!this.option("showIndicator")) {
return
}
var indicator = this._$indicator = $("<div>").addClass(GALLERY_INDICATOR_CLASS).appendTo(this._$wrapper);
var isIndicatorEnabled = this.option("indicatorEnabled");
for (var i = 0; i < this._pagesCount(); i++) {
var $indicatorItem = $("<div>").addClass(GALLERY_INDICATOR_ITEM_CLASS).appendTo(indicator);
if (isIndicatorEnabled) {
this._attachIndicatorClickHandler($indicatorItem, i)
}
}
this._renderSelectedPageIndicator()
},
_attachIndicatorClickHandler: function($element, index) {
eventsEngine.on($element, addNamespace(clickEventName, this.NAME), function(event) {
this._indicatorSelectHandler(event, index)
}.bind(this))
},
_detachIndicatorClickHandler: function($element) {
eventsEngine.off($element, addNamespace(clickEventName, this.NAME))
},
_toggleIndicatorInteraction: function(clickEnabled) {
var _this$_$indicator;
var $indicatorItems = (null === (_this$_$indicator = this._$indicator) || void 0 === _this$_$indicator ? void 0 : _this$_$indicator.find(GALLERY_INDICATOR_ITEM_SELECTOR)) || [];
if ($indicatorItems.length) {
$indicatorItems.each(function(index, element) {
clickEnabled ? this._attachIndicatorClickHandler($(element), index) : this._detachIndicatorClickHandler($(element))
}.bind(this))
}
},
_cleanIndicators: function() {
if (this._$indicator) {
this._$indicator.remove()
}
},
_renderSelectedItem: function() {
var selectedIndex = this.option("selectedIndex");
this._itemElements().removeClass(GALLERY_ITEM_SELECTED_CLASS).eq(selectedIndex).addClass(GALLERY_ITEM_SELECTED_CLASS)
},
_renderItemVisibility: function() {
if (this.option("initialItemWidth") || this.option("wrapAround")) {
this._releaseInvisibleItems();
return
}
this._itemElements().each(function(index, item) {
if (this.option("selectedIndex") === index) {
$(item).removeClass(GALLERY_INVISIBLE_ITEM_CLASS)
} else {
$(item).addClass(GALLERY_INVISIBLE_ITEM_CLASS)
}
}.bind(this));
this._getLoopedItems().addClass(GALLERY_INVISIBLE_ITEM_CLASS)
},
_releaseInvisibleItems: function() {
this._itemElements().removeClass(GALLERY_INVISIBLE_ITEM_CLASS);
this._getLoopedItems().removeClass(GALLERY_INVISIBLE_ITEM_CLASS)
},
_renderSelectedPageIndicator: function() {
if (!this._$indicator) {
return
}
var itemIndex = this.option("selectedIndex");
var lastIndex = this._pagesCount() - 1;
var pageIndex = Math.ceil(itemIndex / this._itemsPerPage());
pageIndex = Math.min(lastIndex, pageIndex);
this._$indicator.find(GALLERY_INDICATOR_ITEM_SELECTOR).removeClass(GALLERY_INDICATOR_ITEM_SELECTED_CLASS).eq(pageIndex).addClass(GALLERY_INDICATOR_ITEM_SELECTED_CLASS)
},
_renderUserInteraction: function() {
var rootElement = this.$element();
var swipeEnabled = this.option("swipeEnabled") && this._itemsCount() > 1;
this._createComponent(rootElement, Swipeable, {
disabled: this.option("disabled") || !swipeEnabled,
onStart: this._swipeStartHandler.bind(this),
onUpdated: this._swipeUpdateHandler.bind(this),
onEnd: this._swipeEndHandler.bind(this),
itemSizeFunc: this._elementWidth.bind(this)
})
},
_indicatorSelectHandler: function(e, indicatorIndex) {
if (!this.option("indicatorEnabled")) {
return
}
var itemIndex = this._fitPaginatedIndex(indicatorIndex * this._itemsPerPage());
this._needLongMove = true;
this.option("selectedIndex", itemIndex);
this._loadNextPageIfNeeded(itemIndex)
},
_renderNavButtons: function() {
var that = this;
if (!that.option("showNavButtons")) {
that._cleanNavButtons();
return
}
that._prevNavButton = $("<div>").appendTo(this._$wrapper);
that._createComponent(that._prevNavButton, GalleryNavButton, {
direction: "prev",
onClick: function() {
that._prevPage()
}
});
that._nextNavButton = $("<div>").appendTo(this._$wrapper);
that._createComponent(that._nextNavButton, GalleryNavButton, {
direction: "next",
onClick: function() {
that._nextPage()
}
});
this._renderNavButtonsVisibility()
},
_prevPage: function() {
var visiblePageSize = this._itemsPerPage();
var newSelectedIndex = this.option("selectedIndex") - visiblePageSize;
if (newSelectedIndex === -visiblePageSize && visiblePageSize === this._itemsCount()) {
return this._relocateItems(newSelectedIndex, 0)
} else {
return this.goToItem(this._fitPaginatedIndex(newSelectedIndex))
}
},
_nextPage: function() {
var visiblePageSize = this._itemsPerPage();
var newSelectedIndex = this.option("selectedIndex") + visiblePageSize;
if (newSelectedIndex === visiblePageSize && visiblePageSize === this._itemsCount()) {
return this._relocateItems(newSelectedIndex, 0)
} else {
return this.goToItem(this._fitPaginatedIndex(newSelectedIndex)).done(this._loadNextPageIfNeeded)
}
},
_loadNextPageIfNeeded: function(selectedIndex) {
selectedIndex = void 0 === selectedIndex ? this.option("selectedIndex") : selectedIndex;
if (this._dataSource && this._dataSource.paginate() && this._shouldLoadNextPage(selectedIndex) && !this._isDataSourceLoading() && !this._isLastPage()) {
this._loadNextPage().done(function() {
this._renderIndicator();
this._cloneDuplicateItems();
this._renderItemPositions();
this._renderNavButtonsVisibility();
this._renderItemSizes(selectedIndex)
}.bind(this))
}
},
_shouldLoadNextPage: function(selectedIndex) {
var visiblePageSize = this._itemsPerPage();
return selectedIndex + 2 * visiblePageSize > this.option("items").length
},
_allowDynamicItemsAppend: function() {
return true
},
_fitPaginatedIndex: function(itemIndex) {
var itemsPerPage = this._itemsPerPage();
var restItemsCount = itemIndex < 0 ? itemsPerPage + itemIndex : this._itemsCount() - itemIndex;
if (itemIndex > this._itemsCount() - 1) {
itemIndex = 0;
this._goToGhostItem = true
} else if (restItemsCount < itemsPerPage && restItemsCount > 0) {
if (itemIndex > 0) {
itemIndex -= itemsPerPage - restItemsCount
} else {
itemIndex += itemsPerPage - restItemsCount
}
}
return itemIndex
},
_cleanNavButtons: function() {
if (this._prevNavButton) {
this._prevNavButton.remove();
delete this._prevNavButton
}
if (this._nextNavButton) {
this._nextNavButton.remove();
delete this._nextNavButton
}
},
_renderNavButtonsVisibility: function() {
if (!this.option("showNavButtons") || !this._prevNavButton || !this._nextNavButton) {
return
}
var selectedIndex = this.option("selectedIndex");
var loop = this.option("loop");
var itemsCount = this._itemsCount();
this._prevNavButton.show();
this._nextNavButton.show();
if (0 === itemsCount) {
this._prevNavButton.hide();
this._nextNavButton.hide()
}
if (loop) {
return
}
var nextHidden = selectedIndex === itemsCount - this._itemsPerPage();
var prevHidden = itemsCount < 2 || 0 === selectedIndex;
if (this._dataSource && this._dataSource.paginate()) {
nextHidden = nextHidden && this._isLastPage()
} else {
nextHidden = nextHidden || itemsCount < 2
}
if (prevHidden) {
this._prevNavButton.hide()
}
if (nextHidden) {
this._nextNavButton.hide()
}
},
_setupSlideShow: function() {
var that = this;
var slideshowDelay = that.option("slideshowDelay");
clearTimeout(that._slideshowTimer);
if (!slideshowDelay) {
return
}
that._slideshowTimer = setTimeout((function() {
if (that._userInteraction) {
that._setupSlideShow();
return
}
that.nextItem(true).done(that._setupSlideShow)
}), slideshowDelay)
},
_elementWidth: function() {
if (!this._cacheElementWidth) {
this._cacheElementWidth = this.$element().width()
}
return this._cacheElementWidth
},
_clearCacheWidth: function() {
delete this._cacheElementWidth
},
_swipeStartHandler: function(e) {
this._releaseInvisibleItems();
this._clearCacheWidth();
this._elementWidth();
var itemsCount = this._itemsCount();
if (!itemsCount) {
e.event.cancel = true;
return
}
this._stopItemAnimations();
this._startSwipe();
this._userInteraction = true;
if (!this.option("loop")) {
var selectedIndex = this.option("selectedIndex");
var startOffset = itemsCount - selectedIndex - this._itemsPerPage();
var endOffset = selectedIndex;
var rtlEnabled = this.option("rtlEnabled");
e.event.maxLeftOffset = rtlEnabled ? endOffset : startOffset;
e.event.maxRightOffset = rtlEnabled ? startOffset : endOffset
}
},
_stopItemAnimations: function() {
fx.stop(this._$container, true)
},
_swipeUpdateHandler: function(e) {
var wrapAroundRatio = this.option("wrapAround") ? 1 : 0;
var offset = this._offsetDirection() * e.event.offset * (this._itemsPerPage() + wrapAroundRatio) - this.option("selectedIndex");
if (offset < 0) {
this._loadNextPageIfNeeded(Math.ceil(Math.abs(offset)))
}
this._renderContainerPosition(offset)
},
_swipeEndHandler: function(e) {
var targetOffset = e.event.targetOffset * this._offsetDirection() * this._itemsPerPage();
var selectedIndex = this.option("selectedIndex");
var newIndex = this._fitIndex(selectedIndex - targetOffset);
var 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: function() {
this._userInteraction = true;
var selectedItem = this.itemElements().filter("." + GALLERY_ITEM_SELECTED_CLASS);
this.option("focusedElement", getPublicElement(selectedItem));
this._userInteraction = false
},
_flipIndex: function(index) {
var itemsCount = this._itemsCount();
index %= itemsCount;
if (index > (itemsCount + 1) / 2) {
index -= itemsCount
}
if (index < -(itemsCount - 1) / 2) {
index += itemsCount
}
return index
},
_fitIndex: function(index) {
if (!this.option("loop")) {
return index
}
var itemsCount = this._itemsCount();
if (index >= itemsCount || index < 0) {
this._goToGhostItem = true
}
if (index >= itemsCount) {
index = itemsCount - index
}
index %= itemsCount;
if (index < 0) {
index += itemsCount
}
return index
},
_clean: function() {
this.callBase();
this._cleanIndicators();
this._cleanNavButtons()
},
_dispose: function() {
clearTimeout(this._slideshowTimer);
this.callBase()
},
_updateSelection: function(addedSelection, removedSelection) {
this._stopItemAnimations();
this._renderNavButtonsVisibility();
this._renderSelectedItem();
this._relocateItems(addedSelection[0], removedSelection[0]);
this._renderSelectedPageIndicator()
},
_relocateItems: function(newIndex, prevIndex, withoutAnimation) {
if (void 0 === prevIndex) {
prevIndex = newIndex
}
var indexOffset = this._calculateIndexOffset(newIndex, prevIndex);
this._renderContainerPosition(indexOffset, true, this.option("animationEnabled") && !withoutAnimation).done((function() {
this._setFocusOnSelect();
this._userInteraction = false;
this._setupSlideShow()
}))
},
_focusInHandler: function() {
if (fx.isAnimating(this._$container) || this._userInteraction) {
return
}
this.callBase.apply(this, arguments)
},
_focusOutHandler: function() {
if (fx.isAnimating(this._$container) || this._userInteraction) {
return
}
this.callBase.apply(this, arguments)
},
_selectFocusedItem: noop,
_moveFocus: function() {
this._stopItemAnimations();
this.callBase.apply(this, arguments);
var index = this.itemElements().index($(this.option("focusedElement")));
this.goToItem(index, this.option("animationEnabled"))
},
_visibilityChanged: function(visible) {
if (visible) {
this._reviseDimensions()
}
},
_calculateIndexOffset: function(newIndex, lastIndex) {
if (void 0 === lastIndex) {
lastIndex = newIndex
}
var indexOffset = lastIndex - newIndex;
if (this.option("loop") && !this._needLongMove && this._goToGhostItem) {
if (this._isItemOnFirstPage(newIndex) && this._isItemOnLastPage(lastIndex)) {
indexOffset = -this._itemsPerPage()
} else if (this._isItemOnLastPage(newIndex) && this._isItemOnFirstPage(lastIndex)) {
indexOffset = this._itemsPerPage()
}
this._goToGhostItem = false
}
this._needLongMove = false;
indexOffset -= lastIndex;
return indexOffset
},
_isItemOnLastPage: function(itemIndex) {
return itemIndex >= this._itemsCount() - this._itemsPerPage()
},
_isItemOnFirstPage: function(itemIndex) {
return itemIndex <= this._itemsPerPage()
},
_optionChanged: function(args) {
switch (args.name) {
case "width":
case "initialItemWidth":
this.callBase.apply(this, arguments);
this._dimensionChanged();
break;
case "animationDuration":
this._renderNavButtonsVisibility();
break;
case "animationEnabled":
break;
case "loop":
this.$element().toggleClass(GALLERY_LOOP_CLASS, args.value);
this.option("loopItemFocus", args.value);
if (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 (hasWindow()) {
this._renderItemSizes();
this._renderItemPositions();
this._renderItemVisibility()
}
break;
case "swipeEnabled":
this._renderUserInteraction();
break;
case "indicatorEnabled":
this._toggleIndicatorInteraction(args.value);
break;
default:
this.callBase(args)
}
},
goToItem: function(itemIndex, animation) {
var selectedIndex = this.option("selectedIndex");
var itemsCount = this._itemsCount();
if (void 0 !== animation) {
this._animationOverride = animation
}
itemIndex = this._fitIndex(itemIndex);
this._deferredAnimate = new Deferred;
if (itemIndex > itemsCount - 1 || itemIndex < 0 || selectedIndex === itemIndex) {
return this._deferredAnimate.resolveWith(this).promise()
}
this.option("selectedIndex", itemIndex);
return this._deferredAnimate.promise()
},
prevItem: function(animation) {
return this.goToItem(this.option("selectedIndex") - 1, animation)
},
nextItem: function(animation) {
return this.goToItem(this.option("selectedIndex") + 1, animation)
}
});
registerComponent("dxGallery", Gallery);
export default Gallery;