From ea4d65ceeef0c17dda4143c836051212c96f904b Mon Sep 17 00:00:00 2001 From: Nick O'Leary Date: Mon, 10 Dec 2018 22:20:56 +0000 Subject: [PATCH] Add RED.editor.registerTypeEditor for custom type editors --- Gruntfile.js | 10 + .../editor-client/src/js/text/format.js | 6 +- .../editor-client/src/js/ui/editor.js | 215 ++++++++++-------- .../editor-client/src/js/ui/editors/buffer.js | 11 +- .../src/js/ui/editors/expression.js | 9 +- .../editor-client/src/js/ui/editors/js.js | 10 +- .../editor-client/src/js/ui/editors/json.js | 9 +- .../src/js/ui/editors/markdown.js | 10 +- 8 files changed, 155 insertions(+), 125 deletions(-) diff --git a/Gruntfile.js b/Gruntfile.js index 86b8160d0..3ddab44f5 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -445,7 +445,17 @@ module.exports = function(grunt) { destination: 'docs', configure: './jsdoc.json' } + }, + editor: { + src: [ + 'packages/node_modules/@node-red/editor-client/src/js' + ], + options: { + destination: 'packages/node_modules/@node-red/editor-client/docs', + configure: './jsdoc.json' + } } + }, jsdoc2md: { runtimeAPI: { diff --git a/packages/node_modules/@node-red/editor-client/src/js/text/format.js b/packages/node_modules/@node-red/editor-client/src/js/text/format.js index c9fac5517..0afe5a824 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/text/format.js +++ b/packages/node_modules/@node-red/editor-client/src/js/text/format.js @@ -1242,7 +1242,7 @@ RED.text.format = (function() { element.dispatchEvent(event); return; } - + var range = selection.getRangeAt(0); var tempRange = range.cloneRange(), startNode, startOffset; startNode = range.startContainer; @@ -1304,7 +1304,7 @@ RED.text.format = (function() { } return { - /** + /*! * Returns the HTML representation of a given structured text * @param text - the structured text * @param type - could be one of filepath, url, email @@ -1315,7 +1315,7 @@ RED.text.format = (function() { getHtml: function (text, type, args, isRtl, locale) { return getHandler(type).format(text, args, isRtl, true, locale); }, - /** + /*! * Handle Structured text correct display for a given HTML element. * @param element - the element : should be of type div contenteditable=true * @param type - could be one of filepath, url, email diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/editor.js b/packages/node_modules/@node-red/editor-client/src/js/ui/editor.js index 86d37761e..d3548d581 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/editor.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/editor.js @@ -13,6 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. **/ + +/** + * @namespace RED.editor + */ RED.editor = (function() { @@ -21,6 +25,8 @@ RED.editor = (function() { var editing_config_node = null; var subflowEditor; + var customEditTypes = {}; + var editTrayWidthCache = {}; function getCredentialsURL(nodeType, nodeID) { @@ -2137,7 +2143,7 @@ RED.editor = (function() { } function showTypeEditor(type, options) { - if (RED.editor.types.hasOwnProperty(type)) { + if (customEditTypes.hasOwnProperty(type)) { if (editStack.length > 0) { options.parent = editStack[editStack.length-1].id; } @@ -2146,12 +2152,99 @@ RED.editor = (function() { options.onclose = function() { editStack.pop(); } - RED.editor.types[type].show(options); + customEditTypes[type].show(options); } else { console.log("Unknown type editor:",type); } } + function createEditor(options) { + var el = options.element || $("#"+options.id)[0]; + var toolbarRow = $("
").appendTo(el); + el = $("
").appendTo(el).addClass("node-text-editor-container")[0]; + var editor = ace.edit(el); + editor.setTheme("ace/theme/tomorrow"); + var session = editor.getSession(); + session.on("changeAnnotation", function () { + var annotations = session.getAnnotations() || []; + var i = annotations.length; + var len = annotations.length; + while (i--) { + if (/doctype first\. Expected/.test(annotations[i].text)) { annotations.splice(i, 1); } + else if (/Unexpected End of file\. Expected/.test(annotations[i].text)) { annotations.splice(i, 1); } + } + if (len > annotations.length) { session.setAnnotations(annotations); } + }); + if (options.mode) { + session.setMode(options.mode); + } + if (options.foldStyle) { + session.setFoldStyle(options.foldStyle); + } else { + session.setFoldStyle('markbeginend'); + } + if (options.options) { + editor.setOptions(options.options); + } else { + editor.setOptions({ + enableBasicAutocompletion:true, + enableSnippets:true, + tooltipFollowsMouse: false + }); + } + if (options.readOnly) { + editor.setOption('readOnly',options.readOnly); + editor.container.classList.add("ace_read-only"); + } + if (options.hasOwnProperty('lineNumbers')) { + editor.renderer.setOption('showGutter',options.lineNumbers); + } + editor.$blockScrolling = Infinity; + if (options.value) { + session.setValue(options.value,-1); + } + if (options.globals) { + setTimeout(function() { + if (!!session.$worker) { + session.$worker.send("setOptions", [{globals: options.globals, esversion:6, sub:true, asi:true, maxerr:1000}]); + } + },100); + } + if (options.mode === 'ace/mode/markdown') { + $(el).addClass("node-text-editor-container-toolbar"); + editor.toolbar = customEditTypes['_markdown'].buildToolbar(toolbarRow,editor); + if (options.expandable !== false) { + var expandButton = $('').appendTo(editor.toolbar); + + expandButton.click(function(e) { + e.preventDefault(); + var value = editor.getValue(); + RED.editor.editMarkdown({ + value: value, + width: "Infinity", + cursor: editor.getCursorPosition(), + complete: function(v,cursor) { + editor.setValue(v, -1); + editor.gotoLine(cursor.row+1,cursor.column,false); + setTimeout(function() { + editor.focus(); + },300); + } + }) + }); + } + var helpButton = $('').appendTo($(el).parent()); + RED.popover.create({ + target: helpButton, + trigger: 'click', + size: "small", + direction: "left", + content: RED._("markdownEditor.format"), + autoClose: 50 + }); + } + return editor; + } return { init: function() { @@ -2164,14 +2257,7 @@ RED.editor = (function() { $("#node-dialog-cancel").click(); $("#node-config-dialog-cancel").click(); }); - - for (var type in RED.editor.types) { - if (RED.editor.types.hasOwnProperty(type)) { - RED.editor.types[type].init(); - } - } }, - types: {}, edit: showEditDialog, editConfig: showEditConfigNodeDialog, editSubflow: showEditSubflowDialog, @@ -2184,93 +2270,32 @@ RED.editor = (function() { validateNode: validateNode, updateNodeProperties: updateNodeProperties, // TODO: only exposed for edit-undo + /** + * Show a type editor. + * @param {string} type - the type to display + * @param {object} options - options for the editor + * @function + * @memberof RED.editor + */ + showTypeEditor: showTypeEditor, - createEditor: function(options) { - var el = options.element || $("#"+options.id)[0]; - var toolbarRow = $("
").appendTo(el); - el = $("
").appendTo(el).addClass("node-text-editor-container")[0]; - var editor = ace.edit(el); - editor.setTheme("ace/theme/tomorrow"); - var session = editor.getSession(); - session.on("changeAnnotation", function () { - var annotations = session.getAnnotations() || []; - var i = annotations.length; - var len = annotations.length; - while (i--) { - if (/doctype first\. Expected/.test(annotations[i].text)) { annotations.splice(i, 1); } - else if (/Unexpected End of file\. Expected/.test(annotations[i].text)) { annotations.splice(i, 1); } - } - if (len > annotations.length) { session.setAnnotations(annotations); } - }); - if (options.mode) { - session.setMode(options.mode); - } - if (options.foldStyle) { - session.setFoldStyle(options.foldStyle); - } else { - session.setFoldStyle('markbeginend'); - } - if (options.options) { - editor.setOptions(options.options); - } else { - editor.setOptions({ - enableBasicAutocompletion:true, - enableSnippets:true, - tooltipFollowsMouse: false - }); - } - if (options.readOnly) { - editor.setOption('readOnly',options.readOnly); - editor.container.classList.add("ace_read-only"); - } - if (options.hasOwnProperty('lineNumbers')) { - editor.renderer.setOption('showGutter',options.lineNumbers); - } - editor.$blockScrolling = Infinity; - if (options.value) { - session.setValue(options.value,-1); - } - if (options.globals) { - setTimeout(function() { - if (!!session.$worker) { - session.$worker.send("setOptions", [{globals: options.globals, esversion:6, sub:true, asi:true, maxerr:1000}]); - } - },100); - } - if (options.mode === 'ace/mode/markdown') { - $(el).addClass("node-text-editor-container-toolbar"); - editor.toolbar = RED.editor.types._markdown.buildToolbar(toolbarRow,editor); - if (options.expandable !== false) { - var expandButton = $('').appendTo(editor.toolbar); + /** + * Register a type editor. + * @param {string} type - the type name + * @param {object} options - the editor definition + * @function + * @memberof RED.editor + */ + registerTypeEditor: function(type, definition) { + customEditTypes[type] = definition; + }, - expandButton.click(function(e) { - e.preventDefault(); - var value = editor.getValue(); - RED.editor.editMarkdown({ - value: value, - width: "Infinity", - cursor: editor.getCursorPosition(), - complete: function(v,cursor) { - editor.setValue(v, -1); - editor.gotoLine(cursor.row+1,cursor.column,false); - setTimeout(function() { - editor.focus(); - },300); - } - }) - }); - } - var helpButton = $('').appendTo($(el).parent()); - RED.popover.create({ - target: helpButton, - trigger: 'click', - size: "small", - direction: "left", - content: RED._("markdownEditor.format"), - autoClose: 50 - }); - } - return editor; - } + /** + * Create a editor ui component + * @param {object} options - the editor options + * @function + * @memberof RED.editor + */ + createEditor: createEditor } })(); diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/editors/buffer.js b/packages/node_modules/@node-red/editor-client/src/js/ui/editors/buffer.js index 9e3cbcacd..beec7ae98 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/editors/buffer.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/editors/buffer.js @@ -13,8 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. **/ -RED.editor.types._buffer = (function() { - +(function() { var template = ''; @@ -45,10 +44,7 @@ RED.editor.types._buffer = (function() { } - return { - init: function() { - $(template).appendTo(document.body); - }, + var definition = { show: function(options) { var value = options.value; var onComplete = options.complete; @@ -206,4 +202,7 @@ RED.editor.types._buffer = (function() { RED.tray.show(trayOptions); } } + $(template).appendTo(document.body); + RED.editor.registerTypeEditor("_buffer", definition); + })(); diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/editors/expression.js b/packages/node_modules/@node-red/editor-client/src/js/ui/editors/expression.js index 92c3c933b..8a6d6e8dd 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/editors/expression.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/editors/expression.js @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. **/ -RED.editor.types._expression = (function() { +(function() { var template = ''; var expressionTestCache = {}; - return { - init: function() { - $(template).appendTo(document.body); - }, + var definition = { show: function(options) { var expressionTestCacheId = options.parent||"_"; var value = options.value; @@ -349,4 +346,6 @@ RED.editor.types._expression = (function() { RED.tray.show(trayOptions); } } + $(template).appendTo(document.body); + RED.editor.registerTypeEditor("_expression", definition); })(); diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/editors/js.js b/packages/node_modules/@node-red/editor-client/src/js/ui/editors/js.js index becc86749..c0ce56411 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/editors/js.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/editors/js.js @@ -13,15 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. **/ -RED.editor.types._js = (function() { +(function() { var template = ''; - return { - init: function() { - $(template).appendTo(document.body); - }, + var definition = { show: function(options) { var value = options.value; var onComplete = options.complete; @@ -99,4 +96,7 @@ RED.editor.types._js = (function() { RED.tray.show(trayOptions); } } + $(template).appendTo(document.body); + RED.editor.registerTypeEditor("_js", definition); + })(); diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/editors/json.js b/packages/node_modules/@node-red/editor-client/src/js/ui/editors/json.js index 6dd0bdbcc..0ddc6934a 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/editors/json.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/editors/json.js @@ -13,15 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. **/ -RED.editor.types._json = (function() { +(function() { var template = ''; - return { - init: function() { - $(template).appendTo(document.body); - }, + var definition = { show: function(options) { var value = options.value; var onComplete = options.complete; @@ -115,4 +112,6 @@ RED.editor.types._json = (function() { RED.tray.show(trayOptions); } } + $(template).appendTo(document.body); + RED.editor.registerTypeEditor("_json", definition); })(); diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/editors/markdown.js b/packages/node_modules/@node-red/editor-client/src/js/ui/editors/markdown.js index 4e3f8a125..89d09397a 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/editors/markdown.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/editors/markdown.js @@ -13,8 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. **/ -RED.editor.types._markdown = (function() { - +(function() { var toolbarTemplate = '
'+ ''+ @@ -66,10 +65,7 @@ RED.editor.types._markdown = (function() { 'hr': { before:"\n---\n\n", tooltip: "Horizontal rule" } } - return { - init: function() { - $(template).appendTo(document.body); - }, + var definition = { show: function(options) { var value = options.value; var onComplete = options.complete; @@ -212,4 +208,6 @@ RED.editor.types._markdown = (function() { return toolbar; } } + $(template).appendTo(document.body); + RED.editor.registerTypeEditor("_markdown", definition); })();