UNPKG

@amcharts/amcharts5

Version:
282 lines 11.2 kB
import { Label } from "./Label"; import { Container } from "./Container"; import { RoundedRectangle } from "./RoundedRectangle"; import { Percent } from "../util/Percent"; import { color } from "../util/Color"; import { MultiDisposer } from "../util/Disposer"; import * as $utils from "../util/Utils"; import * as $type from "../util/Type"; import * as $array from "../util/Array"; /** * Editable label. * * @since 5.9.5 */ export class EditableLabel extends Label { _afterNew() { super._afterNew(); const input = this.children.push(Container.new(this._root, { html: "<textarea class=\"am5-editable-label\"></textarea>", isMeasured: false })); input.hide(); this.setPrivate("input", input); // Set background this._setDefaultTagged("background", ["editablelabel", "background"], () => { return RoundedRectangle.new(this._root, {}); }); } _beforeChanged() { super._beforeChanged(); // If editOn setting is changed, remove old listeners if (this.isDirty("editOn")) { if (this._editOnEvents) { this._editOnEvents.dispose(); } const editOn = this.get("editOn", "click"); if (editOn != "none") { this._editOnEvents = new MultiDisposer([ this.getPrivate("input").events.on(editOn, (_ev) => { // this is here just to make it interactive }), this.events.on(editOn, (_ev) => { this.set("active", true); }) ]); } } } _prepareChildren() { super._prepareChildren(); this._maybeInitTextarea(); } _updateChildren() { super._updateChildren(); if (this.isDirty("active")) { const editing = this.get("active", false); if (editing) { this._startEditing(); } else { this._stopEditing(); } const bg = this.get("background"); if (bg) { bg.set("active", editing); } } ; this._syncText(); this._syncStyle(); } _maybeInitTextarea() { if (!this._isInited()) { const input = this.getPrivate("input"); if (input && input.getPrivate("htmlElement")) { const el = input.getPrivate("htmlElement"); const textarea = el.querySelector(".am5-editable-label"); if (textarea) { this.setPrivate("textarea", textarea); // Resize textarea on keypress textarea.addEventListener("input", _ev => { if (this.get("multiLine") === false) { // replace line breaks with spaces for single-line labels textarea.value = textarea.value.replace(/\n/g, " "); } this.set("text", textarea.value); this._syncStyle(); }); // Finish editing on blur textarea.addEventListener("blur", _ev => this.set("active", false)); // Finish editing on ESC press if ($utils.supports("keyboardevents")) { this._disposers.push($utils.addEventListener(document, "keydown", (ev) => { if ($utils.getEventKey(ev) == "Escape") { this.set("active", false); } })); } // Intercept ENTER if necessary this._disposers.push($utils.addEventListener(document, "keydown", (ev) => { if ($utils.getEventKey(ev) == "Enter" && this.get("multiLine") === false) { // Single-line label, save instead of breaking into new line ev.preventDefault(); this.set("active", false); } })); this.events.dispatch("inited", { type: "inited", target: this }); } } } } _isInited() { return this.getPrivate("textarea") ? true : false; } _startEditing() { if (!this._isInited()) { this.events.once("inited", () => { this._startEditing(); }); return; } this._text.set("opacity", 0); const input = this.getPrivate("input"); const textarea = this.getPrivate("textarea"); if (textarea) { if (this.get("text", "") == "") { this.set("text", " "); } input.show(0); this.setTimeout(() => { // size textarea to fit its actual content this._syncStyle(); textarea.focus(); }, 100); } } _stopEditing() { if (!this._isInited()) { this.events.once("inited", () => { this._stopEditing(); }); return; } const input = this.getPrivate("input"); const textarea = this.getPrivate("textarea"); if (textarea) { this.set("text", textarea.value); input.hide(0); this._text.set("opacity", 1); } } _syncStyle() { const input = this.getPrivate("input"); const textarea = this.getPrivate("textarea"); const el = input.getPrivate("htmlElement"); if (textarea && el) { // Set up HTML // Reset all styles const computedStyles = window.getComputedStyle(textarea); $array.each(computedStyles, (style) => { textarea.style[style] = "initial"; }); // Remove textarea attributes textarea.style.color = this.get("fill", color(0x000000)).toCSS(this.get("fillOpacity", 1)); textarea.style.backgroundColor = "rgba(0, 0, 0, 0)"; textarea.style.border = "none"; textarea.style.outline = "none"; textarea.style.padding = "0"; // Wrapping textarea.wrap = "off"; textarea.style.resize = "none"; // Place carret under mouse cursor // @todo // Size textarea.style.overflow = "hidden"; const maxWidth = this.get("maxWidth", 0) - this.get("paddingLeft", 0) - this.get("paddingRight", 0); if (maxWidth > 0) { textarea.style.maxWidth = maxWidth + "px"; } else { // The actual minWidth will be set on frameend textarea.style.minWidth = ""; } textarea.style.height = "auto"; textarea.style.minHeight = textarea.scrollHeight + "px"; // If width is explicitly set on a label, use it for textarea if (this.get("width")) { textarea.style.width = (this.width() - this.get("paddingLeft", 0) - this.get("paddingRight", 0)) + "px"; textarea.style.minWidth = ""; } // Line height const lineHeight = this.get("lineHeight"); if (!lineHeight) { textarea.style.lineHeight = "1.2"; } else if (lineHeight instanceof Percent) { textarea.style.lineHeight = lineHeight.value + ""; } else if ($type.isNumber(lineHeight)) { textarea.style.lineHeight = lineHeight + ""; } // Font stuff let fontFamily = this.get("fontFamily"); if (!fontFamily) { fontFamily = getComputedStyle(el, "font-family").getPropertyValue("font-family"); } textarea.style.fontFamily = fontFamily; let fontSize = this.get("fontSize"); if (!fontSize) { fontSize = getComputedStyle(el, "font-size").getPropertyValue("font-size"); } else if ($type.isNumber(fontSize)) { fontSize = fontSize + "px"; } else { fontSize = fontSize; } textarea.style.fontSize = fontSize; let fontWeight = this.get("fontWeight"); if (!fontWeight) { fontWeight = getComputedStyle(el, "font-weight").getPropertyValue("font-weight"); } else { fontWeight = fontWeight; } textarea.style.fontWeight = fontWeight; let fontStyle = this.get("fontStyle"); if (!fontStyle) { fontStyle = getComputedStyle(el, "font-style").getPropertyValue("font-style"); } else { fontStyle = fontStyle; } textarea.style.fontStyle = fontStyle; const oversizeBehavior = this.get("oversizedBehavior"); if (oversizeBehavior == "wrap") { textarea.style.whiteSpace = "pre-wrap"; } else { textarea.style.whiteSpace = "nowrap"; } // Adjust textarea postion based on textAlign setting this._root.events.on("frameended", () => { if (textarea.style.minWidth == "") { textarea.style.minWidth = (textarea.scrollWidth + 20) + "px"; } const textAlign = this.get("textAlign", "start"); if (textAlign == "center") { textarea.style.textAlign = "center"; if (!el.style.transform.match(/translateX/) && !this.get("width")) { el.style.transform += " translateX(-50%)"; } } else if (textAlign == "end") { textarea.style.textAlign = "right"; if (!el.style.transform.match(/translateX/) && !this.get("width")) { el.style.transform += " translateX(-100%)"; } } else { textarea.style.textAlign = textAlign; } }); } } _syncText() { const textarea = this.getPrivate("textarea"); let text = this.get("text", ""); if (text == " ") { text = ""; } if (textarea) { textarea.value = text; } } } EditableLabel.className = "EditableLabel"; EditableLabel.classNames = Label.classNames.concat([EditableLabel.className]); //# sourceMappingURL=EditableLabel.js.map