devextreme
Version:
HTML5 JavaScript Component Suite for Responsive Web Development
180 lines (179 loc) • 6.4 kB
JavaScript
/**
* DevExtreme (esm/ui/html_editor/modules/resizing.js)
* Version: 21.1.4
* Build date: Mon Jun 21 2021
*
* Copyright (c) 2012 - 2021 Developer Express Inc. ALL RIGHTS RESERVED
* Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/
*/
import $ from "../../../core/renderer";
import eventsEngine from "../../../events/core/events_engine";
import {
name as ClickEvent
} from "../../../events/click";
import {
addNamespace,
normalizeKeyName
} from "../../../events/utils/index";
import {
move
} from "../../../animation/translator";
import devices from "../../../core/devices";
import Resizable from "../../resizable";
import {
getBoundingRect
} from "../../../core/utils/position";
import Quill from "devextreme-quill";
import BaseModule from "./base";
var DX_RESIZE_FRAME_CLASS = "dx-resize-frame";
var DX_TOUCH_DEVICE_CLASS = "dx-touch-device";
var MODULE_NAMESPACE = "dxHtmlResizingModule";
var KEYDOWN_EVENT = addNamespace("keydown", MODULE_NAMESPACE);
var SCROLL_EVENT = addNamespace("scroll", MODULE_NAMESPACE);
var MOUSEDOWN_EVENT = addNamespace("mousedown", MODULE_NAMESPACE);
var FRAME_PADDING = 1;
export default class ResizingModule extends BaseModule {
constructor(quill, options) {
super(quill, options);
this.allowedTargets = options.allowedTargets || ["image"];
this.enabled = !!options.enabled;
this._hideFrameWithContext = this.hideFrame.bind(this);
this._framePositionChangedHandler = this._prepareFramePositionChangedHandler();
if (this.enabled) {
this._attachEvents();
this._createResizeFrame()
}
}
_attachEvents() {
eventsEngine.on(this.quill.root, addNamespace(ClickEvent, MODULE_NAMESPACE), this._clickHandler.bind(this));
eventsEngine.on(this.quill.root, SCROLL_EVENT, this._framePositionChangedHandler);
this.editorInstance.on("focusOut", this._hideFrameWithContext);
this.quill.on("text-change", this._framePositionChangedHandler)
}
_detachEvents() {
eventsEngine.off(this.quill.root, MODULE_NAMESPACE);
this.editorInstance.off("focusOut", this._hideFrameWithContext);
this.quill.off("text-change", this._framePositionChangedHandler)
}
_clickHandler(e) {
if (this._isAllowedTarget(e.target)) {
if (this._$target === e.target) {
return
}
this._$target = e.target;
this.updateFramePosition();
this.showFrame();
this._adjustSelection()
} else if (this._$target) {
this.hideFrame()
}
}
_prepareFramePositionChangedHandler(e) {
return () => {
if (this._$target) {
this.updateFramePosition()
}
}
}
_adjustSelection() {
if (!this.quill.getSelection()) {
this.quill.setSelection(0, 0)
}
}
_isAllowedTarget(targetElement) {
return this._isImage(targetElement)
}
_isImage(targetElement) {
return -1 !== this.allowedTargets.indexOf("image") && "IMG" === targetElement.tagName.toUpperCase()
}
showFrame() {
this._$resizeFrame.show();
eventsEngine.on(this.quill.root, KEYDOWN_EVENT, this._handleFrameKeyDown.bind(this))
}
_handleFrameKeyDown(e) {
var keyName = normalizeKeyName(e);
if ("del" === keyName || "backspace" === keyName) {
this._deleteImage()
}
this.hideFrame()
}
hideFrame() {
this._$target = null;
this._$resizeFrame.hide();
eventsEngine.off(this.quill.root, KEYDOWN_EVENT)
}
updateFramePosition() {
var {
height: height,
width: width,
top: targetTop,
left: targetLeft
} = getBoundingRect(this._$target);
var {
top: containerTop,
left: containerLeft
} = getBoundingRect(this.quill.root);
var borderWidth = this._getBorderWidth();
this._$resizeFrame.css({
height: height,
width: width,
padding: FRAME_PADDING,
top: targetTop - containerTop - borderWidth - FRAME_PADDING,
left: targetLeft - containerLeft - borderWidth - FRAME_PADDING
});
move(this._$resizeFrame, {
left: 0,
top: 0
})
}
_getBorderWidth() {
return parseInt(this._$resizeFrame.css("borderTopWidth"))
}
_createResizeFrame() {
if (this._$resizeFrame) {
return
}
var {
deviceType: deviceType
} = devices.current();
this._$resizeFrame = $("<div>").addClass(DX_RESIZE_FRAME_CLASS).toggleClass(DX_TOUCH_DEVICE_CLASS, "desktop" !== deviceType).appendTo(this.editorInstance._getQuillContainer()).hide();
eventsEngine.on(this._$resizeFrame, MOUSEDOWN_EVENT, e => {
e.preventDefault()
});
this.editorInstance._createComponent(this._$resizeFrame, Resizable, {
onResize: e => {
if (!this._$target) {
return
}
var correction = 2 * (FRAME_PADDING + this._getBorderWidth());
$(this._$target).attr({
height: e.height - correction,
width: e.width - correction
});
this.updateFramePosition()
}
})
}
_deleteImage() {
if (this._isAllowedTarget(this._$target)) {
Quill.find(this._$target).deleteAt(0)
}
}
option(option, value) {
if ("mediaResizing" === option) {
Object.keys(value).forEach(optionName => this.option(optionName, value[optionName]));
return
}
if ("enabled" === option) {
this.enabled = value;
value ? this._attachEvents() : this._detachEvents()
} else if ("allowedTargets" === option && Array.isArray(value)) {
this.allowedTargets = value
}
}
clean() {
this._detachEvents();
this._$resizeFrame.remove();
this._$resizeFrame = void 0
}
}