UNPKG

devextreme

Version:

HTML5 JavaScript Component Suite for Responsive Web Development

730 lines (724 loc) • 29.9 kB
/** * DevExtreme (ui/html_editor/modules/toolbar.js) * Version: 18.2.18 * Build date: Tue Oct 18 2022 * * Copyright (c) 2012 - 2022 Developer Express Inc. ALL RIGHTS RESERVED * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/ */ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var _createClass = function() { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) { descriptor.writable = true } Object.defineProperty(target, descriptor.key, descriptor) } } return function(Constructor, protoProps, staticProps) { if (protoProps) { defineProperties(Constructor.prototype, protoProps) } if (staticProps) { defineProperties(Constructor, staticProps) } return Constructor } }(); var _quill_importer = require("../quill_importer"); var _renderer = require("../../../core/renderer"); var _renderer2 = _interopRequireDefault(_renderer); var _toolbar = require("../../toolbar"); var _toolbar2 = _interopRequireDefault(_toolbar); require("../../select_box"); require("../../color_box/color_view"); var _widget_collector = require("./widget_collector"); var _widget_collector2 = _interopRequireDefault(_widget_collector); var _iterator = require("../../../core/utils/iterator"); var _type = require("../../../core/utils/type"); var _extend = require("../../../core/utils/extend"); var _message = require("../../../localization/message"); var _inflector = require("../../../core/utils/inflector"); var _events_engine = require("../../../events/core/events_engine"); var _events_engine2 = _interopRequireDefault(_events_engine); var _utils = require("../../../events/utils"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj } } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function") } } function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called") } return call && ("object" === typeof call || "function" === typeof call) ? call : self } function _inherits(subClass, superClass) { if ("function" !== typeof superClass && null !== superClass) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass) } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) { Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass } } var BaseModule = (0, _quill_importer.getQuill)().import("core/module"); var TOOLBAR_WRAPPER_CLASS = "dx-htmleditor-toolbar-wrapper"; var TOOLBAR_CLASS = "dx-htmleditor-toolbar"; var TOOLBAR_FORMAT_WIDGET_CLASS = "dx-htmleditor-toolbar-format"; var TOOLBAR_SEPARATOR_CLASS = "dx-htmleditor-toolbar-separator"; var TOOLBAR_MENU_SEPARATOR_CLASS = "dx-htmleditor-toolbar-menu-separator"; var ACTIVE_FORMAT_CLASS = "dx-format-active"; var BOX_ITEM_CONTENT_CLASS = "dx-box-item-content"; var ICON_CLASS = "dx-icon"; var SELECTION_CHANGE_EVENT = "selection-change"; var DIALOG_COLOR_CAPTION = "dxHtmlEditor-dialogColorCaption"; var DIALOG_BACKGROUND_CAPTION = "dxHtmlEditor-dialogBackgroundCaption"; var DIALOG_LINK_CAPTION = "dxHtmlEditor-dialogLinkCaption"; var DIALOG_LINK_FIELD_URL = "dxHtmlEditor-dialogLinkUrlField"; var DIALOG_LINK_FIELD_TEXT = "dxHtmlEditor-dialogLinkTextField"; var DIALOG_LINK_FIELD_TARGET = "dxHtmlEditor-dialogLinkTargetField"; var DIALOG_LINK_FIELD_TARGET_CLASS = "dx-formdialog-field-target"; var DIALOG_IMAGE_CAPTION = "dxHtmlEditor-dialogImageCaption"; var DIALOG_IMAGE_FIELD_URL = "dxHtmlEditor-dialogImageUrlField"; var DIALOG_IMAGE_FIELD_ALT = "dxHtmlEditor-dialogImageAltField"; var DIALOG_IMAGE_FIELD_WIDTH = "dxHtmlEditor-dialogImageWidthField"; var DIALOG_IMAGE_FIELD_HEIGHT = "dxHtmlEditor-dialogImageHeightField"; var USER_ACTION = "user"; var SILENT_ACTION = "silent"; var HEADING_TEXT = (0, _message.format)("dxHtmlEditor-heading"); var NORMAL_TEXT = (0, _message.format)("dxHtmlEditor-normalText"); var ToolbarModule = function(_BaseModule) { _inherits(ToolbarModule, _BaseModule); function ToolbarModule(quill, options) { _classCallCheck(this, ToolbarModule); var _this = _possibleConstructorReturn(this, (ToolbarModule.__proto__ || Object.getPrototypeOf(ToolbarModule)).call(this, quill, options)); _this._editorInstance = options.editorInstance; _this._toolbarWidgets = new _widget_collector2.default; _this._formatHandlers = _this._getFormatHandlers(); if ((0, _type.isDefined)(options.items)) { _this._addCallbacks(); _this._renderToolbar(); _this.quill.on("editor-change", function(eventName) { var isSelectionChanged = eventName === SELECTION_CHANGE_EVENT; _this._updateToolbar(isSelectionChanged) }) } return _this } _createClass(ToolbarModule, [{ key: "_addCallbacks", value: function() { this._editorInstance.addCleanCallback(this.clean.bind(this)); this._editorInstance.addContentInitializedCallback(this.updateHistoryWidgets.bind(this)) } }, { key: "_updateToolbar", value: function(isSelectionChanged) { this.updateFormatWidgets(isSelectionChanged); this.updateHistoryWidgets() } }, { key: "_getDefaultClickHandler", value: function(formatName) { var _this2 = this; return function(e) { var formats = _this2.quill.getFormat(); var value = formats[formatName]; var newValue = !((0, _type.isBoolean)(value) ? value : (0, _type.isDefined)(value)); _this2.quill.format(formatName, newValue, USER_ACTION); _this2._updateFormatWidget(formatName, newValue, formats) } } }, { key: "_updateFormatWidget", value: function(formatName, isApplied, formats) { var widget = this._toolbarWidgets.getByName(formatName); if (!widget) { return } if (isApplied) { this._markActiveFormatWidget(formatName, widget, formats) } else { this._resetFormatWidget(formatName, widget); formats.hasOwnProperty(formatName) && delete formats[formatName] } this._toggleClearFormatting(isApplied || !(0, _type.isEmptyObject)(formats)) } }, { key: "_getFormatHandlers", value: function() { var _this3 = this; return { clear: function(e) { var range = _this3.quill.getSelection(); if (range) { _this3.quill.removeFormat(range); _this3.updateFormatWidgets() } }, link: this._prepareLinkHandler(), image: this._prepareImageHandler(), color: this._prepareColorClickHandler("color"), background: this._prepareColorClickHandler("background"), orderedList: this._prepareShortcutHandler("list", "ordered"), bulletList: this._prepareShortcutHandler("list", "bullet"), alignLeft: this._prepareShortcutHandler("align", "left"), alignCenter: this._prepareShortcutHandler("align", "center"), alignRight: this._prepareShortcutHandler("align", "right"), alignJustify: this._prepareShortcutHandler("align", "justify"), codeBlock: this._getDefaultClickHandler("code-block"), undo: function() { _this3.quill.history.undo() }, redo: function() { _this3.quill.history.redo() }, increaseIndent: function() { _this3.quill.format("indent", "+1", USER_ACTION) }, decreaseIndent: function() { _this3.quill.format("indent", "-1", USER_ACTION) }, superscript: this._prepareShortcutHandler("script", "super"), subscript: this._prepareShortcutHandler("script", "sub") } } }, { key: "_prepareShortcutHandler", value: function(formatName, shortcutValue) { var _this4 = this; return function() { var formats = _this4.quill.getFormat(); var value = formats[formatName] === shortcutValue ? false : shortcutValue; _this4.quill.format(formatName, value, USER_ACTION); _this4.updateFormatWidgets(true) } } }, { key: "_prepareLinkHandler", value: function() { var _this5 = this; return function() { var selection = _this5.quill.getSelection(); var formats = _this5.quill.getFormat(); var formData = { href: formats.link || "", text: selection ? _this5.quill.getText(selection) : "", target: formats.hasOwnProperty("target") ? !!formats.target : true }; _this5._editorInstance.formDialogOption("title", (0, _message.format)(DIALOG_LINK_CAPTION)); var promise = _this5._editorInstance.showFormDialog({ formData: formData, items: _this5._linkFormItems }); promise.done(function(formData) { if (selection && !formats.link) { var text = formData.text; var index = selection.index, length = selection.length; formData.text = ""; length && _this5.quill.deleteText(index, length, SILENT_ACTION); _this5.quill.insertText(index, text, "link", formData, USER_ACTION); _this5.quill.setSelection(index + text.length, 0, USER_ACTION) } else { _this5.quill.format("link", formData, USER_ACTION) } }); promise.fail(function() { _this5.quill.focus() }) } } }, { key: "_prepareImageHandler", value: function() { var _this6 = this; return function() { var formData = _this6.quill.getFormat(); var isUpdateDialog = formData.hasOwnProperty("imageSrc"); var defaultIndex = _this6._defaultPasteIndex; if (isUpdateDialog) { var _quill$getFormat = _this6.quill.getFormat(defaultIndex - 1, 1), imageSrc = _quill$getFormat.imageSrc; formData.src = formData.imageSrc; delete formData.imageSrc; if (!imageSrc || 0 === defaultIndex) { _this6.quill.setSelection(defaultIndex + 1, 0, SILENT_ACTION) } } var formatIndex = _this6._embedFormatIndex; _this6._editorInstance.formDialogOption("title", (0, _message.format)(DIALOG_IMAGE_CAPTION)); var promise = _this6._editorInstance.showFormDialog({ formData: formData, items: _this6._imageFormItems }); promise.done(function(formData) { var index = defaultIndex; if (isUpdateDialog) { index = formatIndex; _this6.quill.deleteText(index, 1, SILENT_ACTION) } _this6.quill.insertEmbed(index, "extendedImage", formData, USER_ACTION); _this6.quill.setSelection(index + 1, 0, USER_ACTION) }).always(function() { _this6.quill.focus() }) } } }, { key: "_renderToolbar", value: function() { var _this7 = this; var container = this.options.container || this._getContainer(); this._$toolbar = (0, _renderer2.default)("<div>").addClass(TOOLBAR_CLASS).appendTo(container); this._$toolbarContainer = (0, _renderer2.default)(container).addClass(TOOLBAR_WRAPPER_CLASS); _events_engine2.default.on(this._$toolbarContainer, (0, _utils.addNamespace)("mousedown", this._editorInstance.NAME), function(e) { e.preventDefault() }); this.toolbarInstance = this._editorInstance._createComponent(this._$toolbar, _toolbar2.default, this.toolbarConfig); this._editorInstance.on("optionChanged", function(_ref) { var name = _ref.name; if ("readOnly" === name || "disabled" === name) { _this7.toolbarInstance.option("disabled", _this7.isInteractionDisabled) } }) } }, { key: "clean", value: function() { this._toolbarWidgets.clear(); this._$toolbarContainer.empty().removeClass(TOOLBAR_WRAPPER_CLASS) } }, { key: "repaint", value: function() { this.toolbarInstance && this.toolbarInstance.repaint() } }, { key: "_getContainer", value: function() { var $container = (0, _renderer2.default)("<div>"); this._editorInstance.$element().prepend($container); return $container } }, { key: "_prepareToolbarItems", value: function() { var _this8 = this; var resultItems = []; (0, _iterator.each)(this.options.items, function(index, item) { var newItem = void 0; if ((0, _type.isObject)(item)) { newItem = _this8._handleObjectItem(item) } else { if ((0, _type.isString)(item)) { var buttonItemConfig = _this8._prepareButtonItemConfig(item); newItem = _this8._getToolbarItem(buttonItemConfig) } } if (newItem) { resultItems.push(newItem) } }); return resultItems } }, { key: "_handleObjectItem", value: function(item) { if (item.formatName && item.formatValues && this._isAcceptableItem("dxSelectBox")) { var selectItemConfig = this._prepareSelectItemConfig(item); return this._getToolbarItem(selectItemConfig) } else { if (item.formatName && this._isAcceptableItem("dxButton")) { var defaultButtonItemConfig = this._prepareButtonItemConfig(item.formatName); var buttonItemConfig = (0, _extend.extend)(true, defaultButtonItemConfig, item); return this._getToolbarItem(buttonItemConfig) } else { return this._getToolbarItem(item) } } } }, { key: "_isAcceptableItem", value: function(item, acceptableWidgetName) { return !item.widget || item.widget === acceptableWidgetName } }, { key: "_prepareButtonItemConfig", value: function(formatName) { var iconName = "clear" === formatName ? "clearformat" : formatName; var buttonText = (0, _inflector.titleize)(formatName); return { widget: "dxButton", formatName: formatName, options: { hint: buttonText, text: buttonText, icon: iconName.toLowerCase(), onClick: this._formatHandlers[formatName] || this._getDefaultClickHandler(formatName), stylingMode: "text" }, showText: "inMenu" } } }, { key: "_prepareSelectItemConfig", value: function(item) { var _this9 = this; return (0, _extend.extend)(true, { widget: "dxSelectBox", formatName: item.formatName, options: { stylingMode: "filled", dataSource: item.formatValues, placeholder: (0, _inflector.titleize)(item.formatName), onValueChanged: function(e) { if (!_this9._isReset) { _this9.quill.format(item.formatName, e.value, USER_ACTION); _this9._setValueSilent(e.component, e.value) } } } }, item) } }, { key: "_prepareColorClickHandler", value: function(formatName) { var _this10 = this; return function() { var formData = _this10.quill.getFormat(); var caption = "color" === formatName ? DIALOG_COLOR_CAPTION : DIALOG_BACKGROUND_CAPTION; _this10._editorInstance.formDialogOption("title", (0, _message.format)(caption)); var promise = _this10._editorInstance.showFormDialog({ formData: formData, items: [{ dataField: formatName, editorType: "dxColorView", editorOptions: { onContentReady: function(e) { (0, _renderer2.default)(e.element).closest("." + BOX_ITEM_CONTENT_CLASS).css("flexBasis", "auto") }, focusStateEnabled: false }, label: { visible: false } }] }); promise.done(function(formData) { _this10.quill.format(formatName, formData[formatName], USER_ACTION) }); promise.fail(function() { _this10.quill.focus() }) } } }, { key: "_getToolbarItem", value: function(item) { var _this11 = this; var baseItem = { options: { onInitialized: function(e) { if (item.formatName) { e.component.$element().addClass(TOOLBAR_FORMAT_WIDGET_CLASS); e.component.$element().toggleClass("dx-" + item.formatName.toLowerCase() + "-format", !!item.formatName); _this11._toolbarWidgets.add(item.formatName, e.component) } } } }; return (0, _extend.extend)(true, { location: "before", locateInMenu: "auto" }, this._getDefaultConfig(item.formatName), item, baseItem) } }, { key: "_getDefaultItemsConfig", value: function() { return { header: { options: { displayExpr: function(item) { var isHeaderValue = (0, _type.isDefined)(item) && false !== item; return isHeaderValue ? HEADING_TEXT + " " + item : NORMAL_TEXT } } }, clear: { options: { disabled: true } }, undo: { options: { disabled: true } }, redo: { options: { disabled: true } }, separator: { template: function(data, index, element) { (0, _renderer2.default)(element).addClass(TOOLBAR_SEPARATOR_CLASS) }, menuItemTemplate: function(data, index, element) { (0, _renderer2.default)(element).addClass(TOOLBAR_MENU_SEPARATOR_CLASS) } } } } }, { key: "_getDefaultConfig", value: function(formatName) { return this._getDefaultItemsConfig()[formatName] } }, { key: "updateHistoryWidgets", value: function() { var historyModule = this.quill.history; if (!historyModule) { return } var undoOps = historyModule.stack.undo; var redoOps = historyModule.stack.redo; this._updateHistoryWidget(this._toolbarWidgets.getByName("undo"), undoOps); this._updateHistoryWidget(this._toolbarWidgets.getByName("redo"), redoOps) } }, { key: "_updateHistoryWidget", value: function(widget, operations) { if (!widget) { return } widget.option("disabled", !operations.length) } }, { key: "updateFormatWidgets", value: function(isResetRequired) { var selection = this.quill.getSelection(); if (!selection) { return } var formats = this.quill.getFormat(selection); var hasFormats = !(0, _type.isEmptyObject)(formats); if (!hasFormats || isResetRequired) { this._resetFormatWidgets() } for (var formatName in formats) { var widgetName = this._getFormatWidgetName(formatName, formats); var formatWidget = this._toolbarWidgets.getByName(widgetName) || this._toolbarWidgets.getByName(formatName); if (!formatWidget) { continue } this._markActiveFormatWidget(formatName, formatWidget, formats) } this._toggleClearFormatting(hasFormats) } }, { key: "_markActiveFormatWidget", value: function(name, widget, formats) { if (this._isColorFormat(name)) { this._updateColorWidget(name, formats[name]) } if ("value" in widget.option()) { this._setValueSilent(widget, formats[name]) } else { widget.$element().addClass(ACTIVE_FORMAT_CLASS) } } }, { key: "_toggleClearFormatting", value: function(hasFormats) { var clearWidget = this._toolbarWidgets.getByName("clear"); if (clearWidget) { clearWidget.option("disabled", !hasFormats) } } }, { key: "_isColorFormat", value: function(formatName) { return "color" === formatName || "background" === formatName } }, { key: "_updateColorWidget", value: function(formatName, color) { var formatWidget = this._toolbarWidgets.getByName(formatName); if (!formatWidget) { return } formatWidget.$element().find("." + ICON_CLASS).css("borderBottomColor", color || "transparent") } }, { key: "_getFormatWidgetName", value: function(formatName, formats) { var widgetName = void 0; switch (formatName) { case "align": widgetName = formatName + (0, _inflector.titleize)(formats[formatName]); break; case "list": widgetName = formats[formatName] + (0, _inflector.titleize)(formatName); break; case "code-block": widgetName = "codeBlock"; break; case "script": widgetName = formats[formatName] + formatName; break; case "imageSrc": widgetName = "image"; break; default: widgetName = formatName } return widgetName } }, { key: "_setValueSilent", value: function(widget, value) { this._isReset = true; widget.option("value", value); this._isReset = false } }, { key: "_resetFormatWidgets", value: function() { var _this12 = this; this._toolbarWidgets.each(function(name, widget) { _this12._resetFormatWidget(name, widget) }) } }, { key: "_resetFormatWidget", value: function(name, widget) { widget.$element().removeClass(ACTIVE_FORMAT_CLASS); if (this._isColorFormat(name)) { this._updateColorWidget(name) } if ("clear" === name) { widget.option("disabled", true) } if ("dxSelectBox" === widget.NAME) { this._setValueSilent(widget, null) } } }, { key: "addClickHandler", value: function(formatName, handler) { this._formatHandlers[formatName] = handler; var formatWidget = this._toolbarWidgets.getByName(formatName); if (formatWidget && "dxButton" === formatWidget.NAME) { formatWidget.option("onClick", handler) } } }, { key: "_linkFormItems", get: function() { return [{ dataField: "href", label: { text: (0, _message.format)(DIALOG_LINK_FIELD_URL) } }, { dataField: "text", label: { text: (0, _message.format)(DIALOG_LINK_FIELD_TEXT) } }, { dataField: "target", editorType: "dxCheckBox", editorOptions: { text: (0, _message.format)(DIALOG_LINK_FIELD_TARGET) }, cssClass: DIALOG_LINK_FIELD_TARGET_CLASS, label: { visible: false } }] } }, { key: "_embedFormatIndex", get: function() { var selection = this.quill.getSelection(); if (selection) { if (selection.length) { return selection.index } else { return selection.index - 1 } } else { return this.quill.getLength() } } }, { key: "_defaultPasteIndex", get: function() { var selection = this.quill.getSelection(); return selection && selection.index || this.quill.getLength() } }, { key: "_imageFormItems", get: function() { return [{ dataField: "src", label: { text: (0, _message.format)(DIALOG_IMAGE_FIELD_URL) } }, { dataField: "width", label: { text: (0, _message.format)(DIALOG_IMAGE_FIELD_WIDTH) } }, { dataField: "height", label: { text: (0, _message.format)(DIALOG_IMAGE_FIELD_HEIGHT) } }, { dataField: "alt", label: { text: (0, _message.format)(DIALOG_IMAGE_FIELD_ALT) } }] } }, { key: "toolbarConfig", get: function() { return { dataSource: this._prepareToolbarItems(), disabled: this.isInteractionDisabled, menuContainer: this._$toolbarContainer } } }, { key: "isInteractionDisabled", get: function() { return this._editorInstance.option("readOnly") || this._editorInstance.option("disabled") } }]); return ToolbarModule }(BaseModule); exports.default = ToolbarModule;