async () => {
// set testFn() function on globalThis, so you html onlclick can access it
globalThis.testFn = () => {
document.getElementById('demo').innerHTML = "Hello?"
};
const d3 = await import("https://cdn.jsdelivr.net/npm/d3@7/+esm");
// const d3 = await import("https://cdn.jsdelivr.net/npm/d3@5/+esm");
const $ = await import("https://cdn.jsdelivr.net/npm/jquery@3.7.1/dist/jquery.min.js");
globalThis.$ = $;
globalThis.d3 = d3;
globalThis.d3Fn = () => {
d3.select('#viz').append('svg')
.append('rect')
.attr('width', 50)
.attr('height', 50)
.attr('fill', 'black')
.on('mouseover', function(){d3.select(this).attr('fill', 'red')})
.on('mouseout', function(){d3.select(this).attr('fill', 'black')});
};
globalThis.testFn_out = (val,model_radio_c) => {
// document.getElementById('demo').innerHTML = val
console.log(val, "testFn_out");
// globalThis.d3Fn();
return([val,model_radio_c]);
};
globalThis.testFn_out_json = (data) => {
console.log(data, "testFn_out_json --");
// var $ = jQuery;
// console.log( d3.select('#d3_embeddings'));
return(['string', {}])
}
globalThis.testFn_out_json_tr = (data) => {
// data['input|output']['words|tokens']
console.log(data, "testFn_out_json_tr new");
var $ = jQuery;
console.log("$('#d3_embeddings')");
console.log($('#d3_embeddings'));
// d3.select('#d3_embeddings').html("");
d3.select("#d3_embeds_source").html("here");
// words or token visualization ?
console.log(d3.select("#select_type").node().value);
d3.select("#select_type").attr("hidden", null);
d3.select("#select_type").on("change", change);
change();
// tokens
// network plots;
['input', 'output'].forEach(text_type => {
['tokens', 'words'].forEach(text_key => {
// console.log(type, key, data[0][text_type]);
data_i = data[0][text_type][text_key];
embeddings_network([], data_i['tnse'], data_i['similar_queries'], type=text_type +"_"+text_key, )
});
});
// data_proj = data['tsne']; // it is not a dict.
// d3.select("#d3_embeds_" + type).html(scatterPlot(data_proj, data_sentences, dict_token_sentence_id, similar_vocab_queries, 'd3_embeds_'+type, type ));
// d3.select('#d3_embeddings').append(function(){return Tree(root);});
// embeddings_network(data['source_tokens'], data['dict_projected_embds_all']['source'], data['similar_vocab_queries']['source'], "source")
// source
// embeddings_graph(data['dict_projected_embds_all'],source_tks_list, data['source_tokens'], data['similar_vocab_queries'], "source"); //, data['similar_text'], data['similar_embds']);
// target decision: all tokens ? or separeted by language ? hint: do not assume they share the same dict.
// embeddings_graph(data['dict_projected_embds_all'], translated_tks_text, translated_tks_ids_by_sent, data['similar_vocab_queries'], "target"); //, data['similar_text'], data['similar_embds']);
return(['string', {}])
}
function change() {
show_type = d3.select("#select_type").node().value;
// hide all
d3.selectAll(".d3_embed").attr("hidden",'');
d3.selectAll(".d3_graph").attr("hidden", '');
// show current type;
d3.select("#d3_embeds_input_" + show_type).attr("hidden", null);
d3.select("#d3_embeds_output_" + show_type).attr("hidden", null);
d3.select("#d3_graph_input_" + show_type).attr("hidden", null);
d3.select("#d3_graph_output_" + show_type).attr("hidden", null);
}
function embeddings_network(tokens_text, dict_projected_embds, similar_vocab_queries, type="source", ){
// tokens_text : not used;
// dict_projected_embds = tnse
console.log("Each token is a node; distance if in similar list", type );
console.log(tokens_text, dict_projected_embds, similar_vocab_queries);
// similar_vocab_queries_target[key]['similar_topk']
var nodes_tokens = {}
var nodeHash = {};
var nodes = []; // [{id: , label: }]
var edges = []; // [{source: , target: weight: }]
var edges_ids = []; // [{source: , target: weight: }]
// similar_vocab_queries {key: {similar_topk : [], distance : []}}
console.log('similar_vocab_queries', similar_vocab_queries);
prev_node = '';
for ([sent_token, value] of Object.entries(similar_vocab_queries)) {
// console.log('dict_projected_embds',sent_token, parseInt(sent_token), value, dict_projected_embds);
// sent_token = parseInt(sent_token); // Object.entries assumes key:string;
token_text = dict_projected_embds[sent_token][3]
if (!nodeHash[sent_token]) {
nodeHash[sent_token] = {id: sent_token, label: token_text, type: 'sentence', type_i: 0};
nodes.push(nodeHash[sent_token]);
}
sim_tokens = value['similar_topk']
dist_tokens = value['distance']
for (let index = 0; index < sim_tokens.length; index++) {
const sim = sim_tokens[index];
const dist = dist_tokens[index];
token_text_sim = dict_projected_embds[sim][3]
if (!nodeHash[sim]) {
nodeHash[sim] = {id: sim, label: token_text_sim, type:'similar', type_i: 1};
nodes.push(nodeHash[sim]);
}
edges.push({source: nodeHash[sent_token], target: nodeHash[sim], weight: dist});
edges_ids.push({source: sent_token, target: sim, weight: dist});
}
if (prev_node != '' ) {
edges.push({source: nodeHash[prev_node], target:nodeHash[sent_token], weight: 1});
edges_ids.push({source: prev_node, target: sent_token, weight: 1});
}
prev_node = sent_token;
}
console.log("TYPE", type, edges, nodes, edges_ids, similar_vocab_queries)
// d3.select('#d3_graph_input_tokens').html(networkPlot({nodes: nodes, links:edges}, similar_vocab_queries, div_type=type) );
// type +"_"+key
d3.select('#d3_graph_'+type).html("");
d3.select('#d3_graph_'+type).append(function(){return networkPlot({nodes: nodes, links:edges}, similar_vocab_queries, dict_projected_embds,div_type=type);});
// $('#d3_embeds_network_target').html(networkPlot({nodes: nodes, links:edges}));
// $('#d3_embeds_network_'+type).html(etworkPlot({nodes: nodes, link:edges}));
}
function embeddings_graph(data, source_tokens_text_list, source_tokens, similar_vocab_queries, type="source") {
/*
### source
data: dict_projected_embds_all = { token_id: [tns1, tns2, token_id, token_text] ...}
### target
*/
console.log("embeddings_graph");
active_sentences = get_sentences();
console.log("active_sentences", active_sentences, type); // working
active_sentences_tokens_text = active_sentences.map((x) => source_tokens_text_list[x]);
active_sentences_tokens = active_sentences.map((x) => source_tokens[x]);
console.log(active_sentences_tokens);
data_sentences = []
dict_token_sentence_id = {}
// active_sentences_tokens.forEach((sentence, i) => {
source_tokens_text_list.forEach((sentence, i) => {
/// opt1
proj = []
sentence.forEach((tok, tok_j) => {
console.log("tok,tok_j", tok, tok_j);
token_text = source_tokens_text_list[i][tok_j];
proj.push([data[tok][0], data[tok][1], token_text, i, tok_j, tok])
if (token_text in dict_token_sentence_id){
dict_token_sentence_id[token_text].push(i);
}
else{
dict_token_sentence_id[token_text] = [i];
}
});
data_sentences.push(proj);
});
console.log("data_sentences error here in target", data_sentences);
console.log(data);
$('#d3_embeds_' + type).html(scatterPlot(data, data_sentences, dict_token_sentence_id, similar_vocab_queries, 'd3_embeds_'+type, type ));
}
/*
data: dict_projected_embds_all = { token_id: [tns1, tns2, token_id, token_text] ...}
*/
function scatterPlot(data, data_sentences, dict_token_sentence_id, similar_vocab_queries, div_name, div_type="source", {
width = 400, // outer width, in pixels
height , // outer height, in pixels
r = 3, // radius of nodes
padding = 1, // horizontal padding for first and last column
// text = d => d[2],
} = {}){
// data_dict = data[div_type];
var data_dict = { ...data[div_type] };
data = Object.values(data[div_type]);
// similar_vocab_queries = similar_vocab_queries[div_type];
var similar_vocab_queries = { ...similar_vocab_queries[div_type] };
console.log("div_type, data, data_dict, data_sentences, dict_token_sentence_id, similar_vocab_queries");
console.log(div_type, data, data_dict, data_sentences, dict_token_sentence_id, similar_vocab_queries);
// Create the SVG container.
var margin = {top: 10, right: 10, bottom: 30, left: 50 },
width = width - margin.left - margin.right,
height = 400 - margin.top - margin.bottom;
// append the svg object to the body of the page
var svg = d3.create("svg")
// .attr("style", "max-width: 100%; height: auto; height: intrinsic;")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
svg.append("g")
.attr("transform",
"translate(" + margin.left + "," + margin.top + ")");
// const svg = d3.create("svg")
// .attr("width", width)
// .attr("height", height);
// Add X axis
min_value_x = d3.min(data, d => d[0])
max_value_x = d3.max(data, d => d[0])
var x = d3.scaleLinear()
.domain([min_value_x, max_value_x])
.range([ margin.left , width ]);
svg.append("g")
// .attr("transform", "translate("+ margin.left +"," + height + ")")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x));
// Add Y axis
min_value_y = d3.min(data, d => d[1])
max_value_y = d3.max(data, d => d[1])
var y = d3.scaleLinear()
.domain([min_value_y, max_value_y])
.range([ height, margin.top]);
svg.append("g")
.attr("transform", "translate("+ margin.left +", 0)")
.call(d3.axisLeft(y));
svg.selectAll()
.data(data)
.enter()
.append('circle')
.attr("class", function (d) { return "dot-" + d[2] } )
// .attr("cx", function (d) { return x(d[0] + margin.left); } )
.attr("cx", function (d) { return x(d[0]); } )
.attr("cy", function (d) { return y(d[1] - margin.bottom); } )
.attr("r", 5)
.style("fill", "#e85252")
.style("fillOpacity",0.2)
.style("stroke", "#000000ff")
.style("strokeWidth", 1)
.style("opacity", 0.7);
// svg.selectAll()
// .data(data)
// .enter()
// .append('text')
// .text(d => d[3])
// .attr("class", function (d) { return "text-" + d[2] } )
// // .attr("cx", function (d) { return x(d[0] + margin.left); } )
// .attr("x", function (d) { return x(d[0]); } )
// .attr("y", function (d) { return y(d[1] - margin.bottom); } )
// .attr("dy", "0.35em");
// colors = ['#cb1dd1',"#e0ac2b", "#e85252", "#6689c6", "#9a6fb0", "#a53253"];
colors = ['#6689c6',"#e0ac2b", "#e0ac2b", "#cb1dd1", "#cb1dd1", "#cb1dd1"];
// create a tooltip
var Tooltip = d3.select("#"+div_name)
.append("div")
.style("opacity", 0)
.attr("class", "tooltip")
.style("background-color", "white")
.style("border", "solid")
.style("border-width", "2px")
.style("border-radius", "5px")
.style("padding", "5px")
.text("I'm a circle!");
// const colorScale = d3.scaleOrdinal()
// .domain(domain_values)
// .range(["#e0ac2b", "#e85252", "#6689c6", "#9a6fb0", "#a53253"]);
// colorScale(d.group)
for (let i_snt = 0; i_snt < data_sentences.length; i_snt++) {
const sentence = data_sentences[i_snt];
// similar_tokens;
console.log("sentence: ", sentence);
svg.selectAll()
.data(sentence)
.enter()
.append('text')
.text(d => d[2])
.attr("class", function (d) { return "text-" + d[2] + " sent-" + i_snt } )
// .attr("cx", function (d) { return x(d[0] + margin.left); } )
.attr("x", function (d) { return x(d[0]); } )
.attr("y", function (d) { return y(d[1] - margin.bottom); } )
.attr("dy", "0.35em")
.attr("sentence_i", i_snt );
svg.selectAll()
.data(sentence)
.enter()
.append('circle')
.attr("class", function (d) { return "dot " + d[2] + " " + i_snt } )
// .attr("cx", function (d) { return x(d[0] + margin.left); } )
.attr("cx", function (d) { return x(d[0]); } )
.attr("cy", function (d) { return y(d[1] - margin.bottom); } )
.attr("sentence_i", i_snt )
.attr("r", 6)
.style("fill", colors[0])
.style("fillOpacity",0.2)
.style("stroke", "#000000")
.style("strokeWidth", 1)
.style("opacity", 1)
.on('click', change_legend )
.on('mouseover', highlight_mouseover )
.on('mouseout', highlight_mouseout )
// .on("mousemove", mousemove);
}
function change_legend(d,i) {
console.log(d,i);
if (i[2] in dict_token_sentence_id){
show_sentences(dict_token_sentence_id[i[2]], i[2]);
show_similar_tokens(i[5], '#d3_legend_similar_'+type);
console.log(dict_token_sentence_id[i[2]]);
}
else{console.log("no sentence")};
}
function highlight_mouseover(d,i) {
console.log("highlight_mouseover", d,i);
// token_id = parseInt(i[5])
similar_ids = similar_vocab_queries[token_id]['similar_topk'];
d3.select(this).transition()
.duration('50')
.style('opacity', '1')
.attr("r", 12)
similar_ids.forEach(similar_token => {
d3.selectAll('.dot-' + similar_token).attr("r",12 ).style('opacity', '1')//.raise()
});
Tooltip
.style("opacity", 1)
.style("visibility", "visible")
// .style("top", (event.pageY-height)+"px").style("left",(event.pageX-width)+"px")
d3.select(this)
.style("stroke", "red")
.attr("strokeWidth", 2)
.style("opacity", 0.7)
// .html("The exact value of
this cell is: ")
// .style("left", (d3.mouse(this)[0]+70) + "px")
// .style("top", (d3.mouse(this)[1]) + "px")
}
function highlight_mouseout(d,i) {
// token_id = parseInt(i[5])
console.log("similar_vocab_queries", similar_vocab_queries);
similar_ids = similar_vocab_queries[token_id]['similar_topk'];
// clean_sentences();
d3.select(this).transition()
.duration('50')
.style('opacity', '.7')
.attr("r", 6)
similar_ids.forEach(similar_token => {
d3.selectAll('.dot-' + similar_token).attr("r",6 ).style('opacity', '.7')
});
Tooltip
.style("opacity", 0)
d3.select(this)
.style("stroke", "none")
.style("opacity", 0.8)
}
function mousemove(d,i) {
console.log("mousemove", d, i)
pointer = d3.pointer(d);
Tooltip
.html("The exact value of
")
// .style("top", ((e.pageY ) - (height*2)) +"px")
// .attr("transform", `translate(${pointer[0]},0)`)
.style("top", height - pointer[1] +"px")
.style("left", pointer[0]+"px")
}
function show_sentences(sentences_id, token) {
// Show sentences with token "token"
d3.select('#d3_legend_data_'+div_type).html("");
console.log("show_sentences", data_sentences, sentences_id);
sentences_id.forEach(sent_id => {
console.log(data_sentences[sent_id])
// console.log(data_sentences[sent_id].map( x => x[2] ));
// p = d3.select('#d3_legend_data').append("p").enter();
d3.select('#d3_legend_data_'+div_type)
.selectAll().append("p")
.data(data_sentences[sent_id])
.enter()
.append('text')
.attr('class_data', sent_id)
.attr('class_id', d => d[5])
.style("background", d=> {if (d[2]== token) return "yellow"} )
.text( d => d[2] + " ");
d3.select('#d3_legend_data_'+div_type).append("p").enter();
});
// $("#d3_legend_data")
// data_sentences
}
function clean_sentences() {
d3.select('#d3_legend_data_'+div_type).html("");
}
function show_similar_tokens(token, div_name_similar= '#d3_legend_similar_') {
d3.select(div_name_similar).html("");
console.log("token", token);
console.log("similar_vocab_queries[token]", similar_vocab_queries[token]);
token_data = similar_vocab_queries[token];
console.log(token, token_data);
var decForm = d3.format(".3f");
d3.select(div_name_similar)
.selectAll().append("p")
.data(token_data['similar_topk'])
.enter()
.append("p").append('text')
// .attr('class_data', sent_id)
.attr('class_id', d => d)
.style("background", d=> {if (d == token) return "yellow"} )
// .text( d => d + " \n ");
.text((d,i) => do_text(d,i) );
function do_text(d,i){
console.log("do_text d,i" );
console.log(d,i);
console.log("data_dict[d], data_dict");
// console.log(data_dict[d], data_dict);
// return data_dict[d][3] + " " + decForm(token_data['distance'][i]) + " ";
return " " + decForm(token_data['distance'][i]) + " ";
}
}
// data_sentences
// .attr('x', (d) => x_scale(d[0]) + margin.left)
// .attr('y', (d) => y_scale(d[1]) + margin_top_extra)
// .attr("rx", 4)
// .attr("ry", 4)
// .attr("stroke", "#F7F7F7")
// .attr("stroke-width","2px")
// .attr('width', x_scale.bandwidth())
// .attr('height', (d) => height_text);
// // .attr('fill', (d) => color_scale(d.value));
// Add dots
// svg.append('g')
// // .selectAll("dot")
// .data(data)
// .enter()
// .append("circle")
// .attr("class", function (d) { return "dot " + d[2] } )
// .attr("cx", function (d) { return x(d[0]); } )
// .attr("cy", function (d) { return y(d[1]); } )
// .attr("r", 5)
// .style("fill", function (d) { return color(d.Species) } )
// .on("mouseover", highlight)
// .on("mouseleave", doNotHighlight )
return svg.node();
}
function networkPlot(data, similar_vocab_queries,dict_proj, div_type="source", {
width = 400, // outer width, in pixels
height , // outer height, in pixels
r = 3, // radius of nodes
padding = 1, // horizontal padding for first and last column
// text = d => d[2],
} = {}){
// data_dict = data;
data = data// [div_type];
similar_vocab_queries = similar_vocab_queries// [div_type];
console.log("data, similar_vocab_queries, div_type");
console.log(data, similar_vocab_queries, div_type);
// Create the SVG container.
var margin = {top: 10, right: 10, bottom: 30, left: 50 },
width = width //- margin.left - margin.right,
height = 400 //- margin.top - margin.bottom;
width_box = width + margin.left + margin.right;
height_box = height + margin.top + margin.bottom
totalWidth = width*2;
// append the svg object to the body of the page
// const parent = d3.create("div");
// const body = parent.append("div")
// .style("overflow-x", "scroll")
// .style("-webkit-overflow-scrolling", "touch");
var svg = d3.create("svg")
// var svg = body.create("svg")
// .style("display", "block")
// .attr("style", "max-width: 100%; height: auto; height: intrinsic;")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
// .attr("viewBox", [-width_box / 2, -height_box / 2, width_box, height_box])
// .attr("viewBox", [0, 0, width, height]);
// .attr("style", "max-width: 100%; height: auto;");
// svg.append("g")
// .attr("transform",
// "translate(" + margin.left + "," + margin.top + ")");
// Initialize the links
var link = svg
.selectAll("line")
.data(data.links)
.enter()
.append("line")
.style("fill", d => d.weight == 1 ? "#dfd5d5" : "#000000") // , "#69b3a2" : "#69b3a2")
.style("stroke", "#aaa")
var text = svg
.selectAll("text")
.data(data.nodes)
.enter()
.append("text")
.style("text-anchor", "middle")
.attr("y", 15)
.attr("class", d => 'text_token-'+ dict_proj[d.id][4] + div_type)
.attr("div-type", div_type)
// .attr("class", d => 'text_token-'+ d.index)
.text(function (d) {return d.label} )
// .on('mouseover', function(d) { (d.type_i == 0) ? highlight_mouseover_text : console.log(0)} )
// .on('mouseover', function(d) { (d.type_i == 0) ? highlight_mouseout_text : '' } )
// .on('mouseout', highlight_mouseout_text )
// .join('text')
// .text(function(d) {
// return d.id
// })
// Initialize the nodes
var node = svg
.selectAll("circle")
.data(data.nodes)
.enter()
.append("circle")
.attr("r", 6)
// .attr("class", d => 'node_token-'+ d.id)
.attr("class", d => 'node_token-'+ dict_proj[d.id][4] + div_type)
.attr("div-type", div_type)
.style("fill", d => d.type_i ? "#e85252" : "#6689c6") // , "#69b3a2" : "#69b3a2")
.on('mouseover', highlight_mouseover )
// .on('mouseover', function(d) { return (d.type_i == 0) ? highlight_mouseover : console.log(0)} )
.on('mouseout',highlight_mouseout )
.on('click', change_legend )
// .on('click', show_similar_tokens )
// Let's list the force we wanna apply on the network
var simulation = d3.forceSimulation(data.nodes) // Force algorithm is applied to data.nodes
.force("link", d3.forceLink() // This force provides links between nodes
.id(function(d) { return d.id; }) // This provide the id of a node
.links(data.links) // and this the list of links
)
.force("charge", d3.forceManyBody(-400)) // This adds repulsion between nodes. Play with the -400 for the repulsion strength
.force("center", d3.forceCenter(width / 2, height / 2)) // This force attracts nodes to the center of the svg area
// .force("collision", d3.forceCollide())
.on("end", ticked);
// This function is run at each iteration of the force algorithm, updating the nodes position.
function ticked() {
link
.attr("x1", function(d) { return d.source.x; })
.attr("y1", function(d) { return d.source.y; })
.attr("x2", function(d) { return d.target.x; })
.attr("y2", function(d) { return d.target.y; });
node
.attr("cx", function (d) { return d.x+3; })
.attr("cy", function(d) { return d.y-3; });
text
.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; })
}
function highlight_mouseover(d,i) {
console.log("highlight_mouseover", d,i, d3.select(this).attr("div-type"));
if (i.type_i == 0 ){
token_id = i.id
similar_ids = similar_vocab_queries[token_id]['similar_topk'];
d3.select(this).transition()
.duration('50')
.style('opacity', '1')
.attr("r", 12)
type = d3.select(this).attr("div-type")
similar_ids.forEach(similar_token => {
node_id_name = dict_proj[similar_token][4]
d3.selectAll('.node_token-'+ node_id_name + type).attr("r",12 ).style('opacity', '1')//.raise()
// d3.selectAll('.text_token-'+ node_id_name).raise()
});
}
}
function highlight_mouseout(d,i) {
if (i.type_i == 0 ){
token_id = i.id
console.log("similar_vocab_queries", similar_vocab_queries, "this type:", d3.select(this).attr("div-type"));
similar_ids = similar_vocab_queries[token_id]['similar_topk'];
// clean_sentences();
d3.select(this).transition()
.duration('50')
.style('opacity', '.7')
.attr("r", 6)
type = d3.select(this).attr("div-type")
similar_ids.forEach(similar_token => {
node_id_name = dict_proj[similar_token][4]
d3.selectAll('.node_token-' + node_id_name + type).attr("r",6 ).style('opacity', '.7')
d3.selectAll("circle").raise()
});
}
}
function change_legend(d,i,j) {
console.log(d,i,dict_proj);
if (i['id'] in dict_proj){
// show_sentences(dict_proj[i[2]], i[2]);
show_similar_tokens(i['id'], '#similar_'+type);
console.log(dict_proj[i['id']]);
}
else{console.log("no sentence")};
}
function show_similar_tokens(token, div_name_similar='#similar_input_tokens') {
d3.select(div_name_similar).html("");
console.log("token", token);
console.log("similar_vocab_queries[token]", similar_vocab_queries[token]);
token_data = similar_vocab_queries[token];
console.log(token, token_data);
var decForm = d3.format(".3f");
d3.select(div_name_similar)
.selectAll().append("p")
.data(token_data['similar_topk'])
.enter()
.append("p").append('text')
// .attr('class_data', sent_id)
.attr('class_id', d => d)
.style("background", d=> {if (d == token) return "yellow"} )
// .text( d => d + " \n ");
.text((d,i) => do_text(d,i) );
function do_text(d,i){
console.log("do_text d,i" );
console.log(d,i);
console.log("data_dict[d], data_dict");
console.log(dict_proj[d], dict_proj);
return dict_proj[d][3] + " " + decForm(token_data['distance'][i]) + " ";
}
}
// svg.call(d3.zoom()
// .extent([[0, 0], [width, height]])
// .scaleExtent([1, 8])
// .on("zoom", zoomed));
// function zoomed({transform}) {
// circle.attr("transform", d => `translate(${transform.apply(d)})`);
// }
// svg.call(
// d3.zoom().on("zoom", (event) => {
// g.attr("transform", event.transform);
// })
// );
// body.node().scrollBy(totalWidth, 0);
return svg.node();
// return parent.node();
};
}