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