在尝试为使用香草JS呈现的某些foreignObject
添加点击事件监听器时,我目前遇到一些问题。
当我使用内置的d3 on click函数时,它可以工作,但我更希望使用javascript代码来完成它。
但是,该函数从不触发这些元素,我也不明白为什么。
该代码示例并不完整,但应突出显示我正在尝试做的事情。
var nodes = g.selectAll("foreignObject")
.data(response.nodes)
.enter()
.append("foreignObject")
.attr("x", function(d) {
return d.x - nodeWidth / 2;
})
.attr("y", function(d) {
return d.y - nodeHeight / 2;
})
.attr("width", nodeWidth)
.attr("height", nodeHeight)
.append("xhtml:div")
.attr("class", "outer")
.html(function(d) {
var nodeHtml = createNodeElement(d);
return nodeHtml.outerHTML;
})
// If I append the img like this, it works, but ends up in the wrong "element scope"
.append("img")
.attr("class", "optionsImg")
.attr("src","/images/options-squares.svg")
.on("click", function(d) {
currentTooltipObject = d;
renderTooltipDiv();
});
function createNodeElement(d) {
let nodeElement = document.createElement("div");
nodeElement.className = "nodeElement";
let nodeOptionsImg = document.createElement("img");
nodeOptionsImg.className = "nodeOptionsImg";
nodeOptionsImg.src = "/images/options-squares.svg";
nodeOptionsImg.addEventListener("click", function() {
console.log("Clicked on optionsImg for this object: "+d);
});
nodeElement.appendChild(nodeOptionsImg);
return nodeElement;
}
答案 0 :(得分:0)
您的方法的主要问题在于,使用outerHTML
和innerHTML
(.html()
内部使用)创建/移动/复制元素的过程有点像序列化和反序列化HTML DOM树。这适用于HTML元素本身,但是,它不保留事件侦听器。因此,在此过程中,您附加到函数createNodeElement
中的元素的侦听器将丢失。这是其他问题的变体,例如"Is it possible to append to innerHTML without destroying descendants' event listeners?"。
如果您退后一步,重新阅读D3 API docs,您将意识到您实际上已经存在了:D3提供了将本机DOM节点附加到选择内容的方法:
选择。追加(类型)<>
如果指定的 type 是一个函数,则会为每个选定元素求值,依次传递当前基准( d ),当前索引(< em> i )和当前组( nodes ),其中 this 作为当前DOM元素( nodes [ i ])。此函数应返回要附加的元素。
如果您希望坚持使用createNodeElement
的实现以使用本机JS方法创建元素,则可以将该函数简单地传递给selection.append()
,因为它会返回一个新创建的节点及其节点。 <img>
个子节点。因此,您的代码可以简化为:
var nodes = g.selectAll("foreignObject")
/* styling omitted */
.append("xhtml:div")
.attr("class", "outer")
.append(createNodeElement);
因为仅对DOM节点的引用传递给所有附加到元素的事件侦听器,因此也会保留。
答案 1 :(得分:-1)
在ExpiresByType text/html "access 1 month"
ExpiresDefault "access 1 month"
中,createNodeElement
函数中的nodeOptionsImg
元素尚未呈现。侦听器只能添加到渲染的元素。