From bd59661b2c815830f130d21156c3162f8c6b0269 Mon Sep 17 00:00:00 2001 From: Mohamed El Mouctar Haidara Date: Sun, 21 Aug 2022 16:55:38 +0200 Subject: [PATCH] fix: Avoid recursive endless loop when a role references itself (#123) --- .../data/highlight-hover.js | 51 ++++++++++--------- 1 file changed, 28 insertions(+), 23 deletions(-) diff --git a/ansibleplaybookgrapher/data/highlight-hover.js b/ansibleplaybookgrapher/data/highlight-hover.js index 20ead97e..6024177b 100644 --- a/ansibleplaybookgrapher/data/highlight-hover.js +++ b/ansibleplaybookgrapher/data/highlight-hover.js @@ -18,21 +18,24 @@ let currentSelectedElement = null; /** * Highlight the linked nodes of the given root element * @param {Element} parentElement + * @param {string[]} visitedElements */ -function highlightLinkedNodes(parentElement) { - const parentElementId = $(parentElement).attr('id') +function highlightLinkedNodes(parentElement, visitedElements = []) { $(parentElement).find('link').each(function (index, element) { - const target = $(element).attr('target'); - const edge = $(element).attr('edge'); + const linkedElementId = $(element).attr('target'); + const edgeId = $(element).attr('edge'); - const currentElement = $(`#${target}`); + const currentElement = $(`#${linkedElementId}`); currentElement.addClass(HIGHLIGHT_CLASS); // Highlight the edge point to the target - $(`#${edge}`).addClass(HIGHLIGHT_CLASS); + $(`#${edgeId}`).addClass(HIGHLIGHT_CLASS); - // Recursively highlight - highlightLinkedNodes(currentElement); + if (!visitedElements.includes(linkedElementId)) { + visitedElements.push(linkedElementId); + // Recursively highlight + highlightLinkedNodes(currentElement, visitedElements); + } }) } @@ -40,29 +43,32 @@ function highlightLinkedNodes(parentElement) { /** * Unhighlight the linked nodes of the given root element * @param {Element} parentElement + * @param {string[]} visitedElements * @param {boolean} isHover True when we are coming from a mouseleave event. In that case, we should not unhighlight if * the parentElement is the current selected element */ -function unHighlightLinkedNodes(parentElement, isHover) { +function unHighlightLinkedNodes(parentElement, visitedElements = [], isHover) { const currentSelectedElementId = $(currentSelectedElement).attr('id'); - const parentElementId = $(parentElement).attr('id') - // Do not unhighlight the current current selected element + // Do not unhighlight the current selected element if ($(parentElement).attr('id') !== currentSelectedElementId || !isHover) { $(parentElement).find('link').each(function (index, element) { const linkedElementId = $(element).attr('target'); - const edge = $(element).attr('edge'); + const edgeId = $(element).attr('edge'); - const linkedElement = $('#' + linkedElementId); + const linkedElement = $(`#${linkedElementId}`); if (linkedElement.attr('id') !== currentSelectedElementId) { linkedElement.removeClass(HIGHLIGHT_CLASS); // Unhighlight the edge point to the target - $(`#${edge}`).removeClass(HIGHLIGHT_CLASS); + $(`#${edgeId}`).removeClass(HIGHLIGHT_CLASS); - // Recursively unhighlight - unHighlightLinkedNodes(linkedElement, isHover); + if (!visitedElements.includes(linkedElementId)) { + visitedElements.push(linkedElementId); + // Recursively unhighlight + unHighlightLinkedNodes(linkedElement, visitedElements, isHover); + } } }) @@ -75,7 +81,7 @@ function unHighlightLinkedNodes(parentElement, isHover) { * @param {Event} event */ function hoverMouseEnter(event) { - highlightLinkedNodes(event.currentTarget); + highlightLinkedNodes(event.currentTarget, []); } /** @@ -83,7 +89,7 @@ function hoverMouseEnter(event) { * @param {Event} event */ function hoverMouseLeave(event) { - unHighlightLinkedNodes(event.currentTarget, true); + unHighlightLinkedNodes(event.currentTarget, [], true); } /** @@ -97,18 +103,18 @@ function clickOnElement(event) { if (newClickedElement.attr('id') === $(currentSelectedElement).attr('id')) { // clicking again on the same element newClickedElement.removeClass(HIGHLIGHT_CLASS); - unHighlightLinkedNodes(currentSelectedElement, false); + unHighlightLinkedNodes(currentSelectedElement, [], false); currentSelectedElement = null; } else { // clicking on a different node // Remove highlight from all the nodes linked to the current selected node - unHighlightLinkedNodes(currentSelectedElement, false); + unHighlightLinkedNodes(currentSelectedElement, [], false); if (currentSelectedElement) { currentSelectedElement.removeClass(HIGHLIGHT_CLASS); } newClickedElement.addClass(HIGHLIGHT_CLASS); - highlightLinkedNodes(newClickedElement); + highlightLinkedNodes(newClickedElement, []); currentSelectedElement = newClickedElement; } } @@ -122,8 +128,7 @@ function dblClickElement(event) { const links = $(newElementDlbClicked).find("a[xlink\\:href]"); if (links.length > 0) { - const targetLink = $(links[0]).attr("xlink:href"); - document.location = targetLink; + document.location = $(links[0]).attr("xlink:href"); } else { console.log("No links found on this element"); }