diff options
Diffstat (limited to 'devtools/client/inspector/markup/views/text-editor.js')
-rw-r--r-- | devtools/client/inspector/markup/views/text-editor.js | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/devtools/client/inspector/markup/views/text-editor.js b/devtools/client/inspector/markup/views/text-editor.js new file mode 100644 index 0000000000..62b59c74cd --- /dev/null +++ b/devtools/client/inspector/markup/views/text-editor.js @@ -0,0 +1,143 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +const { + createFactory, +} = require("resource://devtools/client/shared/vendor/react.js"); + +const TextNode = createFactory( + require("resource://devtools/client/inspector/markup/components/TextNode.js") +); + +loader.lazyRequireGetter( + this, + "getAutocompleteMaxWidth", + "resource://devtools/client/inspector/markup/utils.js", + true +); +loader.lazyRequireGetter( + this, + "getLongString", + "resource://devtools/client/inspector/shared/utils.js", + true +); +loader.lazyRequireGetter( + this, + "InplaceEditor", + "resource://devtools/client/shared/inplace-editor.js", + true +); + +/** + * Creates a simple text editor node, used for TEXT and COMMENT + * nodes. + * + * @param {MarkupContainer} container + * The container owning this editor. + * @param {DOMNode} node + * The node being edited. + * @param {String} type + * The type of editor to build. This can be either 'text' or 'comment'. + */ +function TextEditor(container, node, type) { + this.container = container; + this.markup = this.container.markup; + this.node = node; + this._selected = false; + + this.showTextEditor = this.showTextEditor.bind(this); + + this.buildMarkup(type); +} + +TextEditor.prototype = { + buildMarkup(type) { + const doc = this.markup.doc; + + this.elt = doc.createElement("span"); + this.elt.classList.add("editor", type); + + getLongString(this.node.getNodeValue()).then(value => { + this.textNode = this.ReactDOM.render( + TextNode({ + showTextEditor: this.showTextEditor, + type, + value, + }), + this.elt + ); + }); + }, + + get ReactDOM() { + // Reuse the toolbox's ReactDOM to avoid loading react-dom.js again in the + // Inspector's BrowserLoader. + return this.container.markup.inspector.ReactDOM; + }, + + get selected() { + return this._selected; + }, + + set selected(value) { + if (value === this._selected) { + return; + } + this._selected = value; + this.update(); + }, + + showTextEditor(element) { + new InplaceEditor({ + cssProperties: this.markup.inspector.cssProperties, + done: (val, commit) => { + if (!commit) { + return; + } + getLongString(this.node.getNodeValue()).then(oldValue => { + this.container.undo.do( + () => { + this.node.setNodeValue(val); + }, + () => { + this.node.setNodeValue(oldValue); + } + ); + }); + }, + element, + maxWidth: () => getAutocompleteMaxWidth(element, this.container.elt), + multiline: true, + stopOnReturn: true, + trimOutput: false, + }); + }, + + async update() { + try { + const value = await getLongString(this.node.getNodeValue()); + + if (this.textNode.state.value !== value) { + this.textNode.setState({ value }); + } + } catch (e) { + console.error(e); + } + }, + + destroy() { + this.ReactDOM.unmountComponentAtNode(this.elt); + }, + + /** + * Stub method for consistency with ElementEditor. + */ + getInfoAtNode() { + return null; + }, +}; + +module.exports = TextEditor; |