mirror of
				https://github.com/node-red/node-red.git
				synced 2025-03-01 10:36:34 +00:00 
			
		
		
		
	Back/Frovard Navigation by window.history feature added to editor.
				
					
				
			This commit is contained in:
		| @@ -88,6 +88,12 @@ | ||||
|                 "language": "Language", | ||||
|                 "browserDefault": "Browser default" | ||||
|             }, | ||||
|             "navigationHistory":{ | ||||
|                 "title":"Back/Forward Navigation", | ||||
|                 "trackNodes": "Enable node selection tracking", | ||||
|                 "trackFlows": "Enable flow selection tracking", | ||||
|                 "trackEditor": "Enable editor selection tracking" | ||||
|             }, | ||||
|             "sidebar": { | ||||
|                 "show": "Show sidebar" | ||||
|             }, | ||||
|   | ||||
| @@ -242,59 +242,12 @@ var RED = (function() { | ||||
|             url: 'flows', | ||||
|             success: function(nodes) { | ||||
|                 if (nodes) { | ||||
|                     var currentHash = window.location.hash; | ||||
|                     RED.nodes.version(nodes.rev); | ||||
|                     loader.reportProgress(RED._("event.importFlows"),90 ) | ||||
|                     try { | ||||
|                         RED.nodes.import(nodes.flows); | ||||
|                         RED.nodes.dirty(false); | ||||
|                         RED.view.redraw(true); | ||||
|                         if (/^#(flow|node|group)\/.+$/.test(currentHash)) { | ||||
|                             const hashParts = currentHash.split('/') | ||||
|                             const showEditDialog = hashParts.length > 2 && hashParts[2] === 'edit' | ||||
|                             if (hashParts[0] === '#flow') { | ||||
|                                 RED.workspaces.show(hashParts[1], true); | ||||
|                                 if (showEditDialog) { | ||||
|                                     RED.workspaces.edit() | ||||
|                                 } | ||||
|                             } else if (hashParts[0] === '#node') { | ||||
|                                 const nodeToShow = RED.nodes.node(hashParts[1]) | ||||
|                                 if (nodeToShow) { | ||||
|                                     setTimeout(() => { | ||||
|                                         RED.view.reveal(nodeToShow.id) | ||||
|                                         window.location.hash = currentHash | ||||
|                                         if (showEditDialog) { | ||||
|                                             RED.editor.edit(nodeToShow) | ||||
|                                         } | ||||
|                                     }, 50) | ||||
|                                 } | ||||
|                             } else if (hashParts[0] === '#group') { | ||||
|                                 const nodeToShow = RED.nodes.group(hashParts[1]) | ||||
|                                 if (nodeToShow) { | ||||
|                                     RED.view.reveal(nodeToShow.id) | ||||
|                                     window.location.hash = currentHash | ||||
|                                     if (showEditDialog) { | ||||
|                                         RED.editor.editGroup(nodeToShow) | ||||
|                                     } | ||||
|                                 } | ||||
|                             } | ||||
|                         } | ||||
|                         if (RED.workspaces.count() > 0) { | ||||
|                             const hiddenTabs = JSON.parse(RED.settings.getLocal("hiddenTabs")||"{}"); | ||||
|                             const workspaces = RED.nodes.getWorkspaceOrder(); | ||||
|                             if (RED.workspaces.active() === 0) { | ||||
|                                 for (let index = 0; index < workspaces.length; index++) { | ||||
|                                     const ws = workspaces[index]; | ||||
|                                     if (!hiddenTabs[ws]) { | ||||
|                                         RED.workspaces.show(ws); | ||||
|                                         break; | ||||
|                                     } | ||||
|                                 } | ||||
|                             } | ||||
|                             if (RED.workspaces.active() === 0) { | ||||
|                                 RED.workspaces.show(workspaces[0]); | ||||
|                             } | ||||
|                         } | ||||
|                     } catch(err) { | ||||
|                         console.warn(err); | ||||
|                         RED.notify( | ||||
| @@ -615,6 +568,7 @@ var RED = (function() { | ||||
|                 if (showProjectWelcome) { | ||||
|                     RED.projects.showStartup(); | ||||
|                 } | ||||
|                 initNavigation() | ||||
|             }); | ||||
|         },100); | ||||
|     } | ||||
| @@ -737,6 +691,117 @@ var RED = (function() { | ||||
|  | ||||
|     } | ||||
|  | ||||
|     function initNavigation() { | ||||
|         let lastNavigated  | ||||
|         let state =  "" | ||||
|         function navigateToHash(currentHash) { | ||||
|             console.log("Navigate", currentHash) | ||||
|             if (currentHash === "") { return revealAndShowEditDialog("fallback") } | ||||
|             if (!/^#(flow|node|group|junction)\/.+$/.test(currentHash)) { return } | ||||
|             const [type, id, edit] = currentHash.split('/') | ||||
|             RED.tray.close(() => revealAndShowEditDialog(type, id, edit === 'edit')); | ||||
|         } | ||||
|         function cancelFlash(type, id) { | ||||
|             if(type === "#flow"){ | ||||
|                 clearInterval($("#red-ui-tab-" + id).removeClass("highlighted")[0].__flashTimer) | ||||
|             } else if (["#node", "#junction", "#group"].includes(type)){ | ||||
|                 const nodeToCancel = RED.nodes[type.substring(1)](id); | ||||
|                 if(nodeToCancel && nodeToCancel.type != "group" && nodeToCancel._def && nodeToCancel._def.category === "config"){ | ||||
|                     let configNode = $(".red-ui-palette-node_id_" + id) | ||||
|                     clearInterval(configNode[0].__flashTimer) | ||||
|                     configNode.children("div").removeClass("highlighted") | ||||
|                 } | ||||
|                 else if(nodeToCancel){ | ||||
|                     clearInterval(nodeToCancel.__flashTimer) | ||||
|                     nodeToCancel.highlighted = false | ||||
|                     RED.view.redraw() | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         function revealAndShowEditDialog(type, id, showEditDialog) { | ||||
|             state = "Nav"; | ||||
|             if(lastNavigated){cancelFlash(lastNavigated.type, lastNavigated.id)} | ||||
|                  | ||||
|             lastNavigated = {type,id} | ||||
|             if (type === '#flow') { | ||||
|                 RED.workspaces.show(id, true, false, true); | ||||
|                 if (showEditDialog) { | ||||
|                     RED.workspaces.edit(); | ||||
|                 } | ||||
|             } else if (["#node", "#junction", "#group"].includes(type)) { | ||||
|                 const nodeToShow = RED.nodes[type.substring(1)](id); | ||||
|                 if (nodeToShow) { | ||||
|                     RED.view.select(nodeToShow.id); | ||||
|                     RED.view.reveal(nodeToShow.id); | ||||
|                     if (showEditDialog && type != "#group") { | ||||
|                         RED.editor.edit(nodeToShow); | ||||
|                     } else if (showEditDialog) { | ||||
|                         RED.editor.editGroup(nodeToShow); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             if (type === "fallback" || RED.workspaces.active() === 0) { | ||||
|                 fallbackWorkspace(); | ||||
|             } | ||||
|             state = "Idle" | ||||
|         } | ||||
|  | ||||
|         function fallbackWorkspace() { | ||||
|             if (RED.workspaces.count() > 0) { | ||||
|                 let workspaces = RED.nodes.getWorkspaceOrder(); | ||||
|                 let fallbackws = workspaces.find(x => !RED.workspaces.isHidden(x)); | ||||
|                 RED.workspaces.show(fallbackws, true); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         function setLocationHash(node, edit) { | ||||
|             if(state === "Nav") {return} | ||||
|             state = "Log" | ||||
|             let newHash = "" | ||||
|             if (["tab", "flow"].includes(node.type) && RED.settings.get("editor.view.view-nav-track-flows")) { | ||||
|                 newHash = "#flow/" + node.id | ||||
|             } | ||||
|             else if (["group", "junction"].includes(node.type) && RED.settings.get("editor.view.view-nav-track-nodes")) { | ||||
|                 newHash = "#" + node.type + "/" + node.id | ||||
|             } | ||||
|             else if (RED.settings.get("editor.view.view-nav-track-nodes")) { | ||||
|                 newHash = "#node/" + node.id | ||||
|             } | ||||
|             if (edit) { | ||||
|                 newHash += "/edit" | ||||
|             } | ||||
|             console.log("set hash", newHash) | ||||
|             window.location.hash = newHash | ||||
|         } | ||||
|  | ||||
|         navigateToHash(window.location.hash) | ||||
|  | ||||
|         window.addEventListener('hashchange', function (e) { | ||||
|             if(state != "Idle") { | ||||
|                 state = "Idle" | ||||
|                 return | ||||
|             } | ||||
|             navigateToHash(window.location.hash) | ||||
|         }, false); | ||||
|  | ||||
|         RED.events.on("view:selection-changed", function (selection) { | ||||
|             if (selection.nodes && selection.nodes.length === 1) { | ||||
|                 setLocationHash(selection.nodes[0]) | ||||
|             } | ||||
|         }); | ||||
|         RED.events.on("workspace:change",function(event){ | ||||
|             setLocationHash({id:event.workspace, type:"flow"}) | ||||
|         }); | ||||
|  | ||||
|         RED.events.on("tab-config:selection-changed", function (node) { | ||||
|             setLocationHash(node) | ||||
|         }); | ||||
|         RED.events.on("editor:editing", function(node){ | ||||
|             setLocationHash(node, true) | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     function loadEditor() { | ||||
|         RED.workspaces.init(); | ||||
|         RED.statusBar.init(); | ||||
|   | ||||
| @@ -1125,6 +1125,7 @@ RED.editor = (function() { | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|         RED.events.emit("editor:editing",editing_node); | ||||
|         RED.tray.show(trayOptions); | ||||
|     } | ||||
|     /** | ||||
| @@ -1512,6 +1513,7 @@ RED.editor = (function() { | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|         RED.events.emit("editor:editing",editing_config_node); | ||||
|         RED.tray.show(trayOptions); | ||||
|     } | ||||
|  | ||||
| @@ -1682,6 +1684,7 @@ RED.editor = (function() { | ||||
|             show: function() { | ||||
|             } | ||||
|         } | ||||
|         RED.events.emit("editor:editing",editing_node); | ||||
|         RED.tray.show(trayOptions); | ||||
|     } | ||||
|  | ||||
| @@ -1795,6 +1798,7 @@ RED.editor = (function() { | ||||
|         if (editTrayWidthCache.hasOwnProperty('group')) { | ||||
|             trayOptions.width = editTrayWidthCache['group']; | ||||
|         } | ||||
|         RED.events.emit("editor:editing",editing_node); | ||||
|         RED.tray.show(trayOptions); | ||||
|     } | ||||
|  | ||||
| @@ -1929,6 +1933,7 @@ RED.editor = (function() { | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         RED.events.emit("editor:editing", workspace); | ||||
|         RED.tray.show(trayOptions); | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -16,7 +16,6 @@ | ||||
| RED.sidebar.config = (function() { | ||||
|  | ||||
|     let flashingConfigNode; | ||||
|     let flashingConfigNodeTimer; | ||||
|  | ||||
|     var content = document.createElement("div"); | ||||
|     content.className = "red-ui-sidebar-node-config"; | ||||
| @@ -180,6 +179,7 @@ RED.sidebar.config = (function() { | ||||
|                         $(this).addClass("selected"); | ||||
|                     } | ||||
|                     RED.sidebar.info.refresh(node); | ||||
|                     RED.events.emit("tab-config:selection-changed",node) | ||||
|                 }); | ||||
|                 nodeDiv.on('dblclick',function(e) { | ||||
|                     e.stopPropagation(); | ||||
| @@ -357,24 +357,22 @@ RED.sidebar.config = (function() { | ||||
|     function flashConfigNode(el) { | ||||
|         if(flashingConfigNode && flashingConfigNode.length) { | ||||
|             //cancel current flashing node before flashing new node | ||||
|             clearInterval(flashingConfigNodeTimer); | ||||
|             flashingConfigNodeTimer = null; | ||||
|             clearInterval(el[0].__flashTimer); | ||||
|             flashingConfigNode.children("div").removeClass('highlighted'); | ||||
|             flashingConfigNode = null; | ||||
|         } | ||||
|         if(!el || !el.children("div").length) { return; } | ||||
|  | ||||
|         flashingConfigNodeTimer = setInterval(function(flashEndTime) { | ||||
|         el[0].__flashTimer = setInterval(function(flashEndTime) { | ||||
|             if (flashEndTime >= Date.now()) { | ||||
|                 const highlighted = el.children("div").hasClass("highlighted"); | ||||
|                 el.children("div").toggleClass('highlighted', !highlighted) | ||||
|             } else { | ||||
|                 clearInterval(flashingConfigNodeTimer); | ||||
|                 flashingConfigNodeTimer = null; | ||||
|                 clearInterval(el[0].__flashTimer); | ||||
|                 flashingConfigNode = null; | ||||
|                 el.children("div").removeClass('highlighted'); | ||||
|             } | ||||
|         }, 100, Date.now() + 2200); | ||||
|         }, 100, Date.now() + 2200, el); | ||||
|         flashingConfigNode = el; | ||||
|         el.children("div").addClass('highlighted'); | ||||
|     } | ||||
|   | ||||
| @@ -335,6 +335,8 @@ | ||||
|                         stack[stack.length-1].tray.css("z-index", "auto"); | ||||
|                     } | ||||
|                 },250) | ||||
|             }else if (done){ | ||||
|                 done() | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|   | ||||
| @@ -143,6 +143,14 @@ RED.userSettings = (function() { | ||||
|                 {setting:"view-node-show-label",label:"menu.label.showNodeLabelDefault",default: true, toggle:true} | ||||
|             ] | ||||
|         }, | ||||
|         { | ||||
|             title: "menu.label.navigationHistory.title", | ||||
|             options: [ | ||||
|                 {setting:"view-nav-track-nodes",label:"menu.label.navigationHistory.trackNodes",default: true, toggle:true}, | ||||
|                 {setting:"view-nav-track-flows",label:"menu.label.navigationHistory.trackFlows",default: true, toggle:true}, | ||||
|                 {setting:"view-nav-track-edit",label:"menu.label.navigationHistory.trackEditor",default: false, toggle:true} | ||||
|             ] | ||||
|         }, | ||||
|         { | ||||
|             title: "menu.label.other", | ||||
|             options: [ | ||||
|   | ||||
| @@ -25,7 +25,6 @@ RED.workspaces = (function() { | ||||
|     var viewStackPos = 0; | ||||
|  | ||||
|     let flashingTab; | ||||
|     let flashingTabTimer; | ||||
|  | ||||
|     function addToViewStack(id) { | ||||
|         if (viewStackPos !== viewStack.length) { | ||||
| @@ -136,12 +135,10 @@ RED.workspaces = (function() { | ||||
|                 if (tab) { | ||||
|                     $("#red-ui-workspace-chart").show(); | ||||
|                     activeWorkspace = tab.id; | ||||
|                     window.location.hash = 'flow/'+tab.id; | ||||
|                     $("#red-ui-workspace").toggleClass("red-ui-workspace-disabled",!!tab.disabled); | ||||
|                 } else { | ||||
|                     $("#red-ui-workspace-chart").hide(); | ||||
|                     activeWorkspace = 0; | ||||
|                     window.location.hash = ''; | ||||
|                 } | ||||
|                 event.workspace = activeWorkspace; | ||||
|                 RED.events.emit("workspace:change",event); | ||||
| @@ -550,25 +547,23 @@ RED.workspaces = (function() { | ||||
|     function flashTab(tabId) { | ||||
|         if(flashingTab && flashingTab.length) { | ||||
|             //cancel current flashing node before flashing new node | ||||
|             clearInterval(flashingTabTimer); | ||||
|             flashingTabTimer = null; | ||||
|             clearInterval(flashingTab.__flashTimer); | ||||
|             flashingTab.removeClass('highlighted'); | ||||
|             flashingTab = null; | ||||
|         } | ||||
|         let tab = $("#red-ui-tab-" + tabId); | ||||
|         if(!tab || !tab.length) { return; } | ||||
|  | ||||
|         flashingTabTimer = setInterval(function(flashEndTime) { | ||||
|         tab[0].__flashTimer = setInterval(function(flashEndTime) { | ||||
|             if (flashEndTime >= Date.now()) { | ||||
|                 const highlighted = tab.hasClass("highlighted"); | ||||
|                 tab.toggleClass('highlighted', !highlighted) | ||||
|             } else { | ||||
|                 clearInterval(flashingTabTimer); | ||||
|                 flashingTabTimer = null; | ||||
|                 clearInterval(tab[0].__flashTimer); | ||||
|                 flashingTab = null; | ||||
|                 tab.removeClass('highlighted'); | ||||
|             } | ||||
|         }, 100, Date.now() + 2200); | ||||
|         }, 100, Date.now() + 2200, tab); | ||||
|         flashingTab = tab; | ||||
|         tab.addClass('highlighted'); | ||||
|     } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user