UNPKG

devextreme

Version:

HTML5 JavaScript Component Suite for Responsive Web Development

1,538 lines (1,269 loc) • 49.8 kB
"use strict"; var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; var $ = require("../core/renderer"), domAdapter = require("../core/dom_adapter"), windowUtils = require("../core/utils/window"), ready = require("../core/utils/ready_callbacks").add, window = windowUtils.getWindow(), navigator = windowUtils.getNavigator(), eventsEngine = require("../events/core/events_engine"), fx = require("../animation/fx"), translator = require("../animation/translator"), compareVersions = require("../core/utils/version").compare, viewPortUtils = require("../core/utils/view_port"), extend = require("../core/utils/extend").extend, inArray = require("../core/utils/array").inArray, getPublicElement = require("../core/utils/dom").getPublicElement, viewPortChanged = viewPortUtils.changeCallback, hideTopOverlayCallback = require("../mobile/hide_top_overlay").hideCallback, positionUtils = require("../animation/position"), fitIntoRange = require("../core/utils/math").fitIntoRange, domUtils = require("../core/utils/dom"), noop = require("../core/utils/common").noop, typeUtils = require("../core/utils/type"), each = require("../core/utils/iterator").each, devices = require("../core/devices"), browser = require("../core/utils/browser"), registerComponent = require("../core/component_registrator"), Widget = require("./widget/ui.widget"), KeyboardProcessor = require("./widget/ui.keyboard_processor"), selectors = require("./widget/selectors"), dragEvents = require("../events/drag"), eventUtils = require("../events/utils"), pointerEvents = require("../events/pointer"), Resizable = require("./resizable"), EmptyTemplate = require("./widget/empty_template"), Deferred = require("../core/utils/deferred").Deferred; var OVERLAY_CLASS = "dx-overlay", OVERLAY_WRAPPER_CLASS = "dx-overlay-wrapper", OVERLAY_CONTENT_CLASS = "dx-overlay-content", OVERLAY_SHADER_CLASS = "dx-overlay-shader", OVERLAY_MODAL_CLASS = "dx-overlay-modal", INVISIBLE_STATE_CLASS = "dx-state-invisible", ANONYMOUS_TEMPLATE_NAME = "content", RTL_DIRECTION_CLASS = "dx-rtl", ACTIONS = ["onShowing", "onShown", "onHiding", "onHidden", "onPositioning", "onPositioned", "onResizeStart", "onResize", "onResizeEnd"], FIRST_Z_INDEX = 1500, OVERLAY_STACK = [], DISABLED_STATE_CLASS = "dx-state-disabled", TAB_KEY = 9, POSITION_ALIASES = { "top": { my: "top center", at: "top center" }, "bottom": { my: "bottom center", at: "bottom center" }, "right": { my: "right center", at: "right center" }, "left": { my: "left center", at: "left center" }, "center": { my: 'center', at: 'center' }, "right bottom": { my: 'right bottom', at: 'right bottom' }, "right top": { my: 'right top', at: 'right top' }, "left bottom": { my: 'left bottom', at: 'left bottom' }, "left top": { my: 'left top', at: 'left top' } }; var realDevice = devices.real(), realVersion = realDevice.version, firefoxDesktop = browser.mozilla && realDevice.deviceType === "desktop", iOS = realDevice.platform === "ios", iOS7_0andBelow = iOS && compareVersions(realVersion, [7, 1]) < 0, android4_0nativeBrowser = realDevice.platform === "android" && compareVersions(realVersion, [4, 0], 2) === 0 && navigator.userAgent.indexOf("Chrome") === -1; var forceRepaint = function forceRepaint($element) { // NOTE: force layout recalculation on iOS 6 & iOS 7.0 (B254713) and FF desktop (T581681) if (iOS7_0andBelow || firefoxDesktop) { $element.width(); } // NOTE: force rendering on buggy android (T112083) if (android4_0nativeBrowser) { var $parents = $element.parents(), inScrollView = $parents.is(".dx-scrollable-native"); if (!inScrollView) { $parents.css("backfaceVisibility", "hidden"); $parents.css("backfaceVisibility"); $parents.css("backfaceVisibility", "visible"); } } }; var getElement = function getElement(value) { return value && $(value.target || value); }; ready(function () { eventsEngine.subscribeGlobal(domAdapter.getDocument(), pointerEvents.down, function (e) { for (var i = OVERLAY_STACK.length - 1; i >= 0; i--) { if (!OVERLAY_STACK[i]._proxiedDocumentDownHandler(e)) { return; } } }); }); /** * @name dxOverlay * @publicName dxOverlay * @type object * @inherits Widget * @hidden */ var Overlay = Widget.inherit({ _supportedKeys: function _supportedKeys() { var offsetSize = 5, move = function move(top, left, e) { if (!this.option("dragEnabled")) { return; } e.preventDefault(); e.stopPropagation(); var allowedOffsets = this._allowedOffsets(); var offset = { top: fitIntoRange(top, -allowedOffsets.top, allowedOffsets.bottom), left: fitIntoRange(left, -allowedOffsets.left, allowedOffsets.right) }; this._changePosition(offset); }; return extend(this.callBase(), { escape: function escape() { this.hide(); }, upArrow: move.bind(this, -offsetSize, 0), downArrow: move.bind(this, offsetSize, 0), leftArrow: move.bind(this, 0, -offsetSize), rightArrow: move.bind(this, 0, offsetSize) }); }, _getDefaultOptions: function _getDefaultOptions() { return extend(this.callBase(), { /** * @name dxOverlayOptions.activeStateEnabled * @publicName activeStateEnabled * @hidden * @inheritdoc */ activeStateEnabled: false, /** * @name dxOverlayOptions.visible * @publicName visible * @type Boolean * @default false * @fires dxOverlayOptions.onShowing * @fires dxOverlayOptions.onHiding */ visible: false, /** * @name dxOverlayOptions.deferRendering * @publicName deferRendering * @type Boolean * @default true */ deferRendering: true, /** * @name dxOverlayOptions.shading * @publicName shading * @type Boolean * @default true */ shading: true, /** * @name dxOverlayOptions.shadingColor * @publicName shadingColor * @type string * @default '' */ shadingColor: "", /** * @name dxOverlayOptions.position * @publicName position * @default { my: 'center', at: 'center', of: window } */ position: { my: "center", at: "center" }, /** * @name dxOverlayOptions.width * @publicName width * @type number|string|function * @default function() {return $(window).width() * 0.8 } * @type_function_return number|string */ width: function width() { return $(window).width() * 0.8; }, /** * @name dxOverlayOptions.minWidth * @publicName minWidth * @type number|string|function * @default null * @type_function_return number|string */ minWidth: null, /** * @name dxOverlayOptions.maxWidth * @publicName maxWidth * @type number|string|function * @default null * @type_function_return number|string */ maxWidth: null, /** * @name dxOverlayOptions.height * @publicName height * @type number|string|function * @default function() { return $(window).height() * 0.8 } * @type_function_return number|string */ height: function height() { return $(window).height() * 0.8; }, /** * @name dxOverlayOptions.minHeight * @publicName minHeight * @type number|string|function * @default null * @type_function_return number|string */ minHeight: null, /** * @name dxOverlayOptions.maxHeight * @publicName maxHeight * @type number|string|function * @default null * @type_function_return number|string */ maxHeight: null, /** * @name dxOverlayOptions.animation * @publicName animation * @type object * @default { show: { type: "pop", duration: 300, from: { scale: 0.55 } }, hide: { type: "pop", duration: 300, to: { opacity: 0, scale: 0.55 }, from: { opacity: 1, scale: 1 } } } * @ref */ animation: { /** * @name dxOverlayOptions.animation.show * @publicName show * @type animationConfig * @default { type: "pop", duration: 400, from: { scale: 0.55 } } */ show: { type: "pop", duration: 300, from: { scale: 0.55 } }, /** * @name dxOverlayOptions.animation.hide * @publicName hide * @type animationConfig * @default { type: "pop", duration: 300, to: { opacity: 0, scale: 0.55 }, from: { opacity: 1, scale: 1 } } } */ hide: { type: "pop", duration: 300, to: { opacity: 0, scale: 0.55 }, from: { opacity: 1, scale: 1 } } }, /** * @name dxOverlayOptions.closeOnOutsideClick * @publicName closeOnOutsideClick * @type boolean|function * @default false * @type_function_param1 event:event * @type_function_return Boolean */ closeOnOutsideClick: false, /** * @name dxOverlayOptions.closeOnBackButton * @publicName closeOnBackButton * @type boolean * @default true */ closeOnBackButton: true, /** * @name dxOverlayOptions.onShowing * @publicName onShowing * @extends Action * @action */ onShowing: null, /** * @name dxOverlayOptions.onShown * @publicName onShown * @extends Action * @action */ onShown: null, /** * @name dxOverlayOptions.onHiding * @publicName onHiding * @extends Action * @type function(e) * @type_function_param1 e:object * @type_function_param1_field4 cancel:boolean * @action */ onHiding: null, /** * @name dxOverlayOptions.onHidden * @publicName onHidden * @extends Action * @action */ onHidden: null, /** * @name dxOverlayOptions.contentTemplate * @publicName contentTemplate * @type template|function * @default "content" * @type_function_param1 contentElement:dxElement * @type_function_return string|Node|jQuery */ contentTemplate: "content", /** * @name dxOverlayOptions.dragEnabled * @publicName dragEnabled * @type boolean * @default false */ dragEnabled: false, resizeEnabled: false, onResizeStart: null, onResize: null, onResizeEnd: null, // NOTE: private options target: undefined, container: undefined, hideTopOverlayHandler: undefined, closeOnTargetScroll: false, onPositioned: null, boundaryOffset: { h: 0, v: 0 }, propagateOutsideClick: false, _checkParentVisibility: true }); }, _defaultOptionsRules: function _defaultOptionsRules() { return this.callBase().concat([{ device: function device() { var realDevice = devices.real(), realPlatform = realDevice.platform, realVersion = realDevice.version; return realPlatform === "android" && compareVersions(realVersion, [4, 2]) < 0; }, options: { /** * @name dxOverlayOptions.animation * @publicName animation * @default { show: { type: 'fade', duration: 400 }, hide: { type: 'fade', duration: 400, to: { opacity: 0 }, from: { opacity: 1 } }} @for Android_below_version_4.2 */ animation: { show: { type: "fade", duration: 400 }, hide: { type: "fade", duration: 400, to: { opacity: 0 }, from: { opacity: 1 } } } } }, { device: function device() { return !windowUtils.hasWindow(); }, options: { width: null, height: null, animation: null, _checkParentVisibility: false } }]); }, _setOptionsByReference: function _setOptionsByReference() { this.callBase(); extend(this._optionsByReference, { animation: true }); }, _getAnonymousTemplateName: function _getAnonymousTemplateName() { return ANONYMOUS_TEMPLATE_NAME; }, _wrapper: function _wrapper() { return this._$wrapper; }, _container: function _container() { return this._$content; }, _eventBindingTarget: function _eventBindingTarget() { return this._$content; }, _init: function _init() { this.callBase(); this._initActions(); this._initCloseOnOutsideClickHandler(); this._initTabTerminatorHandler(); this._$wrapper = $("<div>").addClass(OVERLAY_WRAPPER_CLASS); this._$content = $("<div>").addClass(OVERLAY_CONTENT_CLASS); var $element = this.$element(); this._$wrapper.addClass($element.attr("class")); $element.addClass(OVERLAY_CLASS); this._$wrapper.attr("data-bind", "dxControlsDescendantBindings: true"); // NOTE: hack to fix B251087 eventsEngine.on(this._$wrapper, "MSPointerDown", noop); // NOTE: bootstrap integration T342292 eventsEngine.on(this._$wrapper, "focusin", function (e) { e.stopPropagation(); }); this._toggleViewPortSubscription(true); }, _initOptions: function _initOptions(options) { this._initTarget(options.target); this._initContainer(options.container); this._initHideTopOverlayHandler(options.hideTopOverlayHandler); this.callBase(options); }, _initTarget: function _initTarget(target) { if (!typeUtils.isDefined(target)) { return; } var options = this.option(); each(["position.of", "animation.show.from.position.of", "animation.show.to.position.of", "animation.hide.from.position.of", "animation.hide.to.position.of"], function (_, path) { var pathParts = path.split("."); var option = options; while (option) { if (pathParts.length === 1) { if (typeUtils.isPlainObject(option)) { option[pathParts.shift()] = target; } break; } else { option = option[pathParts.shift()]; } } }); }, _initContainer: function _initContainer(container) { container = container === undefined ? viewPortUtils.value() : container; var $element = this.$element(), $container = $element.closest(container); if (!$container.length) { $container = $(container).first(); } this._$container = $container.length ? $container : $element.parent(); }, _initHideTopOverlayHandler: function _initHideTopOverlayHandler(handler) { this._hideTopOverlayHandler = handler !== undefined ? handler : this._defaultHideTopOverlayHandler.bind(this); }, _defaultHideTopOverlayHandler: function _defaultHideTopOverlayHandler() { this.hide(); }, _initActions: function _initActions() { this._actions = {}; each(ACTIONS, function (_, action) { this._actions[action] = this._createActionByOption(action, { excludeValidators: ["disabled", "readOnly"] }) || noop; }.bind(this)); }, _initCloseOnOutsideClickHandler: function _initCloseOnOutsideClickHandler() { var that = this; this._proxiedDocumentDownHandler = function () { return that._documentDownHandler.apply(that, arguments); }; }, _documentDownHandler: function _documentDownHandler(e) { if (this._showAnimationProcessing) { this._stopAnimation(); } var closeOnOutsideClick = this.option("closeOnOutsideClick"); if (typeUtils.isFunction(closeOnOutsideClick)) { closeOnOutsideClick = closeOnOutsideClick(e); } if (closeOnOutsideClick) { var $container = this._$content, outsideClick = !$container.is(e.target) && !domUtils.contains($container.get(0), e.target) && $(e.target).closest(window.document).length; if (outsideClick) { if (this.option("shading")) { e.preventDefault(); } this.hide(); } } return this.option("propagateOutsideClick"); }, _initTemplates: function _initTemplates() { this.callBase(); this._defaultTemplates["content"] = new EmptyTemplate(this); }, _isTopOverlay: function _isTopOverlay() { var overlayStack = this._overlayStack(); for (var i = overlayStack.length - 1; i >= 0; i--) { var $tabbableElements = overlayStack[i]._findTabbableElements(); if ($tabbableElements.length) { return overlayStack[i] === this; } } return false; }, _overlayStack: function _overlayStack() { return OVERLAY_STACK; }, _zIndexInitValue: function _zIndexInitValue() { return FIRST_Z_INDEX; }, _toggleViewPortSubscription: function _toggleViewPortSubscription(toggle) { viewPortChanged.remove(this._viewPortChangeHandle); if (toggle) { this._viewPortChangeHandle = this._viewPortChangeHandler.bind(this); viewPortChanged.add(this._viewPortChangeHandle); } }, _viewPortChangeHandler: function _viewPortChangeHandler() { this._initContainer(this.option("container")); this._refresh(); }, _renderVisibilityAnimate: function _renderVisibilityAnimate(visible) { this._stopAnimation(); return visible ? this._show() : this._hide(); }, _normalizePosition: function _normalizePosition() { var position = this.option("position"); this._position = typeof position === "function" ? position() : position; }, _getAnimationConfig: function _getAnimationConfig() { var animation = this.option("animation"); if (typeUtils.isFunction(animation)) animation = animation.call(this); return animation; }, _show: function _show() { var that = this, deferred = new Deferred(); this._parentHidden = this._isParentHidden(); deferred.done(function () { delete that._parentHidden; }); if (this._parentHidden) { return deferred.resolve(); } if (this._currentVisible) { return new Deferred().resolve().promise(); } this._currentVisible = true; this._normalizePosition(); var animation = that._getAnimationConfig() || {}, showAnimation = this._normalizeAnimation(animation.show, "to"), startShowAnimation = showAnimation && showAnimation.start || noop, completeShowAnimation = showAnimation && showAnimation.complete || noop; if (this._isHidingActionCanceled) { delete this._isHidingActionCanceled; deferred.resolve(); } else { var show = function () { this._renderVisibility(true); this._animate(showAnimation, function () { if (that.option("focusStateEnabled")) { eventsEngine.trigger(that._focusTarget(), "focus"); } completeShowAnimation.apply(this, arguments); that._showAnimationProcessing = false; that._actions.onShown(); deferred.resolve(); }, function () { startShowAnimation.apply(this, arguments); that._showAnimationProcessing = true; }); }.bind(this); if (this.option("templatesRenderAsynchronously")) { this._asyncShowTimeout = setTimeout(show); } else { show(); } } return deferred.promise(); }, _normalizeAnimation: function _normalizeAnimation(animation, prop) { if (animation) { animation = extend({ type: "slide" }, animation); if (animation[prop] && _typeof(animation[prop]) === "object") { extend(animation[prop], { position: this._position }); } } return animation; }, _hide: function _hide() { if (!this._currentVisible) { return new Deferred().resolve().promise(); } this._currentVisible = false; var that = this, deferred = new Deferred(), animation = that._getAnimationConfig() || {}, hideAnimation = this._normalizeAnimation(animation.hide, "from"), startHideAnimation = hideAnimation && hideAnimation.start || noop, completeHideAnimation = hideAnimation && hideAnimation.complete || noop, hidingArgs = { cancel: false }; this._actions.onHiding(hidingArgs); if (hidingArgs.cancel) { this._isHidingActionCanceled = true; this.option("visible", true); deferred.resolve(); } else { this._forceFocusLost(); this._toggleShading(false); this._toggleSubscriptions(false); this._animate(hideAnimation, function () { that._$content.css("pointerEvents", ""); that._renderVisibility(false); completeHideAnimation.apply(this, arguments); that._actions.onHidden(); deferred.resolve(); }, function () { that._$content.css("pointerEvents", "none"); startHideAnimation.apply(this, arguments); }); } return deferred.promise(); }, _forceFocusLost: function _forceFocusLost() { var activeElement = domAdapter.getActiveElement(); activeElement && this._$content.find(activeElement).length && activeElement.blur(); }, _animate: function _animate(animation, completeCallback, startCallback) { if (animation) { startCallback = startCallback || animation.start || noop; fx.animate(this._$content, extend({}, animation, { start: startCallback, complete: completeCallback })); } else { completeCallback(); } }, _stopAnimation: function _stopAnimation() { fx.stop(this._$content, true); }, _renderVisibility: function _renderVisibility(visible) { if (visible && this._isParentHidden()) { return; } this._currentVisible = visible; this._stopAnimation(); clearTimeout(this._asyncShowTimeout); if (!visible) { domUtils.triggerHidingEvent(this._$content); } this._toggleVisibility(visible); this._$content.toggleClass(INVISIBLE_STATE_CLASS, !visible); this._updateZIndexStackPosition(visible); if (visible) { this._renderContent(); this._actions.onShowing(); this._moveToContainer(); this._renderGeometry(); domUtils.triggerShownEvent(this._$content); domUtils.triggerResizeEvent(this._$content); } else { this._moveFromContainer(); } this._toggleShading(visible); this._toggleSubscriptions(visible); }, _updateZIndexStackPosition: function _updateZIndexStackPosition(pushToStack) { var overlayStack = this._overlayStack(), index = inArray(this, overlayStack); if (pushToStack) { if (index === -1) { var length = overlayStack.length; this._zIndex = (length ? overlayStack[length - 1]._zIndex : this._zIndexInitValue()) + 1; overlayStack.push(this); } this._$wrapper.css("zIndex", this._zIndex); this._$content.css("zIndex", this._zIndex); } else if (index !== -1) { overlayStack.splice(index, 1); } }, _toggleShading: function _toggleShading(visible) { this._$wrapper.toggleClass(OVERLAY_MODAL_CLASS, this.option("shading") && !this.option("container")); this._$wrapper.toggleClass(OVERLAY_SHADER_CLASS, visible && this.option("shading")); this._$wrapper.css("backgroundColor", this.option("shading") ? this.option("shadingColor") : ""); this._toggleTabTerminator(visible && this.option("shading")); }, _initTabTerminatorHandler: function _initTabTerminatorHandler() { var that = this; this._proxiedTabTerminatorHandler = function () { that._tabKeyHandler.apply(that, arguments); }; }, _toggleTabTerminator: function _toggleTabTerminator(enabled) { var eventName = eventUtils.addNamespace("keydown", this.NAME); if (enabled) { eventsEngine.on(domAdapter.getDocument(), eventName, this._proxiedTabTerminatorHandler); } else { eventsEngine.off(domAdapter.getDocument(), eventName, this._proxiedTabTerminatorHandler); } }, _findTabbableElements: function _findTabbableElements() { return this._$wrapper.find("*").filter(selectors.tabbable); }, _tabKeyHandler: function _tabKeyHandler(e) { if (e.keyCode !== TAB_KEY || !this._isTopOverlay()) { return; } var tabbableElements = this._findTabbableElements(), $firstTabbable = tabbableElements.first(), $lastTabbable = tabbableElements.last(), isTabOnLast = !e.shiftKey && e.target === $lastTabbable.get(0), isShiftTabOnFirst = e.shiftKey && e.target === $firstTabbable.get(0), isEmptyTabList = tabbableElements.length === 0, isOutsideTarget = inArray(e.target, tabbableElements) === -1; if (isTabOnLast || isShiftTabOnFirst || isEmptyTabList || isOutsideTarget) { e.preventDefault(); var $focusElement = e.shiftKey ? $lastTabbable : $firstTabbable; eventsEngine.trigger($focusElement, "focusin"); eventsEngine.trigger($focusElement, "focus"); } }, _toggleSubscriptions: function _toggleSubscriptions(enabled) { if (windowUtils.hasWindow()) { this._toggleHideTopOverlayCallback(enabled); this._toggleParentsScrollSubscription(enabled); } }, _toggleHideTopOverlayCallback: function _toggleHideTopOverlayCallback(subscribe) { if (!this._hideTopOverlayHandler) { return; } if (subscribe && this.option("closeOnBackButton")) { hideTopOverlayCallback.add(this._hideTopOverlayHandler); } else { hideTopOverlayCallback.remove(this._hideTopOverlayHandler); } }, _toggleParentsScrollSubscription: function _toggleParentsScrollSubscription(subscribe) { if (!this._position) { return; } var target = this._position.of || $(), closeOnScroll = this.option("closeOnTargetScroll"), $parents = getElement(target).parents(), scrollEvent = eventUtils.addNamespace("scroll", this.NAME); if (devices.real().platform === "generic") { $parents = $parents.add(window); } this._proxiedTargetParentsScrollHandler = this._proxiedTargetParentsScrollHandler || function (e) { this._targetParentsScrollHandler(e); }.bind(this); eventsEngine.off($().add(this._$prevTargetParents), scrollEvent, this._proxiedTargetParentsScrollHandler); if (subscribe && closeOnScroll) { eventsEngine.on($parents, scrollEvent, this._proxiedTargetParentsScrollHandler); this._$prevTargetParents = $parents; } }, _targetParentsScrollHandler: function _targetParentsScrollHandler(e) { var closeHandled = false, closeOnScroll = this.option("closeOnTargetScroll"); if (typeUtils.isFunction(closeOnScroll)) { closeHandled = closeOnScroll(e); } if (!closeHandled && !this._showAnimationProcessing) { this.hide(); } }, _render: function _render() { this.callBase(); this._$content.appendTo(this.$element()); this._renderVisibilityAnimate(this.option("visible")); }, _renderContent: function _renderContent() { var shouldDeferRendering = !this._currentVisible && this.option("deferRendering"); var isParentHidden = this.option("visible") && this._isParentHidden(); if (isParentHidden) { this._isHidden = true; return; } if (this._contentAlreadyRendered || shouldDeferRendering) { return; } this._contentAlreadyRendered = true; this.callBase(); }, _isParentHidden: function _isParentHidden() { if (!this.option("_checkParentVisibility")) { return false; } if (this._parentHidden !== undefined) { return this._parentHidden; } var $parent = this.$element().parent(); if ($parent.is(":visible")) { return false; } var isHidden = false; $parent.add($parent.parents()).each(function () { var $element = $(this); if ($element.css("display") === "none") { isHidden = true; return false; } }); return isHidden || !domAdapter.getBody().contains($parent.get(0)); }, _renderContentImpl: function _renderContentImpl() { var $element = this.$element(); this._$content.appendTo($element); var contentTemplate = this._getTemplate(this.option("contentTemplate")); contentTemplate && contentTemplate.render({ container: getPublicElement(this.$content()), noModel: true }); this._renderDrag(); this._renderResize(); this._renderScrollTerminator(); }, _renderDrag: function _renderDrag() { var $dragTarget = this._getDragTarget(); if (!$dragTarget) { return; } var startEventName = eventUtils.addNamespace(dragEvents.start, this.NAME), updateEventName = eventUtils.addNamespace(dragEvents.move, this.NAME); eventsEngine.off($dragTarget, startEventName); eventsEngine.off($dragTarget, updateEventName); if (!this.option("dragEnabled")) { return; } eventsEngine.on($dragTarget, startEventName, this._dragStartHandler.bind(this)); eventsEngine.on($dragTarget, updateEventName, this._dragUpdateHandler.bind(this)); }, _renderResize: function _renderResize() { this._resizable = this._createComponent(this._$content, Resizable, { handles: this.option("resizeEnabled") ? "all" : "none", onResizeEnd: this._resizeEndHandler.bind(this), onResize: this._actions.onResize.bind(this), onResizeStart: this._actions.onResizeStart.bind(this), minHeight: 100, minWidth: 100, area: this._getDragResizeContainer() }); }, _resizeEndHandler: function _resizeEndHandler() { this._positionChangeHandled = true; var width = this._resizable.option("width"), height = this._resizable.option("height"); width && this.option("width", width); height && this.option("height", height); this._actions.onResizeEnd(); }, _renderScrollTerminator: function _renderScrollTerminator() { var $scrollTerminator = this._wrapper(); var terminatorEventName = eventUtils.addNamespace(dragEvents.move, this.NAME); eventsEngine.off($scrollTerminator, terminatorEventName); eventsEngine.on($scrollTerminator, terminatorEventName, { validate: function validate() { return true; }, getDirection: function getDirection() { return "both"; }, _toggleGestureCover: noop, _clearSelection: noop, isNative: true }, function (e) { var originalEvent = e.originalEvent.originalEvent; e._cancelPreventDefault = true; if (originalEvent && originalEvent.type !== "mousemove") { e.preventDefault(); } }); }, _getDragTarget: function _getDragTarget() { return this.$content(); }, _dragStartHandler: function _dragStartHandler(e) { e.targetElements = []; this._prevOffset = { x: 0, y: 0 }; var allowedOffsets = this._allowedOffsets(); e.maxTopOffset = allowedOffsets.top; e.maxBottomOffset = allowedOffsets.bottom; e.maxLeftOffset = allowedOffsets.left; e.maxRightOffset = allowedOffsets.right; }, _getDragResizeContainer: function _getDragResizeContainer() { var isContainerDefined = viewPortUtils.originalViewPort().get(0) || this.option("container"), $container = !isContainerDefined ? $(window) : this._$container; return $container; }, _deltaSize: function _deltaSize() { var $content = this._$content, $container = this._getDragResizeContainer(); var contentWidth = $content.outerWidth(), contentHeight = $content.outerHeight(), containerWidth = $container.outerWidth(), containerHeight = $container.outerHeight(); if (this._isWindow($container)) { var document = domAdapter.getDocument(), fullPageHeight = Math.max($(document).outerHeight(), containerHeight), fullPageWidth = Math.max($(document).outerWidth(), containerWidth); containerHeight = fullPageHeight; containerWidth = fullPageWidth; } return { width: containerWidth - contentWidth, height: containerHeight - contentHeight }; }, _dragUpdateHandler: function _dragUpdateHandler(e) { var offset = e.offset, prevOffset = this._prevOffset, targetOffset = { top: offset.y - prevOffset.y, left: offset.x - prevOffset.x }; this._changePosition(targetOffset); this._prevOffset = offset; }, _changePosition: function _changePosition(offset) { var position = translator.locate(this._$content); translator.move(this._$content, { left: position.left + offset.left, top: position.top + offset.top }); this._positionChangeHandled = true; }, _allowedOffsets: function _allowedOffsets() { var position = translator.locate(this._$content), deltaSize = this._deltaSize(), isAllowedDrag = deltaSize.height >= 0 && deltaSize.width >= 0, shaderOffset = this.option("shading") && !this.option("container") && !this._isWindow(this._getContainer()) ? translator.locate(this._$wrapper) : { top: 0, left: 0 }, boundaryOffset = this.option("boundaryOffset"); return { top: isAllowedDrag ? position.top + shaderOffset.top + boundaryOffset.v : 0, bottom: isAllowedDrag ? -position.top - shaderOffset.top + deltaSize.height - boundaryOffset.v : 0, left: isAllowedDrag ? position.left + shaderOffset.left + boundaryOffset.h : 0, right: isAllowedDrag ? -position.left - shaderOffset.left + deltaSize.width - boundaryOffset.h : 0 }; }, _fireContentReadyAction: function _fireContentReadyAction() { if (this.option("visible")) { this._moveToContainer(); } this.callBase.apply(this, arguments); }, _moveFromContainer: function _moveFromContainer() { this._$content.appendTo(this.$element()); this._detachWrapperToContainer(); }, _detachWrapperToContainer: function _detachWrapperToContainer() { this._$wrapper.detach(); }, _moveToContainer: function _moveToContainer() { this._attachWrapperToContainer(); this._$content.appendTo(this._$wrapper); }, _attachWrapperToContainer: function _attachWrapperToContainer() { var $element = this.$element(); if (this._$container && this._$container[0] !== $element.parent()[0]) { this._$wrapper.appendTo(this._$container); } else { this._$wrapper.appendTo($element); } }, _renderGeometry: function _renderGeometry() { if (this.option("visible") && windowUtils.hasWindow()) { this._renderGeometryImpl(); } }, _renderGeometryImpl: function _renderGeometryImpl() { this._stopAnimation(); this._normalizePosition(); this._renderShading(); this._renderDimensions(); var resultPosition = this._renderPosition(); this._actions.onPositioned({ position: resultPosition }); }, _renderShading: function _renderShading() { var $wrapper = this._$wrapper, $container = this._getContainer(); $wrapper.css("position", this._isWindow($container) && !iOS ? "fixed" : "absolute"); this._renderShadingDimensions(); this._renderShadingPosition(); }, _renderShadingPosition: function _renderShadingPosition() { if (this.option("shading")) { var $container = this._getContainer(); positionUtils.setup(this._$wrapper, { my: "top left", at: "top left", of: $container }); } }, _renderShadingDimensions: function _renderShadingDimensions() { var wrapperWidth, wrapperHeight; if (this.option("shading")) { var $container = this._getContainer(); wrapperWidth = this._isWindow($container) ? "100%" : $container.outerWidth(), wrapperHeight = this._isWindow($container) ? "100%" : $container.outerHeight(); } else { wrapperWidth = ""; wrapperHeight = ""; } this._$wrapper.css({ width: wrapperWidth, height: wrapperHeight }); }, _isWindow: function _isWindow($element) { return !!$element && typeUtils.isWindow($element.get(0)); }, _getContainer: function _getContainer() { var position = this._position, container = this.option("container"), positionOf = position ? position.of || window : null; return getElement(container || positionOf); }, _renderDimensions: function _renderDimensions() { var content = this._$content.get(0); this._$content.css({ minWidth: this._getOptionValue("minWidth", content), maxWidth: this._getOptionValue("maxWidth", content), minHeight: this._getOptionValue("minHeight", content), maxHeight: this._getOptionValue("maxHeight", content), width: this._getOptionValue("width", content), height: this._getOptionValue("height", content) }); }, _renderPosition: function _renderPosition() { if (this._positionChangeHandled) { var allowedOffsets = this._allowedOffsets(); this._changePosition({ top: fitIntoRange(0, -allowedOffsets.top, allowedOffsets.bottom), left: fitIntoRange(0, -allowedOffsets.left, allowedOffsets.right) }); } else { this._renderOverlayBoundaryOffset(); translator.resetPosition(this._$content); var position = this._transformStringPosition(this._position, POSITION_ALIASES), resultPosition = positionUtils.setup(this._$content, position); forceRepaint(this._$content); // TODO: hotfix for T338096 this._actions.onPositioning(); return resultPosition; } }, _transformStringPosition: function _transformStringPosition(position, positionAliases) { if (typeUtils.isString(position)) { position = extend({}, positionAliases[position]); } return position; }, _renderOverlayBoundaryOffset: function _renderOverlayBoundaryOffset() { var boundaryOffset = this.option("boundaryOffset"); this._$content.css("margin", boundaryOffset.v + "px " + boundaryOffset.h + "px"); }, _focusTarget: function _focusTarget() { return this._$content; }, _attachKeyboardEvents: function _attachKeyboardEvents() { this._keyboardProcessor = new KeyboardProcessor({ element: this._$content, handler: this._keyboardHandler, context: this }); }, _keyboardHandler: function _keyboardHandler(options) { var e = options.originalEvent, $target = $(e.target); if ($target.is(this._$content)) { this.callBase.apply(this, arguments); } }, _isVisible: function _isVisible() { return this.option("visible"); }, _visibilityChanged: function _visibilityChanged(visible) { if (visible) { if (this.option("visible")) { this._renderVisibilityAnimate(visible); } } else { this._renderVisibilityAnimate(visible); } }, _dimensionChanged: function _dimensionChanged() { this._renderGeometry(); }, _clean: function _clean() { if (!this._contentAlreadyRendered) { this.$content().empty(); } this._renderVisibility(false); this._cleanFocusState(); }, _dispose: function _dispose() { fx.stop(this._$content, false); clearTimeout(this._deferShowTimer); this._toggleViewPortSubscription(false); this._toggleSubscriptions(false); this._updateZIndexStackPosition(false); this._toggleTabTerminator(false); this._actions = null; this.callBase(); this._$wrapper.remove(); this._$content.remove(); }, _toggleDisabledState: function _toggleDisabledState(value) { this.callBase.apply(this, arguments); this._$content.toggleClass(DISABLED_STATE_CLASS, Boolean(value)); }, _toggleRTLDirection: function _toggleRTLDirection(rtl) { this._$content.toggleClass(RTL_DIRECTION_CLASS, rtl); }, _optionChanged: function _optionChanged(args) { var value = args.value; if (inArray(args.name, ACTIONS) > -1) { this._initActions(); return; } switch (args.name) { case "dragEnabled": this._renderDrag(); this._renderGeometry(); break; case "resizeEnabled": this._renderResize(); this._renderGeometry(); break; case "shading": case "shadingColor": this._toggleShading(this.option("visible")); break; case "width": case "height": case "minWidth": case "maxWidth": case "minHeight": case "maxHeight": case "position": case "boundaryOffset": this._renderGeometry(); break; case "visible": this._renderVisibilityAnimate(value).done(function () { if (!this._animateDeferred) { return; } this._animateDeferred.resolveWith(this); }.bind(this)); break; case "target": this._initTarget(value); this._invalidate(); break; case "container": this._initContainer(value); this._invalidate(); break; case "deferRendering": case "contentTemplate": this._contentAlreadyRendered = false; this._invalidate(); break; case "closeOnBackButton": this._toggleHideTopOverlayCallback(this.option("visible")); break; case "closeOnTargetScroll": this._toggleParentsScrollSubscription(this.option("visible")); break; case "closeOnOutsideClick": case "animation": case "propagateOutsideClick": break; case "rtlEnabled": this._contentAlreadyRendered = false; this.option("visible", false); this.callBase(args); break; default: this.callBase(args); } }, /** * @name dxOverlaymethods.toggle * @publicName toggle(showing) * @param1 showing:boolean * @return Promise<void> */ toggle: function toggle(showing) { showing = showing === undefined ? !this.option("visible") : showing; if (showing === this.option("visible")) { return new Deferred().resolve().promise(); } var animateDeferred = new Deferred(); this._animateDeferred = animateDeferred; this.option("visible", showing); return animateDeferred.promise().done(function () { delete this._animateDeferred; }.bind(this)); }, $content: function $content() { return this._$content; }, /** * @name dxOverlaymethods.show * @publicName show() * @return Promise<void> */ show: function show() { return this.toggle(true); }, /** * @name dxOverlaymethods.hide * @publicName hide() * @return Promise<void> */ hide: function hide() { return this.toggle(false); }, /** * @name dxOverlaymethods.content * @publicName content() * @return dxElement */ content: function content() { return getPublicElement(this._$content); }, /** * @name dxOverlaymethods.repaint * @publicName repaint() */ repaint: function repaint() { this._renderGeometry(); } }); /** * @name ui.dxOverlay * @publicName dxOverlay * @section utils */ /** * @name ui.dxOverlayMethods.baseZIndex * @publicName baseZIndex(zIndex) * @param1 zIndex:number * @namespace DevExpress.ui.dxOverlay * @module ui/overlay * @export dxOverlay.baseZIndex * @static */ Overlay.baseZIndex = function (zIndex) { FIRST_Z_INDEX = zIndex; }; registerComponent("dxOverlay", Overlay); module.exports = Overlay;