devextreme
Version:
HTML5 JavaScript Component Suite for Responsive Web Development
564 lines (460 loc) • 16.7 kB
JavaScript
"use strict";
var $ = require("../core/renderer"),
eventsEngine = require("../events/core/events_engine"),
fx = require("../animation/fx"),
swipeEvents = require("../events/swipe"),
translator = require("../animation/translator"),
domUtils = require("../core/utils/dom"),
extend = require("../core/utils/extend").extend,
isDefined = require("../core/utils/type").isDefined,
registerComponent = require("../core/component_registrator"),
eventUtils = require("../events/utils"),
config = require("../core/config"),
CollectionWidget = require("./collection/ui.collection_widget.edit"),
PivotTabs = require("./pivot/ui.pivot_tabs"),
EmptyTemplate = require("./widget/empty_template"),
ChildDefaultTemplate = require("./widget/child_default_template"),
Deferred = require("../core/utils/deferred").Deferred;
var PIVOT_CLASS = "dx-pivot",
PIVOT_AUTOHEIGHT_CLASS = "dx-pivot-autoheight",
PIVOT_WRAPPER_CLASS = "dx-pivot-wrapper",
PIVOT_TABS_CONTAINER_CLASS = "dx-pivottabs-container",
PIVOT_ITEM_CONTAINER_CLASS = "dx-pivot-itemcontainer",
PIVOT_ITEM_WRAPPER_CLASS = "dx-pivot-itemwrapper",
PIVOT_ITEM_CLASS = "dx-pivot-item",
PIVOT_ITEM_HIDDEN_CLASS = "dx-pivot-item-hidden",
PIVOT_ITEM_DATA_KEY = "dxPivotItemData",
PIVOT_RETURN_BACK_DURATION = 200,
PIVOT_SLIDE_AWAY_DURATION = 50,
PIVOT_SLIDE_BACK_DURATION = 250,
PIVOT_SLIDE_BACK_EASING = "cubic-bezier(.10, 1, 0, 1)";
var animation = {
returnBack: function returnBack($element) {
fx.animate($element, {
type: "slide",
to: { left: 0 },
duration: PIVOT_RETURN_BACK_DURATION
});
},
slideAway: function slideAway($element, position, complete) {
fx.animate($element, {
type: "slide",
to: { left: position },
duration: PIVOT_SLIDE_AWAY_DURATION,
complete: complete
});
},
slideBack: function slideBack($element) {
fx.animate($element, {
type: "slide",
to: { left: 0 },
easing: PIVOT_SLIDE_BACK_EASING,
duration: PIVOT_SLIDE_BACK_DURATION
});
},
complete: function complete($element) {
fx.stop($element, true);
}
};
/**
* @name dxPivot
* @publicName dxPivot
* @inherits CollectionWidget
* @module ui/pivot
* @export default
* @deprecated
*/
var Pivot = CollectionWidget.inherit({
_getDefaultOptions: function _getDefaultOptions() {
return extend(this.callBase(), {
/**
* @name dxPivotOptions.selectedIndex
* @publicName selectedIndex
* @type number
* @default 0
*/
selectedIndex: 0,
/**
* @name dxPivotOptions.swipeEnabled
* @publicName swipeEnabled
* @type boolean
* @default true
*/
swipeEnabled: true,
/**
* @name dxPivotOptions.itemTitleTemplate
* @publicName itemTitleTemplate
* @type template|function
* @default "title"
* @type_function_param1 itemData:object
* @type_function_param2 itemIndex:number
* @type_function_param3 itemElement:dxElement
* @type_function_return string|Node|jQuery
*/
itemTitleTemplate: "title",
/**
* @name dxPivotOptions.contentTemplate
* @publicName contentTemplate
* @type template|function
* @default "content"
* @type_function_param1 container:dxElement
* @type_function_return string|Node|jQuery
*/
contentTemplate: "content",
/**
* @name dxPivotOptions.focusStateEnabled
* @publicName focusStateEnabled
* @type boolean
* @default false
* @hidden
*/
focusStateEnabled: false,
selectionMode: "single",
selectionRequired: true,
selectionByClick: false
/**
* @name dxPivotOptions.noDataText
* @publicName noDataText
* @hidden
* @inheritdoc
*/
/**
* @name dxPivotOptions.selectedItems
* @publicName selectedItems
* @hidden
* @inheritdoc
*/
/**
* @name dxPivotOptions.selectedItemKeys
* @publicName selectedItemKeys
* @hidden
* @inheritdoc
*/
/**
* @name dxPivotOptions.keyExpr
* @publicName keyExpr
* @hidden
* @inheritdoc
*/
/**
* @name dxPivotOptions.accessKey
* @publicName accessKey
* @hidden
* @inheritdoc
*/
/**
* @name dxPivotOptions.tabIndex
* @publicName tabIndex
* @hidden
* @inheritdoc
*/
});
},
_itemClass: function _itemClass() {
return PIVOT_ITEM_CLASS;
},
_itemDataKey: function _itemDataKey() {
return PIVOT_ITEM_DATA_KEY;
},
_itemContainer: function _itemContainer() {
return this._$itemWrapper;
},
_elementWidth: function _elementWidth() {
if (!this._elementWidthCache) {
this._elementWidthCache = this.$element().width();
}
return this._elementWidthCache;
},
_clearElementWidthCache: function _clearElementWidthCache() {
delete this._elementWidthCache;
},
_init: function _init() {
this.callBase();
this.$element().addClass(PIVOT_CLASS);
this._initWrapper();
this._initTabs();
this._initItemContainer();
this._clearItemsCache();
this._initSwipeHandlers();
},
_initTemplates: function _initTemplates() {
this.callBase();
/**
* @name dxPivotItemTemplate
* @publicName dxPivotItemTemplate
* @inherits CollectionWidgetItemTemplate
* @type object
*/
/**
* @name dxPivotItemTemplate.titleTemplate
* @publicName titleTemplate
* @type template|function
* @type_function_return string|Node|jQuery
*/
/**
* @name dxPivotItemTemplate.visible
* @publicName visible
* @hidden
* @inheritdoc
*/
/**
* @name dxPivotItemTemplate.title
* @publicName title
* @type String
*/
this._defaultTemplates["content"] = new EmptyTemplate();
this._defaultTemplates["title"] = new ChildDefaultTemplate("item", this);
},
_dimensionChanged: function _dimensionChanged() {
this._clearElementWidthCache();
},
_initWrapper: function _initWrapper() {
this._$wrapper = $("<div>").addClass(PIVOT_WRAPPER_CLASS).appendTo(this.$element());
},
_initItemContainer: function _initItemContainer() {
var $itemContainer = $("<div>").addClass(PIVOT_ITEM_CONTAINER_CLASS);
this._$wrapper.append($itemContainer);
this._$itemWrapper = $("<div>").addClass(PIVOT_ITEM_WRAPPER_CLASS);
$itemContainer.append(this._$itemWrapper);
},
_clearItemsCache: function _clearItemsCache() {
this._itemsCache = [];
},
_initTabs: function _initTabs() {
var that = this,
$tabsContainer = $("<div>").addClass(PIVOT_TABS_CONTAINER_CLASS);
this._$wrapper.append($tabsContainer);
this._tabs = this._createComponent($tabsContainer, PivotTabs, {
itemTemplateProperty: "titleTemplate",
itemTemplate: this._getTemplateByOption("itemTitleTemplate"),
items: this.option("items"),
selectedIndex: this.option("selectedIndex"),
onPrepare: function onPrepare() {
that._prepareAnimation();
},
onUpdatePosition: function onUpdatePosition(args) {
that._updateContentPosition(args.offset);
},
onRollback: function onRollback() {
that._animateRollback();
},
onSelectionChanged: function onSelectionChanged(args) {
that.option("selectedItem", args.addedItems[0]);
},
swipeEnabled: this.option("swipeEnabled")
});
},
_initMarkup: function _initMarkup() {
this._renderContentTemplate();
this.callBase();
},
_render: function _render() {
this.callBase();
var selectedIndex = this.option("selectedIndex");
this._renderCurrentContent(selectedIndex, selectedIndex);
},
_renderContentTemplate: function _renderContentTemplate() {
if (isDefined(this._singleContent)) {
return;
}
this._getTemplateByOption("contentTemplate").render({
container: domUtils.getPublicElement(this._$itemWrapper)
});
this._singleContent = !this._$itemWrapper.is(":empty");
},
_renderDimensions: function _renderDimensions() {
this.callBase();
this.$element().toggleClass(PIVOT_AUTOHEIGHT_CLASS, this.option("height") === "auto");
},
_visibilityChanged: function _visibilityChanged(visible) {
if (visible) {
this._tabs._dimensionChanged();
}
},
_renderCurrentContent: function _renderCurrentContent(currentIndex, previousIndex) {
var itemsCache = this._itemsCache;
itemsCache[previousIndex] = this._selectedItemElement();
var $hidingItem = itemsCache[previousIndex],
$showingItem = itemsCache[currentIndex];
domUtils.triggerHidingEvent($hidingItem);
$hidingItem.addClass(PIVOT_ITEM_HIDDEN_CLASS);
if ($showingItem) {
$showingItem.removeClass(PIVOT_ITEM_HIDDEN_CLASS);
domUtils.triggerShownEvent($showingItem);
} else {
this._prepareContent();
this._renderContent();
}
this._selectionChangePromise && this._selectionChangePromise.resolve();
this._selectionChangePromise = new Deferred();
},
_updateContentPosition: function _updateContentPosition(offset) {
translator.move(this._$itemWrapper, { left: this._calculatePixelOffset(offset) });
},
_animateRollback: function _animateRollback() {
animation.returnBack(this._$itemWrapper);
},
_animateComplete: function _animateComplete(newIndex, currentIndex) {
var $itemWrapper = this._$itemWrapper,
rtlSignCorrection = this._getRTLSignCorrection(),
intermediatePosition = this._elementWidth() * (this._isPrevSwipeHandled() ? 1 : -1) * rtlSignCorrection;
animation.slideAway($itemWrapper, intermediatePosition, function () {
translator.move($itemWrapper, { left: -intermediatePosition });
this._renderCurrentContent(newIndex, currentIndex);
}.bind(this));
animation.slideBack($itemWrapper);
},
_calculatePixelOffset: function _calculatePixelOffset(offset) {
offset = offset || 0;
return offset * this._elementWidth();
},
_isPrevSwipeHandled: function _isPrevSwipeHandled() {
var wrapperOffset = translator.locate(this._$itemWrapper).left,
rtl = this.option("rtlEnabled");
return rtl ^ wrapperOffset > 0 && wrapperOffset !== 0;
},
_initSwipeHandlers: function _initSwipeHandlers() {
var $element = this.$element();
eventsEngine.on($element, eventUtils.addNamespace(swipeEvents.start, this.NAME), {
itemSizeFunc: this._elementWidth.bind(this)
}, this._swipeStartHandler.bind(this));
eventsEngine.on($element, eventUtils.addNamespace(swipeEvents.swipe, this.NAME), this._swipeUpdateHandler.bind(this));
eventsEngine.on($element, eventUtils.addNamespace(swipeEvents.end, this.NAME), this._swipeEndHandler.bind(this));
},
_swipeStartHandler: function _swipeStartHandler(e) {
this._prepareAnimation();
this._tabs.prepare();
if (config().designMode || this.option("disabled") || !this.option("swipeEnabled") || this._indexBoundary() <= 1) {
e.cancel = true;
} else {
this._swipeGestureRunning = true;
}
e.maxLeftOffset = 1;
e.maxRightOffset = 1;
},
_prepareAnimation: function _prepareAnimation() {
this._stopAnimation();
},
_stopAnimation: function _stopAnimation() {
animation.complete(this._$itemWrapper);
},
_swipeUpdateHandler: function _swipeUpdateHandler(e) {
var offset = e.offset;
this._updateContentPosition(offset);
this._tabs.updatePosition(offset);
},
_swipeEndHandler: function _swipeEndHandler(e) {
var targetOffset = e.targetOffset * this._getRTLSignCorrection();
if (targetOffset === 0) {
this._animateRollback();
this._tabs.rollback();
} else {
var newIndex = this._normalizeIndex(this.option("selectedIndex") - targetOffset);
this.option("selectedIndex", newIndex);
}
this._swipeGestureRunning = false;
},
_normalizeIndex: function _normalizeIndex(index) {
var boundary = this._indexBoundary();
if (index < 0) {
index = boundary + index;
}
if (index >= boundary) {
index = index - boundary;
}
return index;
},
_indexBoundary: function _indexBoundary() {
return this.option("items").length;
},
_renderContentImpl: function _renderContentImpl() {
if (this._singleContent) {
return;
}
var items = this.option("items"),
selectedIndex = this.option("selectedIndex");
if (items.length) {
this._renderItems([items[selectedIndex]]);
}
},
_selectedItemElement: function _selectedItemElement() {
return this._$itemWrapper.children("." + PIVOT_ITEM_CLASS + ":not(." + PIVOT_ITEM_HIDDEN_CLASS + ")");
},
_getRTLSignCorrection: function _getRTLSignCorrection() {
return this.option("rtlEnabled") ? -1 : 1;
},
_clean: function _clean() {
animation.complete(this._$itemWrapper);
this.callBase();
},
_cleanItemContainer: function _cleanItemContainer() {
if (this._singleContent) {
return;
}
this.callBase();
},
_refresh: function _refresh() {
this._tabs._refresh();
this.callBase();
},
_updateSelection: function _updateSelection(addedItems, removedItems) {
var newIndex = addedItems[0],
oldIndex = removedItems[0];
if (!this._swipeGestureRunning) {
this._prepareAnimation();
}
this._animateComplete(newIndex, oldIndex);
this._tabs.option("selectedIndex", newIndex);
},
_optionChanged: function _optionChanged(args) {
var value = args.value;
switch (args.name) {
case "disabled":
this._tabs.option("disabled", value);
this.callBase(args);
break;
case "items":
this._tabs.option(args.fullName, value);
this._clearItemsCache();
this.callBase(args);
break;
case "rtlEnabled":
this._tabs.option("rtlEnabled", value);
this._clearItemsCache();
this.callBase(args);
break;
case "itemTitleTemplate":
this._tabs.option("itemTemplate", this._getTemplate(value));
break;
case "swipeEnabled":
this._tabs.option("swipeEnabled", value);
break;
case "contentTemplate":
this._singleContent = null;
this._invalidate();
break;
default:
this.callBase(args);
}
}
/**
* @name dxPivotMethods.registerKeyHandler
* @publicName registerKeyHandler(key, handler)
* @hidden
* @inheritdoc
*/
/**
* @name dxPivotMethods.focus
* @publicName focus()
* @hidden
* @inheritdoc
*/
});
registerComponent("dxPivot", Pivot);
module.exports = Pivot;
///#DEBUG
module.exports.mockPivotTabs = function (Mock) {
PivotTabs = Mock;
};
module.exports.animation = animation;
///#ENDDEBUG