devextreme
Version:
HTML5 JavaScript Component Suite for Responsive Web Development
276 lines (218 loc) • 10.5 kB
JavaScript
"use strict";
var $ = require("../../core/renderer"),
eventsEngine = require("../../events/core/events_engine"),
noop = require("../../core/utils/common").noop,
clickEvent = require("../../events/click"),
messageLocalization = require("../../localization/message"),
translator = require("../../animation/translator"),
eventUtils = require("../../events/utils"),
feedbackEvents = require("../../events/core/emitter.feedback"),
EditDecoratorMenuHelperMixin = require("./ui.list.edit.decorator_menu_helper"),
registerDecorator = require("./ui.list.edit.decorator_registry").register,
SwitchableEditDecorator = require("./ui.list.edit.decorator.switchable"),
fx = require("../../animation/fx"),
themes = require("../themes"),
ActionSheet = require("../action_sheet");
var LIST_EDIT_DECORATOR = "dxListEditDecorator",
CLICK_EVENT_NAME = eventUtils.addNamespace(clickEvent.name, LIST_EDIT_DECORATOR),
ACTIVE_EVENT_NAME = eventUtils.addNamespace(feedbackEvents.active, LIST_EDIT_DECORATOR),
SLIDE_MENU_CLASS = "dx-list-slide-menu",
SLIDE_MENU_WRAPPER_CLASS = "dx-list-slide-menu-wrapper",
SLIDE_MENU_CONTENT_CLASS = "dx-list-slide-menu-content",
SLIDE_MENU_BUTTONS_CONTAINER_CLASS = "dx-list-slide-menu-buttons-container",
SLIDE_MENU_BUTTONS_CLASS = "dx-list-slide-menu-buttons",
SLIDE_MENU_BUTTON_CLASS = "dx-list-slide-menu-button",
SLIDE_MENU_BUTTON_MENU_CLASS = "dx-list-slide-menu-button-menu",
SLIDE_MENU_BUTTON_DELETE_CLASS = "dx-list-slide-menu-button-delete",
SLIDE_MENU_ANIMATION_DURATION = 400,
SLIDE_MENU_ANIMATION_EASING = "cubic-bezier(0.075, 0.82, 0.165, 1)";
registerDecorator("menu", "slide", SwitchableEditDecorator.inherit({
_shouldHandleSwipe: true,
_init: function _init() {
this.callBase.apply(this, arguments);
this._$buttonsContainer = $("<div>").addClass(SLIDE_MENU_BUTTONS_CONTAINER_CLASS);
eventsEngine.on(this._$buttonsContainer, ACTIVE_EVENT_NAME, noop);
this._$buttons = $("<div>").addClass(SLIDE_MENU_BUTTONS_CLASS).appendTo(this._$buttonsContainer);
this._renderMenu();
this._renderDeleteButton();
},
_renderMenu: function _renderMenu() {
if (!this._menuEnabled()) {
return;
}
var menuItems = this._menuItems();
if (menuItems.length === 1) {
var menuItem = menuItems[0];
this._renderMenuButton(menuItem.text, function (e) {
e.stopPropagation();
this._fireAction(menuItem);
}.bind(this));
} else {
var $menu = $("<div>").addClass(SLIDE_MENU_CLASS);
this._menu = this._list._createComponent($menu, ActionSheet, {
showTitle: false,
items: menuItems,
onItemClick: function (args) {
this._fireAction(args.itemData);
}.bind(this),
integrationOptions: {}
});
$menu.appendTo(this._list.$element());
var $menuButton = this._renderMenuButton(messageLocalization.format("dxListEditDecorator-more"), function (e) {
e.stopPropagation();
this._menu.show();
}.bind(this));
this._menu.option("target", $menuButton);
}
},
_renderMenuButton: function _renderMenuButton(text, action) {
var $menuButton = $("<div>").addClass(SLIDE_MENU_BUTTON_CLASS).addClass(SLIDE_MENU_BUTTON_MENU_CLASS).text(text);
this._$buttons.append($menuButton);
eventsEngine.on($menuButton, CLICK_EVENT_NAME, action);
return $menuButton;
},
_renderDeleteButton: function _renderDeleteButton() {
if (!this._deleteEnabled()) {
return;
}
var $deleteButton = $("<div>").addClass(SLIDE_MENU_BUTTON_CLASS).addClass(SLIDE_MENU_BUTTON_DELETE_CLASS).text(themes.isMaterial() ? "" : messageLocalization.format("dxListEditDecorator-delete"));
eventsEngine.on($deleteButton, CLICK_EVENT_NAME, function (e) {
e.stopPropagation();
this._deleteItem();
}.bind(this));
this._$buttons.append($deleteButton);
},
_fireAction: function _fireAction(menuItem) {
this._fireMenuAction($(this._cachedNode), menuItem.action);
this._cancelDeleteReadyItem();
},
modifyElement: function modifyElement(config) {
this.callBase.apply(this, arguments);
var $itemElement = config.$itemElement;
$itemElement.addClass(SLIDE_MENU_WRAPPER_CLASS);
var $slideMenuContent = $("<div>").addClass(SLIDE_MENU_CONTENT_CLASS);
$itemElement.wrapInner($slideMenuContent);
},
handleClick: function handleClick(_, e) {
if ($(e.target).closest("." + SLIDE_MENU_CONTENT_CLASS).length) {
return this.callBase.apply(this, arguments);
}
return false;
},
_swipeStartHandler: function _swipeStartHandler($itemElement) {
this._enablePositioning($itemElement);
this._cacheItemData($itemElement);
this._setPositions(this._getPositions(0));
},
_swipeUpdateHandler: function _swipeUpdateHandler($itemElement, args) {
var rtl = this._isRtlEnabled(),
signCorrection = rtl ? -1 : 1,
isItemReadyToDelete = this._isReadyToDelete($itemElement),
moveJustStarted = this._getCurrentPositions().content === this._getStartPositions().content;
if (moveJustStarted && !isItemReadyToDelete && args.offset * signCorrection > 0) {
args.cancel = true;
return;
}
var offset = this._cachedItemWidth * args.offset,
startOffset = isItemReadyToDelete ? -this._cachedButtonWidth * signCorrection : 0,
correctedOffset = (offset + startOffset) * signCorrection,
percent = correctedOffset < 0 ? Math.abs((offset + startOffset) / this._cachedButtonWidth) : 0;
this._setPositions(this._getPositions(percent));
return true;
},
_getStartPositions: function _getStartPositions() {
var rtl = this._isRtlEnabled(),
signCorrection = rtl ? -1 : 1;
return {
content: 0,
buttonsContainer: rtl ? -this._cachedButtonWidth : this._cachedItemWidth,
buttons: -this._cachedButtonWidth * signCorrection
};
},
_getPositions: function _getPositions(percent) {
var rtl = this._isRtlEnabled(),
signCorrection = rtl ? -1 : 1,
startPositions = this._getStartPositions();
return {
content: startPositions.content - percent * this._cachedButtonWidth * signCorrection,
buttonsContainer: startPositions.buttonsContainer - Math.min(percent, 1) * this._cachedButtonWidth * signCorrection,
buttons: startPositions.buttons + Math.min(percent, 1) * this._cachedButtonWidth * signCorrection
};
},
_getCurrentPositions: function _getCurrentPositions() {
return {
content: translator.locate(this._$cachedContent).left,
buttonsContainer: translator.locate(this._$buttonsContainer).left,
buttons: translator.locate(this._$buttons).left
};
},
_setPositions: function _setPositions(positions) {
translator.move(this._$cachedContent, { left: positions.content });
translator.move(this._$buttonsContainer, { left: positions.buttonsContainer });
translator.move(this._$buttons, { left: positions.buttons });
},
_cacheItemData: function _cacheItemData($itemElement) {
if ($itemElement[0] === this._cachedNode) {
return;
}
this._$cachedContent = $itemElement.find("." + SLIDE_MENU_CONTENT_CLASS);
this._cachedItemWidth = $itemElement.outerWidth();
this._cachedButtonWidth = this._cachedButtonWidth || this._$buttons.outerWidth();
this._$buttonsContainer.width(this._cachedButtonWidth);
if (this._$cachedContent.length) {
this._cachedNode = $itemElement[0];
}
},
_minButtonContainerLeftOffset: function _minButtonContainerLeftOffset() {
return this._cachedItemWidth - this._cachedButtonWidth;
},
_swipeEndHandler: function _swipeEndHandler($itemElement, args) {
this._cacheItemData($itemElement);
var signCorrection = this._isRtlEnabled() ? 1 : -1,
offset = this._cachedItemWidth * args.offset,
endedAtReadyToDelete = !this._isReadyToDelete($itemElement) && offset * signCorrection > this._cachedButtonWidth * 0.2,
readyToDelete = args.targetOffset === signCorrection && endedAtReadyToDelete;
this._toggleDeleteReady($itemElement, readyToDelete);
return true;
},
_enablePositioning: function _enablePositioning($itemElement) {
fx.stop(this._$cachedContent, true);
this.callBase.apply(this, arguments);
this._$buttonsContainer.appendTo($itemElement);
},
_disablePositioning: function _disablePositioning() {
this.callBase.apply(this, arguments);
this._$buttonsContainer.detach();
},
_animatePrepareDeleteReady: function _animatePrepareDeleteReady() {
return this._animateToPositions(this._getPositions(1));
},
_animateForgetDeleteReady: function _animateForgetDeleteReady($itemElement) {
this._cacheItemData($itemElement);
return this._animateToPositions(this._getPositions(0));
},
_animateToPositions: function _animateToPositions(positions) {
var that = this,
currentPosition = this._getCurrentPositions(),
durationTimePart = Math.min(Math.abs(currentPosition.content - positions.content) / this._cachedButtonWidth, 1);
return fx.animate(this._$cachedContent, {
from: currentPosition,
to: positions,
easing: SLIDE_MENU_ANIMATION_EASING,
duration: SLIDE_MENU_ANIMATION_DURATION * durationTimePart,
strategy: "frame",
draw: function draw(positions) {
that._setPositions(positions);
}
});
},
dispose: function dispose() {
if (this._menu) {
this._menu.$element().remove();
}
if (this._$buttonsContainer) {
this._$buttonsContainer.remove();
}
this.callBase.apply(this, arguments);
}
}).include(EditDecoratorMenuHelperMixin));