devextreme
Version:
HTML5 JavaScript Component Suite for Responsive Web Development
537 lines (534 loc) • 21.1 kB
JavaScript
/**
* DevExtreme (cjs/__internal/ui/drawer/m_drawer.js)
* Version: 24.2.6
* Build date: Mon Mar 17 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 _click = require("../../../common/core/events/click");
var _events_engine = _interopRequireDefault(require("../../../common/core/events/core/events_engine"));
var _visibility_change = require("../../../common/core/events/visibility_change");
var _component_registrator = _interopRequireDefault(require("../../../core/component_registrator"));
var _element = require("../../../core/element");
var _renderer = _interopRequireDefault(require("../../../core/renderer"));
var _empty_template = require("../../../core/templates/empty_template");
var _deferred = require("../../../core/utils/deferred");
var _position = require("../../../core/utils/position");
var _type = require("../../../core/utils/type");
var _window = require("../../../core/utils/window");
var _widget = _interopRequireDefault(require("../../core/widget/widget"));
var _m_drawer = require("../../ui/drawer/m_drawer.animation");
var _m_drawerRenderingStrategy = _interopRequireDefault(require("../../ui/drawer/m_drawer.rendering.strategy.overlap"));
var _m_drawerRenderingStrategy2 = _interopRequireDefault(require("../../ui/drawer/m_drawer.rendering.strategy.push"));
var _m_drawerRenderingStrategy3 = _interopRequireDefault(require("../../ui/drawer/m_drawer.rendering.strategy.shrink"));
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 DRAWER_CLASS = "dx-drawer";
const DRAWER_WRAPPER_CLASS = "dx-drawer-wrapper";
const DRAWER_PANEL_CONTENT_CLASS = "dx-drawer-panel-content";
const DRAWER_PANEL_CONTENT_HIDDEN_CLASS = "dx-drawer-panel-content-hidden";
const DRAWER_VIEW_CONTENT_CLASS = "dx-drawer-content";
const DRAWER_SHADER_CLASS = "dx-drawer-shader";
const INVISIBLE_STATE_CLASS = "dx-state-invisible";
const OPENED_STATE_CLASS = "dx-drawer-opened";
const ANONYMOUS_TEMPLATE_NAME = "content";
const PANEL_TEMPLATE_NAME = "panel";
class Drawer extends _widget.default {
_getDefaultOptions() {
return _extends({}, super._getDefaultOptions(), {
position: "left",
opened: false,
minSize: null,
maxSize: null,
shading: false,
template: "panel",
openedStateMode: "shrink",
revealMode: "slide",
animationEnabled: true,
animationDuration: 400,
closeOnOutsideClick: false,
contentTemplate: "content"
})
}
_init() {
super._init();
this._initStrategy();
this.$element().addClass("dx-drawer");
this._whenAnimationCompleted = void 0;
this._whenPanelContentRendered = void 0;
this._whenPanelContentRefreshed = void 0;
this._$wrapper = (0, _renderer.default)("<div>").addClass("dx-drawer-wrapper");
this._$viewContentWrapper = (0, _renderer.default)("<div>").addClass("dx-drawer-content");
this._$wrapper.append(this._$viewContentWrapper);
this.$element().append(this._$wrapper)
}
_initStrategy() {
const {
openedStateMode: openedStateMode
} = this.option();
switch (openedStateMode) {
case "push":
default:
this._strategy = new _m_drawerRenderingStrategy2.default(this);
break;
case "shrink":
this._strategy = new _m_drawerRenderingStrategy3.default(this);
break;
case "overlap":
this._strategy = new _m_drawerRenderingStrategy.default(this)
}
}
_getAnonymousTemplateName() {
return "content"
}
_initTemplates() {
const defaultTemplates = {};
defaultTemplates.panel = new _empty_template.EmptyTemplate;
defaultTemplates.content = new _empty_template.EmptyTemplate;
this._templateManager.addDefaultTemplates(defaultTemplates);
super._initTemplates()
}
_viewContentWrapperClickHandler(e) {
let closeOnOutsideClick = this.option("closeOnOutsideClick");
if ((0, _type.isFunction)(closeOnOutsideClick)) {
closeOnOutsideClick = closeOnOutsideClick(e)
}
if (closeOnOutsideClick && this.option("opened")) {
this.stopAnimations();
if (this.option("shading")) {
e.preventDefault()
}
this.hide()
}
}
_initMarkup() {
super._initMarkup();
const {
opened: opened
} = this.option();
this._toggleOpenedStateClass(opened);
this._renderPanelContentWrapper();
this._refreshOpenedStateModeClass();
this._refreshRevealModeClass();
this._renderShader();
this._refreshPositionClass();
this._whenPanelContentRendered = (0, _deferred.Deferred)();
this._strategy.renderPanelContent(this._whenPanelContentRendered);
this._strategy.onPanelContentRendered();
this._renderViewContent();
_events_engine.default.off(this._$viewContentWrapper, _click.name);
_events_engine.default.on(this._$viewContentWrapper, _click.name, this._viewContentWrapperClickHandler.bind(this));
this._refreshWrapperChildrenOrder()
}
_render() {
var _this$_whenPanelConte;
this._initMinMaxSize();
super._render();
null === (_this$_whenPanelConte = this._whenPanelContentRendered) || void 0 === _this$_whenPanelConte || _this$_whenPanelConte.always((() => {
this._initMinMaxSize();
const {
revealMode: revealMode,
opened: opened
} = this.option();
this._strategy.refreshPanelElementSize("slide" === revealMode);
this._renderPosition(opened, true);
this._removePanelManualPosition()
}))
}
_removePanelManualPosition() {
if (this._$panelContentWrapper.attr("manualposition")) {
this._$panelContentWrapper.removeAttr("manualPosition");
this._$panelContentWrapper.css({
position: "",
top: "",
left: "",
right: "",
bottom: ""
})
}
}
_togglePanelContentHiddenClass() {
const callback = () => {
const {
minSize: minSize,
opened: opened
} = this.option();
const shouldBeSet = minSize ? false : !opened;
this._$panelContentWrapper.toggleClass("dx-drawer-panel-content-hidden", shouldBeSet)
};
if (this._whenAnimationCompleted && !this.option("opened")) {
(0, _deferred.when)(this._whenAnimationCompleted).done(callback)
} else {
callback()
}
}
_renderPanelContentWrapper() {
const {
openedStateMode: openedStateMode,
opened: opened,
minSize: minSize
} = this.option();
this._$panelContentWrapper = (0, _renderer.default)("<div>").addClass("dx-drawer-panel-content");
this._togglePanelContentHiddenClass();
const position = this.calcTargetPosition();
if ("push" === openedStateMode && ["top", "bottom"].includes(position)) {
this._$panelContentWrapper.addClass("dx-drawer-panel-content-push-top-or-bottom")
}
if ("overlap" !== openedStateMode && !opened && !minSize) {
this._$panelContentWrapper.attr("manualposition", true);
this._$panelContentWrapper.css({
position: "absolute",
top: "-10000px",
left: "-10000px",
right: "auto",
bottom: "auto"
})
}
this._$wrapper.append(this._$panelContentWrapper)
}
_refreshOpenedStateModeClass(prevOpenedStateMode) {
if (prevOpenedStateMode) {
this.$element().removeClass(`dx-drawer-${prevOpenedStateMode}`)
}
const {
openedStateMode: openedStateMode
} = this.option();
this.$element().addClass(`dx-drawer-${openedStateMode}`)
}
_refreshPositionClass() {
this.$element().removeClass(["left", "right", "top", "bottom"].map((position => `dx-drawer-${position}`)).join(" ")).addClass(`dx-drawer-${this.calcTargetPosition()}`)
}
_refreshWrapperChildrenOrder() {
const position = this.calcTargetPosition();
if (this._strategy.isViewContentFirst(position, this.option("rtlEnabled"))) {
this._$wrapper.prepend(this._$viewContentWrapper)
} else {
this._$wrapper.prepend(this._$panelContentWrapper)
}
}
_refreshRevealModeClass(prevRevealMode) {
if (prevRevealMode) {
this.$element().removeClass(`dx-drawer-${prevRevealMode}`)
}
const {
revealMode: revealMode
} = this.option();
this.$element().addClass(`dx-drawer-${revealMode}`)
}
_renderViewContent() {
const contentTemplateOption = this.option("contentTemplate");
const contentTemplate = this._getTemplate(contentTemplateOption);
if (contentTemplate) {
const $viewTemplate = contentTemplate.render({
container: this.viewContent(),
noModel: true,
transclude: this._templateManager.anonymousTemplateName === contentTemplateOption
});
if ($viewTemplate.hasClass("ng-scope")) {
(0, _renderer.default)(this._$viewContentWrapper).children().not(".dx-drawer-shader").replaceWith($viewTemplate)
}
}
}
_renderShader() {
this._$shader = this._$shader || (0, _renderer.default)("<div>").addClass("dx-drawer-shader");
this._$shader.appendTo(this.viewContent());
const {
opened: opened
} = this.option();
this._toggleShaderVisibility(opened)
}
_initSize() {
this._initMinMaxSize()
}
_initMinMaxSize() {
const realPanelSize = this.isHorizontalDirection() ? this.getRealPanelWidth() : this.getRealPanelHeight();
const {
maxSize: maxSize,
minSize: minSize
} = this.option();
this._maxSize = maxSize || realPanelSize;
this._minSize = minSize || 0
}
calcTargetPosition() {
const {
position: position,
rtlEnabled: rtlEnabled
} = this.option();
if ("before" === position) {
return rtlEnabled ? "right" : "left"
}
if ("after" === position) {
return rtlEnabled ? "left" : "right"
}
return position
}
getOverlayTarget() {
return this._$wrapper
}
getOverlay() {
return this._overlay
}
getMaxSize() {
return this._maxSize
}
getMinSize() {
return this._minSize
}
getRealPanelWidth() {
if ((0, _window.hasWindow)()) {
const {
templateSize: templateSize
} = this.option();
if ((0, _type.isDefined)(templateSize)) {
return templateSize
}
return (0, _position.getBoundingRect)(this._getPanelTemplateElement()).width
}
return 0
}
getRealPanelHeight() {
if ((0, _window.hasWindow)()) {
const {
templateSize: templateSize
} = this.option();
if ((0, _type.isDefined)(templateSize)) {
return templateSize
}
return (0, _position.getBoundingRect)(this._getPanelTemplateElement()).height
}
return 0
}
_getPanelTemplateElement() {
const $panelContent = this._strategy.getPanelContent();
let $result = $panelContent;
if ($panelContent.children().length) {
$result = $panelContent.children().eq(0);
if ($panelContent.hasClass("dx-overlay-content") && $result.hasClass("dx-template-wrapper") && $result.children().length) {
$result = $result.children().eq(0)
}
}
return $result.get(0)
}
getElementHeight($element) {
const $children = $element.children();
return $children.length ? (0, _position.getBoundingRect)($children.eq(0).get(0)).height : (0, _position.getBoundingRect)($element.get(0)).height
}
isHorizontalDirection() {
const position = this.calcTargetPosition();
return "left" === position || "right" === position
}
stopAnimations(jumpToEnd) {
_animation.fx.stop(this._$shader, jumpToEnd);
_animation.fx.stop((0, _renderer.default)(this.content()), jumpToEnd);
_animation.fx.stop((0, _renderer.default)(this.viewContent()), jumpToEnd);
const overlay = this.getOverlay();
if (overlay) {
_animation.fx.stop((0, _renderer.default)(overlay.$content()), jumpToEnd)
}
}
setZIndex(zIndex) {
this._$shader.css("zIndex", zIndex - 1);
this._$panelContentWrapper.css("zIndex", zIndex)
}
resizeContent() {
this.resizeViewContent
}
resizeViewContent() {
(0, _visibility_change.triggerResizeEvent)(this.viewContent())
}
_isInvertedPosition() {
const position = this.calcTargetPosition();
return "right" === position || "bottom" === position
}
_renderPosition(isDrawerOpened, disableAnimation, jumpToEnd) {
this.stopAnimations(jumpToEnd);
this._whenAnimationCompleted = (0, _deferred.Deferred)();
let {
animationEnabled: animationEnabled
} = this.option();
if (true === disableAnimation) {
animationEnabled = false
}
if (!animationEnabled) {
this._whenAnimationCompleted.resolve()
}
if (!(0, _window.hasWindow)()) {
return
}(0, _renderer.default)(this.viewContent()).css("paddingLeft", 0);
(0, _renderer.default)(this.viewContent()).css("paddingRight", 0);
(0, _renderer.default)(this.viewContent()).css("paddingTop", 0);
(0, _renderer.default)(this.viewContent()).css("paddingBottom", 0);
if (isDrawerOpened) {
this._toggleShaderVisibility(isDrawerOpened)
}
this._strategy.renderPosition(animationEnabled, this.option("animationDuration"))
}
_animationCompleteHandler() {
var _this$_whenAnimationC;
this.resizeViewContent();
null === (_this$_whenAnimationC = this._whenAnimationCompleted) || void 0 === _this$_whenAnimationC || _this$_whenAnimationC.resolve()
}
_getPositionCorrection() {
return this._isInvertedPosition() ? -1 : 1
}
_dispose() {
_m_drawer.animation.complete((0, _renderer.default)(this.viewContent()));
super._dispose()
}
_visibilityChanged(visible) {
if (visible) {
this._dimensionChanged()
}
}
_dimensionChanged() {
this._initMinMaxSize();
const {
revealMode: revealMode
} = this.option();
this._strategy.refreshPanelElementSize("slide" === revealMode);
this._renderPosition(this.option("opened"), true)
}
_toggleShaderVisibility(visible) {
if (this.option("shading")) {
this._$shader.toggleClass("dx-state-invisible", !visible);
this._$shader.css("visibility", visible ? "visible" : "hidden")
} else {
this._$shader.toggleClass("dx-state-invisible", true)
}
}
_toggleOpenedStateClass(opened) {
this.$element().toggleClass("dx-drawer-opened", opened)
}
_refreshPanel() {
(0, _renderer.default)(this.viewContent()).css("left", 0);
(0, _renderer.default)(this.viewContent()).css("transform", "translate(0px, 0px)");
(0, _renderer.default)(this.viewContent()).removeClass("dx-theme-background-color");
this._removePanelContentWrapper();
this._removeOverlay();
this._renderPanelContentWrapper();
this._refreshWrapperChildrenOrder();
this._whenPanelContentRefreshed = (0, _deferred.Deferred)();
this._strategy.renderPanelContent(this._whenPanelContentRefreshed);
this._strategy.onPanelContentRendered();
if ((0, _window.hasWindow)()) {
this._whenPanelContentRefreshed.always((() => {
const {
revealMode: revealMode
} = this.option();
this._strategy.refreshPanelElementSize("slide" === revealMode);
this._renderPosition(this.option("opened"), true, true);
this._removePanelManualPosition()
}))
}
}
_clean() {
this._cleanFocusState();
this._removePanelContentWrapper();
this._removeOverlay()
}
_removePanelContentWrapper() {
if (this._$panelContentWrapper) {
this._$panelContentWrapper.remove()
}
}
_removeOverlay() {
if (this._overlay) {
this._overlay.dispose();
delete this._overlay;
delete this._$panelContentWrapper
}
}
_optionChanged(args) {
switch (args.name) {
case "width":
super._optionChanged(args);
this._dimensionChanged();
break;
case "opened":
this._renderPosition(this.option("opened"));
this._toggleOpenedStateClass(args.value);
this._togglePanelContentHiddenClass();
break;
case "position":
this._refreshPositionClass();
this._refreshWrapperChildrenOrder();
this._invalidate();
break;
case "contentTemplate":
case "template":
this._invalidate();
break;
case "openedStateMode":
this._initStrategy();
this._refreshOpenedStateModeClass(args.previousValue);
this._refreshPanel();
break;
case "minSize":
this._initMinMaxSize();
this._renderPosition(this.option("opened"), true);
this._togglePanelContentHiddenClass();
break;
case "maxSize":
this._initMinMaxSize();
this._renderPosition(this.option("opened"), true);
break;
case "revealMode":
this._refreshRevealModeClass(args.previousValue);
this._refreshPanel();
break;
case "shading": {
const {
opened: opened
} = this.option();
this._toggleShaderVisibility(opened);
break
}
case "animationEnabled":
case "animationDuration":
case "closeOnOutsideClick":
break;
default:
super._optionChanged(args)
}
}
content() {
return (0, _element.getPublicElement)(this._$panelContentWrapper)
}
viewContent() {
return (0, _element.getPublicElement)(this._$viewContentWrapper)
}
show() {
return this.toggle(true)
}
hide() {
return this.toggle(false)
}
toggle(opened) {
var _this$_whenAnimationC2;
const targetOpened = void 0 === opened ? !this.option("opened") : opened;
this.option("opened", targetOpened);
return null === (_this$_whenAnimationC2 = this._whenAnimationCompleted) || void 0 === _this$_whenAnimationC2 ? void 0 : _this$_whenAnimationC2.promise()
}
}(0, _component_registrator.default)("dxDrawer", Drawer);
var _default = exports.default = Drawer;