devextreme
Version:
HTML5 JavaScript Component Suite for Responsive Web Development
1,538 lines (1,269 loc) • 49.8 kB
JavaScript
"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;