devextreme
Version:
HTML5 JavaScript Component Suite for Responsive Web Development
209 lines (208 loc) • 9.64 kB
JavaScript
/**
* DevExtreme (ui/grid_core/ui.grid_core.editor_factory.js)
* Version: 18.1.3
* Build date: Tue May 15 2018
*
* Copyright (c) 2012 - 2018 Developer Express Inc. ALL RIGHTS RESERVED
* Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/
*/
"use strict";
var $ = require("../../core/renderer"),
domAdapter = require("../../core/dom_adapter"),
eventsEngine = require("../../events/core/events_engine"),
modules = require("./ui.grid_core.modules"),
clickEvent = require("../../events/click"),
contextMenuEvent = require("../../events/contextmenu"),
pointerEvents = require("../../events/pointer"),
positionUtils = require("../../animation/position"),
eventUtils = require("../../events/utils"),
addNamespace = eventUtils.addNamespace,
browser = require("../../core/utils/browser"),
extend = require("../../core/utils/extend").extend,
EditorFactoryMixin = require("../shared/ui.editor_factory_mixin");
var EDITOR_INLINE_BLOCK = "dx-editor-inline-block",
CELL_FOCUS_DISABLED_CLASS = "dx-cell-focus-disabled",
FOCUS_OVERLAY_CLASS = "focus-overlay",
CONTENT_CLASS = "content",
FOCUSED_ELEMENT_CLASS = "dx-focused",
ROW_CLASS = "dx-row",
MODULE_NAMESPACE = "dxDataGridEditorFactory",
UPDATE_FOCUS_EVENTS = addNamespace([pointerEvents.down, "focusin", clickEvent.name].join(" "), MODULE_NAMESPACE),
POINTER_EVENTS_TARGET_CLASS = "dx-pointer-events-target",
POINTER_EVENTS_NONE_CLASS = "dx-pointer-events-none",
FOCUSED_ELEMENT_SELECTOR = "td[tabindex]:focus, tr[tabindex]:focus, input:focus, textarea:focus, .dx-lookup-field:focus, .dx-checkbox:focus",
DX_HIDDEN = "dx-hidden",
TAB_KEY = 9;
var EditorFactory = modules.ViewController.inherit({
_getFocusedElement: function($dataGridElement) {
return $dataGridElement.find(FOCUSED_ELEMENT_SELECTOR)
},
_getFocusCellSelector: function() {
return ".dx-row > td"
},
_updateFocusCore: function() {
var $focusCell, hideBorders, $focus = this._$focusedElement,
$dataGridElement = this.component && this.component.$element();
if ($dataGridElement) {
$focus = this._getFocusedElement($dataGridElement);
if ($focus.length) {
if (!$focus.hasClass(CELL_FOCUS_DISABLED_CLASS) && !$focus.hasClass(ROW_CLASS)) {
$focusCell = $focus.closest(this._getFocusCellSelector() + ", ." + CELL_FOCUS_DISABLED_CLASS);
hideBorders = $focusCell.get(0) !== $focus.get(0) && $focusCell.hasClass(EDITOR_INLINE_BLOCK);
$focus = $focusCell
}
if ($focus.length && !$focus.hasClass(CELL_FOCUS_DISABLED_CLASS)) {
this.focus($focus, hideBorders);
return
}
}
}
this.loseFocus()
},
_updateFocus: function(e) {
var that = this,
isFocusOverlay = e && e.event && $(e.event.target).hasClass(that.addWidgetPrefix(FOCUS_OVERLAY_CLASS));
that._isFocusOverlay = that._isFocusOverlay || isFocusOverlay;
clearTimeout(that._updateFocusTimeoutID);
that._updateFocusTimeoutID = setTimeout(function() {
delete that._updateFocusTimeoutID;
if (!that._isFocusOverlay) {
that._updateFocusCore()
}
that._isFocusOverlay = false
})
},
_updateFocusOverlaySize: function($element, position) {
var location = positionUtils.calculate($element, extend({
collision: "fit"
}, position));
if (location.h.oversize > 0) {
$element.outerWidth($element.outerWidth() - location.h.oversize)
}
if (location.v.oversize > 0) {
$element.outerHeight($element.outerHeight() - location.v.oversize)
}
},
callbackNames: function() {
return ["focused"]
},
focus: function($element, hideBorder) {
var that = this;
if (void 0 === $element) {
return that._$focusedElement
} else {
if ($element) {
that._$focusedElement && that._$focusedElement.removeClass(FOCUSED_ELEMENT_CLASS);
that._$focusedElement = $element;
clearTimeout(that._focusTimeoutID);
that._focusTimeoutID = setTimeout(function() {
delete that._focusTimeoutID;
var focusOverlayPosition, $focusOverlay = that._$focusOverlay = that._$focusOverlay || $("<div>").addClass(that.addWidgetPrefix(FOCUS_OVERLAY_CLASS) + " " + POINTER_EVENTS_TARGET_CLASS);
if (hideBorder) {
that._$focusOverlay && that._$focusOverlay.addClass(DX_HIDDEN)
} else {
if ($element.length) {
var align = browser.msie ? "left bottom" : browser.mozilla ? "right bottom" : "left top",
$content = $element.closest("." + that.addWidgetPrefix(CONTENT_CLASS)),
elemCoord = $element[0].getBoundingClientRect();
$focusOverlay.removeClass(DX_HIDDEN).appendTo($content).outerWidth(elemCoord.right - elemCoord.left + 1).outerHeight(elemCoord.bottom - elemCoord.top + 1);
focusOverlayPosition = {
precise: true,
my: align,
at: align,
of: $element,
boundary: $content.length && $content
};
that._updateFocusOverlaySize($focusOverlay, focusOverlayPosition);
positionUtils.setup($focusOverlay, focusOverlayPosition);
$focusOverlay.css("visibility", "visible")
}
}
$element.addClass(FOCUSED_ELEMENT_CLASS);
that.focused.fire($element)
})
}
}
},
resize: function() {
var $focusedElement = this._$focusedElement;
if ($focusedElement) {
this.focus($focusedElement)
}
},
loseFocus: function() {
this._$focusedElement && this._$focusedElement.removeClass(FOCUSED_ELEMENT_CLASS);
this._$focusedElement = null;
this._$focusOverlay && this._$focusOverlay.addClass(DX_HIDDEN)
},
init: function() {
this.createAction("onEditorPreparing", {
excludeValidators: ["designMode", "disabled", "readOnly"],
category: "rendering"
});
this.createAction("onEditorPrepared", {
excludeValidators: ["designMode", "disabled", "readOnly"],
category: "rendering"
});
this._updateFocusHandler = this._updateFocusHandler || this.createAction(this._updateFocus.bind(this));
eventsEngine.on(domAdapter.getDocument(), UPDATE_FOCUS_EVENTS, this._updateFocusHandler);
this._attachContainerEventHandlers()
},
_attachContainerEventHandlers: function() {
var that = this,
$container = that.component && that.component.$element(),
isIE10OrLower = browser.msie && parseInt(browser.version) < 11;
if ($container) {
eventsEngine.on($container, addNamespace("keydown", MODULE_NAMESPACE), function(e) {
if (e.which === TAB_KEY) {
that._updateFocusHandler(e)
}
});
isIE10OrLower && eventsEngine.on($container, [pointerEvents.down, pointerEvents.move, pointerEvents.up, clickEvent.name, contextMenuEvent.name].join(" "), "." + POINTER_EVENTS_TARGET_CLASS, that._focusOverlayEventProxy.bind(that))
}
},
_focusOverlayEventProxy: function(e) {
var element, $target = $(e.target),
$currentTarget = $(e.currentTarget),
needProxy = $target.hasClass(POINTER_EVENTS_TARGET_CLASS) || $target.hasClass(POINTER_EVENTS_NONE_CLASS);
if (!needProxy || $currentTarget.hasClass(DX_HIDDEN)) {
return
}
$currentTarget.addClass(DX_HIDDEN);
element = $target.get(0).ownerDocument.elementFromPoint(e.clientX, e.clientY);
eventUtils.fireEvent({
originalEvent: e,
target: element
});
e.stopPropagation();
$currentTarget.removeClass(DX_HIDDEN);
if (e.type === clickEvent.name && "INPUT" === element.tagName) {
eventsEngine.trigger($(element), "focus")
}
},
dispose: function() {
clearTimeout(this._focusTimeoutID);
clearTimeout(this._updateFocusTimeoutID);
eventsEngine.off(domAdapter.getDocument(), UPDATE_FOCUS_EVENTS, this._updateFocusHandler)
}
}).include(EditorFactoryMixin);
module.exports = {
defaultOptions: function() {
return {}
},
controllers: {
editorFactory: EditorFactory
},
extenders: {
controllers: {
columnsResizer: {
_startResizing: function(args) {
this.callBase(args);
if (this.isResizing()) {
this.getController("editorFactory").loseFocus()
}
}
}
}
}
};