Skip to content

Instantly share code, notes, and snippets.

@deenar
Forked from billdwhite/index.html
Last active September 24, 2015 08:13
Show Gist options
  • Save deenar/336efdeb97f1c79d4a6b to your computer and use it in GitHub Desktop.
Save deenar/336efdeb97f1c79d4a6b to your computer and use it in GitHub Desktop.
D3 Treemap with Headers - DIV Labels
var BrowserDetect =
{
init: function ()
{
this.browser = this.searchString(this.dataBrowser) || "Other";
this.version = this.searchVersion(navigator.userAgent) || this.searchVersion(navigator.appVersion) || "Unknown";
},
searchString: function (data)
{
for (var i=0 ; i < data.length ; i++)
{
var dataString = data[i].string;
this.versionSearchString = data[i].subString;
if (dataString.indexOf(data[i].subString) != -1)
{
return data[i].identity;
}
}
},
searchVersion: function (dataString)
{
var index = dataString.indexOf(this.versionSearchString);
if (index == -1) return;
return parseFloat(dataString.substring(index+this.versionSearchString.length+1));
},
dataBrowser:
[
{ string: navigator.userAgent, subString: "Chrome", identity: "Chrome" },
{ string: navigator.userAgent, subString: "MSIE", identity: "Explorer" },
{ string: navigator.userAgent, subString: "Firefox", identity: "Firefox" },
{ string: navigator.userAgent, subString: "Safari", identity: "Safari" },
{ string: navigator.userAgent, subString: "Opera", identity: "Opera" }
]
};
BrowserDetect.init();
{
"children":[
{
"children":[
{
"children":[
{
"children":[
],
"name":"Asian FX",
"data":{
"var1d":-18.16,
"size":-26.74,
"description":"Asian FX",
"name2":"Foreign Exchange",
"var10d":-23.37,
"$angularWidth":18.16,
"$area":18.16,
"$color":"#FFB100",
"es":-26.74,
"days":-23.37,
"level":4
},
"id":115400,
"parentId":115000
},
{
"children":[
],
"name":"LATAM FX",
"data":{
"var1d":-22.4,
"size":-34.9,
"description":"LATAM FX",
"name2":"Foreign Exchange",
"var10d":-33.06,
"$angularWidth":22.4,
"$area":22.4,
"$color":"#FFFF00",
"es":-34.9,
"days":-33.06,
"level":4
},
"id":115200,
"parentId":115000
},
{
"children":[
],
"name":"European FX",
"data":{
"var1d":-40.34,
"size":-65.11,
"description":"European FX",
"name2":"Foreign Exchange",
"var10d":-59.08,
"$angularWidth":40.34,
"$area":40.34,
"$color":"#36FFC8",
"es":-65.11,
"days":-59.08,
"level":4
},
"id":115300,
"parentId":115000
},
{
"children":[
],
"name":"Developing FX",
"data":{
"var1d":-22.31,
"size":-33.81,
"description":"Developing FX",
"name2":"Foreign Exchange",
"var10d":-30.93,
"$angularWidth":22.31,
"$area":22.31,
"$color":"#FFE700",
"es":-33.81,
"days":-30.93,
"level":4
},
"id":115500,
"parentId":115000
},
{
"children":[
],
"name":"US",
"data":{
"var1d":-19.24,
"size":-28.33,
"description":"US",
"name2":"Foreign Exchange",
"var10d":-24.59,
"$angularWidth":19.24,
"$area":19.24,
"$color":"#FFB900",
"es":-28.33,
"days":-24.59,
"level":4
},
"id":115100,
"parentId":115000
}
],
"name":"Foreign Exchange",
"data":{
"var1d":-162.39,
"size":-255.88,
"description":"Foreign Exchange",
"name2":"Foreign Exchange",
"var10d":-227.91,
"$angularWidth":162.39,
"$area":162.39,
"$color":"#0000FF",
"es":-255.88,
"days":-227.91,
"level":3
},
"id":115000,
"parentId":110000
},
{
"children":[
{
"children":[
],
"name":"US Debt",
"data":{
"var1d":-18.53,
"size":-29.25,
"description":"US Debt",
"name2":"Global Debt",
"var10d":-25.74,
"$angularWidth":18.53,
"$area":18.53,
"$color":"#FFC100",
"es":-29.25,
"days":-25.74,
"level":4
},
"id":112100,
"parentId":112000
},
{
"children":[
],
"name":"European Debt",
"data":{
"var1d":-19.33,
"size":-30.3,
"description":"European Debt",
"name2":"Global Debt",
"var10d":-27.12,
"$angularWidth":19.33,
"$area":19.33,
"$color":"#FFD000",
"es":-30.3,
"days":-27.12,
"level":4
},
"id":112200,
"parentId":112000
},
{
"children":[
],
"name":"Emerging Market Debt",
"data":{
"var1d":-21.34,
"size":-32.95,
"description":"Emerging Market Debt",
"name2":"Global Debt",
"var10d":-29.36,
"$angularWidth":21.34,
"$area":21.34,
"$color":"#FFE000",
"es":-32.95,
"days":-29.36,
"level":4
},
"id":112400,
"parentId":112000
},
{
"children":[
],
"name":"Asian Debt",
"data":{
"var1d":-18.32,
"size":-28.88,
"description":"Asian Debt",
"name2":"Global Debt",
"var10d":-25.08,
"$angularWidth":18.32,
"$area":18.32,
"$color":"#FFC100",
"es":-28.88,
"days":-25.08,
"level":4
},
"id":112300,
"parentId":112000
}
],
"name":"Global Debt",
"data":{
"var1d":-98.38,
"size":-152.9,
"description":"Global Debt",
"name2":"Global Debt",
"var10d":-135.03,
"$angularWidth":98.38,
"$area":98.38,
"$color":"#0000FF",
"es":-152.9,
"days":-135.03,
"level":3
},
"id":112000,
"parentId":110000
},
{
"children":[
{
"children":[
],
"name":"Index Trading",
"data":{
"var1d":-18.76,
"size":-28.36,
"description":"Index Trading",
"name2":"Credit Trading",
"var10d":-25.27,
"$angularWidth":18.76,
"$area":18.76,
"$color":"#FFC100",
"es":-28.36,
"days":-25.27,
"level":4
},
"id":113200,
"parentId":113000
},
{
"children":[
],
"name":"Structured Credit",
"data":{
"var1d":-4.54,
"size":-7.33,
"description":"Structured Credit",
"name2":"Credit Trading",
"var10d":-6.51,
"$angularWidth":4.54,
"$area":4.54,
"$color":"#FF2E00",
"es":-7.33,
"days":-6.51,
"level":4
},
"id":113100,
"parentId":113000
},
{
"children":[
],
"name":"Loans",
"data":{
"var1d":-20.53,
"size":-31.39,
"description":"Loans",
"name2":"Credit Trading",
"var10d":-29.65,
"$angularWidth":20.53,
"$area":20.53,
"$color":"#FFE000",
"es":-31.39,
"days":-29.65,
"level":4
},
"id":113300,
"parentId":113000
},
{
"children":[
],
"name":"Asset Backed",
"data":{
"var1d":-19.06,
"size":-27.8,
"description":"Asset Backed",
"name2":"Credit Trading",
"var10d":-24.02,
"$angularWidth":19.06,
"$area":19.06,
"$color":"#FFB900",
"es":-27.8,
"days":-24.02,
"level":4
},
"id":113400,
"parentId":113000
}
],
"name":"Credit Trading",
"data":{
"var1d":-84.34,
"size":-126.48,
"description":"Credit Trading",
"name2":"Credit Trading",
"var10d":-112.44,
"$angularWidth":84.34,
"$area":84.34,
"$color":"#0000FF",
"es":-126.48,
"days":-112.44,
"level":3
},
"id":113000,
"parentId":110000
},
{
"children":[
{
"children":[
],
"name":"Energy",
"data":{
"var1d":-48.42,
"size":-73.61,
"description":"Energy",
"name2":"Commodities",
"var10d":-66.02,
"$angularWidth":48.42,
"$area":48.42,
"$color":"#00FFFF",
"es":-73.61,
"days":-66.02,
"level":4
},
"id":114100,
"parentId":114000
},
{
"children":[
],
"name":"Metals",
"data":{
"var1d":-5.61,
"size":-8.8,
"description":"Metals",
"name2":"Commodities",
"var10d":-8.26,
"$angularWidth":5.61,
"$area":5.61,
"$color":"#FF3D00",
"es":-8.8,
"days":-8.26,
"level":4
},
"id":114200,
"parentId":114000
},
{
"children":[
],
"name":"Lifestock",
"data":{
"var1d":-20.01,
"size":-32.7,
"description":"Lifestock",
"name2":"Commodities",
"var10d":-29.07,
"$angularWidth":20.01,
"$area":20.01,
"$color":"#FFE000",
"es":-32.7,
"days":-29.07,
"level":4
},
"id":114300,
"parentId":114000
},
{
"children":[
],
"name":"Agricultural",
"data":{
"var1d":-20.77,
"size":-30.47,
"description":"Agricultural",
"name2":"Commodities",
"var10d":-26.64,
"$angularWidth":20.77,
"$area":20.77,
"$color":"#FFC800",
"es":-30.47,
"days":-26.64,
"level":4
},
"id":115110,
"parentId":114000
}
],
"name":"Commodities",
"data":{
"var1d":-136.23,
"size":-205.74,
"description":"Commodities",
"name2":"Commodities",
"var10d":-180.88,
"$angularWidth":136.23,
"$area":136.23,
"$color":"#0000FF",
"es":-205.74,
"days":-180.88,
"level":3
},
"id":114000,
"parentId":110000
},
{
"children":[
{
"children":[
],
"name":"US Equities",
"data":{
"var1d":-77.79,
"size":-117.15,
"description":"US Equities",
"name2":"Global Equities",
"var10d":-101.13,
"$angularWidth":77.79,
"$area":77.79,
"$color":"#0000FF",
"es":-117.15,
"days":-101.13,
"level":4
},
"id":111100,
"parentId":111000
},
{
"children":[
],
"name":"Dev Equities",
"data":{
"var1d":-21.37,
"size":-35.99,
"description":"Dev Equities",
"name2":"Global Equities",
"var10d":-32.93,
"$angularWidth":21.37,
"$area":21.37,
"$color":"#FFF700",
"es":-35.99,
"days":-32.93,
"level":4
},
"id":111500,
"parentId":111000
},
{
"children":[
],
"name":"Asian Equities",
"data":{
"var1d":-18.88,
"size":-27.7,
"description":"Asian Equities",
"name2":"Global Equities",
"var10d":-24.35,
"$angularWidth":18.88,
"$area":18.88,
"$color":"#FFB900",
"es":-27.7,
"days":-24.35,
"level":4
},
"id":111400,
"parentId":111000
},
{
"children":[
],
"name":"European Equties",
"data":{
"var1d":-21.59,
"size":-31.58,
"description":"European Equties",
"name2":"Global Equities",
"var10d":-29.05,
"$angularWidth":21.59,
"$area":21.59,
"$color":"#FFE000",
"es":-31.58,
"days":-29.05,
"level":4
},
"id":111300,
"parentId":111000
},
{
"children":[
],
"name":"LATAM Equities",
"data":{
"var1d":-20.1,
"size":-32.09,
"description":"LATAM Equities",
"name2":"Global Equities",
"var10d":-29.07,
"$angularWidth":20.1,
"$area":20.1,
"$color":"#FFE000",
"es":-32.09,
"days":-29.07,
"level":4
},
"id":111200,
"parentId":111000
}
],
"name":"Global Equities",
"data":{
"var1d":-178.2,
"size":-277.06,
"description":"Global Equities",
"name2":"Global Equities",
"var10d":-245.04,
"$angularWidth":178.2,
"$area":178.2,
"$color":"#0000FF",
"es":-277.06,
"days":-245.04,
"level":3
},
"id":111000,
"parentId":110000
}
],
"name":"Investment Bank",
"data":{
"var1d":-660.32,
"size":-1017.38,
"description":"Investment Bank",
"name2":"Investment Bank",
"var10d":-897.93,
"$angularWidth":660.32,
"$area":660.32,
"$color":"#0000FF",
"es":-1017.38,
"days":-897.93,
"level":2
},
"id":110000,
"parentId":100000
},
{
"children":[
],
"name":"Transaction Bank",
"data":{
"var1d":-5.01,
"size":-7.77,
"description":"Transaction Bank",
"name2":"Transaction Bank",
"var10d":-7.27,
"$angularWidth":5.01,
"$area":5.01,
"$color":"#FF3600",
"es":-7.77,
"days":-7.27,
"level":2
},
"id":150000,
"parentId":100000
},
{
"children":[
],
"name":"Asset Management",
"data":{
"var1d":-4.98,
"size":-8.55,
"description":"Asset Management",
"name2":"Asset Management",
"var10d":-7.67,
"$angularWidth":4.98,
"$area":4.98,
"$color":"#FF3600",
"es":-8.55,
"days":-7.67,
"level":2
},
"id":130000,
"parentId":100000
},
{
"children":[
],
"name":"Private Bank",
"data":{
"var1d":-3.41,
"size":-5.23,
"description":"Private Bank",
"name2":"Private Bank",
"var10d":-4.57,
"$angularWidth":3.41,
"$area":3.41,
"$color":"#FF1E00",
"es":-5.23,
"days":-4.57,
"level":2
},
"id":140000,
"parentId":100000
},
{
"children":[
{
"children":[
],
"name":"LATAM Retail",
"data":{
"var1d":-4.81,
"size":-7.22,
"description":"LATAM Retail",
"name2":"LATAM Retail",
"var10d":-6.43,
"$angularWidth":4.81,
"$area":4.81,
"$color":"#FF2E00",
"es":-7.22,
"days":-6.43,
"level":3
},
"id":122000,
"parentId":120000
},
{
"children":[
],
"name":"Developing Retail",
"data":{
"var1d":-5.31,
"size":-7.82,
"description":"Developing Retail",
"name2":"Developing Retail",
"var10d":-7.1,
"$angularWidth":5.31,
"$area":5.31,
"$color":"#FF3600",
"es":-7.82,
"days":-7.1,
"level":3
},
"id":125000,
"parentId":120000
},
{
"children":[
],
"name":"Asian Retail",
"data":{
"var1d":-6.55,
"size":-11.53,
"description":"Asian Retail",
"name2":"Asian Retail",
"var10d":-11.04,
"$angularWidth":6.55,
"$area":6.55,
"$color":"#FF5500",
"es":-11.53,
"days":-11.04,
"level":3
},
"id":124000,
"parentId":120000
},
{
"children":[
],
"name":"European Retail",
"data":{
"var1d":-4.52,
"size":-6.65,
"description":"European Retail",
"name2":"European Retail",
"var10d":-5.62,
"$angularWidth":4.52,
"$area":4.52,
"$color":"#FF2600",
"es":-6.65,
"days":-5.62,
"level":3
},
"id":123000,
"parentId":120000
},
{
"children":[
],
"name":"US Retail",
"data":{
"var1d":-5.85,
"size":-8.92,
"description":"US Retail",
"name2":"US Retail",
"var10d":-8.3,
"$angularWidth":5.85,
"$area":5.85,
"$color":"#FF3D00",
"es":-8.92,
"days":-8.3,
"level":3
},
"id":121000,
"parentId":120000
}
],
"name":"Retail Bank",
"data":{
"var1d":-25.1,
"size":-40.38,
"description":"Retail Bank",
"name2":"Retail Bank",
"var10d":-37.35,
"$angularWidth":25.1,
"$area":25.1,
"$color":"#E0FF1E",
"es":-40.38,
"days":-37.35,
"level":2
},
"id":120000,
"parentId":100000
}
],
"name":"Bank Ltd",
"data":{
"var1d":-698.25,
"size":-1078.87,
"description":"Bank Ltd",
"name2":"Bank Ltd",
"var10d":-952.74,
"$angularWidth":698.25,
"$area":698.25,
"$color":"#0000FF",
"es":-1078.87,
"days":-952.74,
"level":1
},
"id":100000,
"parentId":0
}
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<title>Treemap - Neat Zoom Effect</title>
<script type="text/javascript" src="browserdetect.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
<style type="text/css">
body {
overflow: hidden;
margin: 0;
font-size: 12px;
font-family: "Helvetica Neue", Helvetica;
}
.footer {
z-index: 1;
display: block;
font-size: 26px;
font-weight: 200;
text-shadow: 0 1px 0 #fff;
}
svg {
overflow: hidden;
}
rect {
pointer-events: all;
cursor: pointer;
stroke: #EEEEEE;
}
.chart {
display: block;
margin: auto;
}
.parent .label {
color: #FFFFFF;
text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.3);
-webkit-text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.3);
-moz-text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.3);
}
.labelbody {
background: transparent;
}
.label {
margin: 2px;
white-space: pre;
overflow: hidden;
text-overflow: ellipsis;
text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.3);
-webkit-text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.3);
-moz-text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.3);
}
.child .label {
white-space: pre-wrap;
text-align: center;
text-overflow: ellipsis;
}
.cell {
font-size: 11px;
cursor: pointer
}
</style>
</head>
<body>
<div id="body"></div>
<div class="footer">
<select>
<option value="size">Size</option>
<option value="count">Count</option>
</select>
</div>
</body>
<script type="text/javascript">
var isIE = BrowserDetect.browser == 'Explorer';
var chartWidth = 550;
var chartHeight = 550;
var xscale = d3.scale.linear().range([0, chartWidth]);
var yscale = d3.scale.linear().range([0, chartHeight]);
var color = d3.scale.category10();
var headerHeight = 20;
var headerColor = "#555555";
var transitionDuration = 500;
var root;
var node;
var treemap = d3.layout.treemap()
.round(false)
.size([chartWidth, chartHeight])
.sticky(true)
.value(function(d) {
return d.data.$area;
});
var chart = d3.select("#body")
.append("svg:svg")
.attr("width", chartWidth)
.attr("height", chartHeight)
.append("svg:g");
d3.json("flare.json", function(data) {
node = root = data;
var nodes = treemap.nodes(root);
var children = nodes.filter(function(d) {
return !d.children;
});
var parents = nodes.filter(function(d) {
return d.children;
});
// create parent cells
var parentCells = chart.selectAll("g.cell.parent")
.data(parents, function(d) {
return "p-" + d.name;
});
var parentEnterTransition = parentCells.enter()
.append("g")
.attr("class", "cell parent")
.on("click", function(d) {
zoom(d);
});
parentEnterTransition.append("rect")
.attr("width", function(d) {
return Math.max(0.01, d.dx);
})
.attr("height", headerHeight)
.style("fill", headerColor);
parentEnterTransition.append('foreignObject')
.attr("class", "foreignObject")
.append("xhtml:body")
.attr("class", "labelbody")
.append("div")
.attr("class", "label");
// update transition
var parentUpdateTransition = parentCells.transition().duration(transitionDuration);
parentUpdateTransition.select(".cell")
.attr("transform", function(d) {
return "translate(" + d.dx + "," + d.y + ")";
});
parentUpdateTransition.select("rect")
.attr("width", function(d) {
return Math.max(0.01, d.dx);
})
.attr("height", headerHeight)
.style("fill", headerColor);
parentUpdateTransition.select(".foreignObject")
.attr("width", function(d) {
return Math.max(0.01, d.dx);
})
.attr("height", headerHeight)
.select(".labelbody .label")
.text(function(d) {
return d.name;
});
// remove transition
parentCells.exit()
.remove();
// create children cells
var childrenCells = chart.selectAll("g.cell.child")
.data(children, function(d) {
return "c-" + d.name;
});
// enter transition
var childEnterTransition = childrenCells.enter()
.append("g")
.attr("class", "cell child")
.on("click", function(d) {
zoom(node === d.parent ? root : d.parent);
});
childEnterTransition.append("rect")
.classed("background", true)
.style("fill", function(d) {
return color(d.parent.name);
});
childEnterTransition.append('foreignObject')
.attr("class", "foreignObject")
.attr("width", function(d) {
return Math.max(0.01, d.dx);
})
.attr("height", function(d) {
return Math.max(0.01, d.dy);
})
.append("xhtml:body")
.attr("class", "labelbody")
.append("div")
.attr("class", "label")
.text(function(d) {
return d.name;
});
if (isIE) {
childEnterTransition.selectAll(".foreignObject .labelbody .label")
.style("display", "none");
} else {
childEnterTransition.selectAll(".foreignObject")
.style("display", "none");
}
// update transition
var childUpdateTransition = childrenCells.transition().duration(transitionDuration);
childUpdateTransition.select(".cell")
.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")";
});
childUpdateTransition.select("rect")
.attr("width", function(d) {
return Math.max(0.01, d.dx);
})
.attr("height", function(d) {
return d.dy;
})
.style("fill", function(d) {
return color(d.parent.name);
});
childUpdateTransition.select(".foreignObject")
.attr("width", function(d) {
return Math.max(0.01, d.dx);
})
.attr("height", function(d) {
return Math.max(0.01, d.dy);
})
.select(".labelbody .label")
.text(function(d) {
return d.name;
});
// exit transition
childrenCells.exit()
.remove();
d3.select("select").on("change", function() {
console.log("select zoom(node)");
treemap.value(this.value == "size" ? size : count)
.nodes(root);
zoom(node);
});
zoom(node);
});
function size(d) {
return d.data.$area;
}
function count(d) {
return 1;
}
//and another one
function textHeight(d) {
var ky = chartHeight / d.dy;
yscale.domain([d.y, d.y + d.dy]);
return (ky * d.dy) / headerHeight;
}
function getRGBComponents (color) {
var r = color.substring(1, 3);
var g = color.substring(3, 5);
var b = color.substring(5, 7);
return {
R: parseInt(r, 16),
G: parseInt(g, 16),
B: parseInt(b, 16)
};
}
function idealTextColor (bgColor) {
var nThreshold = 105;
var components = getRGBComponents(bgColor);
var bgDelta = (components.R * 0.299) + (components.G * 0.587) + (components.B * 0.114);
return ((255 - bgDelta) < nThreshold) ? "#000000" : "#ffffff";
}
function zoom(d) {
this.treemap
.padding([headerHeight/(chartHeight/d.dy), 0, 0, 0])
.nodes(d);
// moving the next two lines above treemap layout messes up padding of zoom result
var kx = chartWidth / d.dx;
var ky = chartHeight / d.dy;
var level = d;
xscale.domain([d.x, d.x + d.dx]);
yscale.domain([d.y, d.y + d.dy]);
if (node != level) {
if (isIE) {
chart.selectAll(".cell.child .foreignObject .labelbody .label")
.style("display", "none");
} else {
chart.selectAll(".cell.child .foreignObject")
.style("display", "none");
}
}
var zoomTransition = chart.selectAll("g.cell").transition().duration(transitionDuration)
.attr("transform", function(d) {
return "translate(" + xscale(d.x) + "," + yscale(d.y) + ")";
})
.each("end", function(d, i) {
if (!i && (level !== self.root)) {
chart.selectAll(".cell.child")
.filter(function(d) {
return d.parent === self.node; // only get the children for selected group
})
.select(".foreignObject .labelbody .label")
.style("color", function(d) {
return idealTextColor(color(d.parent.name));
});
if (isIE) {
chart.selectAll(".cell.child")
.filter(function(d) {
return d.parent === self.node; // only get the children for selected group
})
.select(".foreignObject .labelbody .label")
.style("display", "")
} else {
chart.selectAll(".cell.child")
.filter(function(d) {
return d.parent === self.node; // only get the children for selected group
})
.select(".foreignObject")
.style("display", "")
}
}
});
zoomTransition.select(".foreignObject")
.attr("width", function(d) {
return Math.max(0.01, kx * d.dx);
})
.attr("height", function(d) {
return d.children ? headerHeight: Math.max(0.01, ky * d.dy);
})
.select(".labelbody .label")
.text(function(d) {
return d.name;
});
// update the width/height of the rects
zoomTransition.select("rect")
.attr("width", function(d) {
return Math.max(0.01, kx * d.dx);
})
.attr("height", function(d) {
return d.children ? headerHeight : Math.max(0.01, ky * d.dy);
})
.style("fill", function(d) {
return d.children ? headerColor : color(d.parent.name);
});
node = d;
if (d3.event) {
d3.event.stopPropagation();
}
}
</script>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment