mirror of
https://github.com/node-red/node-red.git
synced 2023-10-10 13:36:53 +02:00
better support for multiple editors
- as the javascript model is singleton, need to disable syntax checking when editor not focused (support multiple instances of js editor (function node))
This commit is contained in:
parent
10465c5d68
commit
dedf5c52d9
@ -153,7 +153,7 @@ RED.editor.codeEditor.monaco = (function() {
|
|||||||
//@see https://github.com/microsoft/monaco-editor/issues/2382
|
//@see https://github.com/microsoft/monaco-editor/issues/2382
|
||||||
//This is fixed in commit microsoft/vscode@49cad9a however it is not yet present monaco-editor
|
//This is fixed in commit microsoft/vscode@49cad9a however it is not yet present monaco-editor
|
||||||
//Remove the below addEventListener once monaco-editor V0.23.1 or greater is published
|
//Remove the below addEventListener once monaco-editor V0.23.1 or greater is published
|
||||||
window.addEventListener('unhandledrejection', (evt) => {
|
window.addEventListener('unhandledrejection', function(evt) {
|
||||||
if(evt && evt.reason && evt.reason.stack) {
|
if(evt && evt.reason && evt.reason.stack) {
|
||||||
if (evt.reason.name === 'Canceled' && evt.reason.stack.indexOf('vendor/monaco/dist') >= 0) {
|
if (evt.reason.name === 'Canceled' && evt.reason.stack.indexOf('vendor/monaco/dist') >= 0) {
|
||||||
evt.preventDefault();
|
evt.preventDefault();
|
||||||
@ -681,8 +681,7 @@ RED.editor.codeEditor.monaco = (function() {
|
|||||||
|
|
||||||
var editorSettings = RED.editor.codeEditor.settings || {};
|
var editorSettings = RED.editor.codeEditor.settings || {};
|
||||||
var loadedLibs = {JS:{}, TS:{}};//for tracking and later disposing of loaded type libs
|
var loadedLibs = {JS:{}, TS:{}};//for tracking and later disposing of loaded type libs
|
||||||
|
var watchTimer, elVisible, elVisibleMem;
|
||||||
|
|
||||||
var createThemeMenuOption = function (theme, keybinding) {
|
var createThemeMenuOption = function (theme, keybinding) {
|
||||||
return {
|
return {
|
||||||
// An unique identifier of the contributed action.
|
// An unique identifier of the contributed action.
|
||||||
@ -883,7 +882,7 @@ RED.editor.codeEditor.monaco = (function() {
|
|||||||
}
|
}
|
||||||
Object.values(loadExtraModules).forEach(function(m) {
|
Object.values(loadExtraModules).forEach(function(m) {
|
||||||
_loadModuleDTS(m, false, loadedLibs, function(err, extraLib) {
|
_loadModuleDTS(m, false, loadedLibs, function(err, extraLib) {
|
||||||
loadList = loadList.filter(e => e.module != extraLib.module );
|
loadList = loadList.filter(function(e) {return e.module != extraLib.module} );
|
||||||
if(loadList.length == 0) {
|
if(loadList.length == 0) {
|
||||||
var _imports = imports.join("");
|
var _imports = imports.join("");
|
||||||
var _defs = "\ndeclare global {\n" + defs.join("") + "\n}";
|
var _defs = "\ndeclare global {\n" + defs.join("") + "\n}";
|
||||||
@ -931,14 +930,21 @@ RED.editor.codeEditor.monaco = (function() {
|
|||||||
var newModel
|
var newModel
|
||||||
|
|
||||||
if (oldModel) {
|
if (oldModel) {
|
||||||
|
var oldScrollTop = ed.getScrollTop();
|
||||||
|
var oldScrollLeft = ed.getScrollLeft();
|
||||||
|
var oldSelections = ed.getSelections();
|
||||||
|
var oldPosition = ed.getPosition();
|
||||||
oldValue = oldModel.getValue() || "";
|
oldValue = oldModel.getValue() || "";
|
||||||
newModel = monaco.editor.createModel((oldValue || ""), mode);
|
newModel = monaco.editor.createModel((oldValue || ""), mode);
|
||||||
ed.setModel(newModel);
|
ed.setModel(newModel);
|
||||||
oldModel.dispose();
|
oldModel.dispose();
|
||||||
|
ed.setScrollTop(oldScrollTop, 1/* immediate */);
|
||||||
|
ed.setScrollLeft(oldScrollLeft, 1/* immediate */);
|
||||||
|
ed.setPosition(oldPosition);
|
||||||
|
ed.setSelections(oldSelections);
|
||||||
} else {
|
} else {
|
||||||
newModel = monaco.editor.createModel((oldValue || ""), mode);
|
newModel = monaco.editor.createModel((oldValue || ""), mode);
|
||||||
ed.setModel(newModel);
|
ed.setModel(newModel);
|
||||||
oldModel.dispose();
|
|
||||||
}
|
}
|
||||||
if (cb && typeof cb == "function") {
|
if (cb && typeof cb == "function") {
|
||||||
cb();
|
cb();
|
||||||
@ -996,6 +1002,7 @@ RED.editor.codeEditor.monaco = (function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ed.destroy = function destroy() {
|
ed.destroy = function destroy() {
|
||||||
|
if(watchTimer) { clearInterval(watchTimer); }
|
||||||
try {
|
try {
|
||||||
//dispose serverside addExtraLib disposible we added - this is the only way (https://github.com/microsoft/monaco-editor/issues/1002#issuecomment-564123586)
|
//dispose serverside addExtraLib disposible we added - this is the only way (https://github.com/microsoft/monaco-editor/issues/1002#issuecomment-564123586)
|
||||||
if(Object.keys(loadedLibs.JS).length) {
|
if(Object.keys(loadedLibs.JS).length) {
|
||||||
@ -1024,6 +1031,8 @@ RED.editor.codeEditor.monaco = (function() {
|
|||||||
}
|
}
|
||||||
} catch (error) { }
|
} catch (error) { }
|
||||||
try {
|
try {
|
||||||
|
var m = this.getModel();
|
||||||
|
m.dispose();
|
||||||
this.setModel(null);
|
this.setModel(null);
|
||||||
} catch (e) { }
|
} catch (e) { }
|
||||||
|
|
||||||
@ -1171,6 +1180,80 @@ RED.editor.codeEditor.monaco = (function() {
|
|||||||
}
|
}
|
||||||
ed._mode = editorOptions.language;
|
ed._mode = editorOptions.language;
|
||||||
|
|
||||||
|
//as models are signleton, consts and let are avialable to other javascript instances
|
||||||
|
//so when not focused, set editor mode to text temporarily to avoid multiple defs
|
||||||
|
ed.onDidBlurEditorWidget(function() {
|
||||||
|
if(isVisible(el) == false) {
|
||||||
|
if(ed._mode == "javascript") {
|
||||||
|
ed.setMode('text');
|
||||||
|
ed._tempMode = "text";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
ed.onDidFocusEditorWidget(function() {
|
||||||
|
if(ed._mode == "javascript" && ed._tempMode == "text") {
|
||||||
|
ed._tempMode = "";
|
||||||
|
setTimeout(function() {
|
||||||
|
ed.setMode('javascript');
|
||||||
|
}, 5);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
watchVisibility(el, function(visible, element) {
|
||||||
|
if(visible) {
|
||||||
|
if(ed._mode == "javascript" && ed._tempMode == "text") {
|
||||||
|
ed._tempMode = "";
|
||||||
|
setTimeout(function() {
|
||||||
|
ed.setMode('javascript');
|
||||||
|
}, 5);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(ed._mode == "javascript") {
|
||||||
|
ed.setMode('text');
|
||||||
|
ed._tempMode = "text";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function watchVisibility(element, callback) {
|
||||||
|
try {
|
||||||
|
var options = {
|
||||||
|
root: $(element).closest("div.red-ui-tray-content")[0] || document,
|
||||||
|
attributes: true,
|
||||||
|
childList: true,
|
||||||
|
};
|
||||||
|
var observer = new IntersectionObserver(function(entries, observer) {
|
||||||
|
entries.forEach(function(entry) {
|
||||||
|
callback(entry.intersectionRatio > 0, entry);
|
||||||
|
});
|
||||||
|
}, options);
|
||||||
|
observer.observe(element);
|
||||||
|
} catch (e1) {
|
||||||
|
//browser not supporting IntersectionObserver?
|
||||||
|
//fall back to polling
|
||||||
|
try {
|
||||||
|
watchTimer = setInterval(function() {
|
||||||
|
elVisible = isVisible(el);
|
||||||
|
if(elVisible != elVisibleMem) {
|
||||||
|
callback(elVisible, element);
|
||||||
|
}
|
||||||
|
elVisible = elVisibleMem;
|
||||||
|
}, 200);
|
||||||
|
} catch (e2) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//by default, set javascript editors to text mode.
|
||||||
|
//when elemt becomes visible, it will be (re) set to javascript mode
|
||||||
|
//this is to ensure multiple editors sharing the model dont presnet its
|
||||||
|
//consts & lets to each other
|
||||||
|
if(ed._mode == "javascript") {
|
||||||
|
ed.setMode('text');
|
||||||
|
ed._tempMode = "text";
|
||||||
|
}
|
||||||
|
|
||||||
if (editorOptions.language === 'markdown') {
|
if (editorOptions.language === 'markdown') {
|
||||||
$(el).addClass("red-ui-editor-text-container-toolbar");
|
$(el).addClass("red-ui-editor-text-container-toolbar");
|
||||||
ed.toolbar = RED.editor.customEditTypes['_markdown'].buildToolbar(toolbarRow, ed);
|
ed.toolbar = RED.editor.customEditTypes['_markdown'].buildToolbar(toolbarRow, ed);
|
||||||
@ -1209,6 +1292,12 @@ RED.editor.codeEditor.monaco = (function() {
|
|||||||
return ed;
|
return ed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isVisible(el) {
|
||||||
|
if(!el.offsetHeight && !el.offsetWidth) { return false; }
|
||||||
|
if(getComputedStyle(el).visibility === 'hidden') { return false; }
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
/**
|
/**
|
||||||
* Editor type
|
* Editor type
|
||||||
|
Loading…
Reference in New Issue
Block a user