Reputation: 21
I am working on a chromosome visualization program. This program allows users to select chromosomes and view their evolution.
At the moment I am attempting to add an onclick event to an SVG rect element and failing. The code below is one example of many I have tried. I absolutely need this to be in vector format, and this is only an intermediate step.
This stage of the program takes two input arrays: one with a list of names of chromosomes and a second with a list of sizes. This section of code is designed to display the chromosomes, and allow the user to select those they are interested in. It will then display data about the chromosomes in a second div (text only with href) and generate a button. Upon clicking this button, they will be in for an interactive treat of chromosome evolution through a newly generated SVG.
I am having great success in drawing the chromosomes, but I have been unable to link my objects to the necessary javascript code. I am relatively new to Javascript so any help is appreciated.
Here is my test code:
<body>
<button onclick="Draw_Chromosomes()">
Start this baby up
</button>
<!-- This is where the refrence chromosomes are displayed -->
<div id="RefChromosomes_box" width=100%>
<svg id="RefChromosomes" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" height="300"></svg>
</div>
<!-- This is where the output is displayed -->
<div id="SELECTED_CHROMOSOMES" width=100%>
</div>
<script type="text/javascript">
var svgNS = "http://www.w3.org/2000/svg";
var Chromosomes = ["1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20","21","22","X","Y"];
var Positions = [248956422,242193529,198295559,190214555,181538259,170805979,159345973,145138636,138394717,133797422,135086622,133275309,114364328,107043718,101991189,90338345,83257441,80373285,58617616,64444167,46709983,50818468,156040895,57227415];
var Length = Positions.length;
var Largest= Math.max.apply(Math, Positions);
function Draw_Chromosomes(){
while (document.getElementById("RefChromosomes").lastChild) {
document.getElementById("RefChromosomes").removeChild(document.getElementById("RefChromosomes").lastChild);
}
//Make SVG element the proper size
var newidth=50+100*Length;
document.getElementById("RefChromosomes").style.width = newidth;
//Set the parameters for the first chromosome
var tempx=75;
//Draw the Chromosomes
for (var i = 0; i < Length; i++) {
var myChrome = document.createElementNS(svgNS,"rect");
var ID=Chromosomes[i] + "CHR";
myChrome.setAttributeNS(null,"id",ID);
myChrome.setAttributeNS(null,"x",tempx);
//set up X position for the next one
var tempx=tempx+100;
//Calculate the Y Top position (0 for maximum length, 250 for minimum)
// First get the length and divide it by max *250.
var CHRLENGTH=Positions[i]/Largest*250;
// set it for length
var endpos=250-CHRLENGTH;
myChrome.setAttributeNS(null,"y",endpos);
myChrome.setAttributeNS(null,"height",CHRLENGTH);
// set curviture
myChrome.setAttributeNS(null,"rx",15);
myChrome.setAttributeNS(null,"ry",15);
// set width (standard)
myChrome.setAttributeNS(null,"width",50);
// Set height
myChrome.setAttributeNS(null,"fill","blue");
myChrome.setAttributeNS(null,"stroke","black");
myChrome.setAttributeNS(null,"stroke-width",2);
// myChrome.setAttributeNS(null,"onclick","alert("bla")");
document.getElementById("RefChromosomes").appendChild(myChrome);
//document.getElementById(Chromosomes[i] + "CHR").dispatchEvent(new Event('click'));
// Add text Labels
var chrtext = document.createElementNS(svgNS,"text");
chrtext.setAttributeNS(null,"x",tempx-125);
chrtext.setAttributeNS(null,"y",280);
chrtext.setAttributeNS(null,"font-size","12px");
chrtext.setAttributeNS(null,"class","textlabel");
chrtext.innerHTML = "CHROMSOME " + Chromosomes[i];
document.getElementById("RefChromosomes").appendChild(chrtext);
}
}
}
</script>
</body>
Upvotes: 2
Views: 48
Reputation: 33024
I've changed your code. Now every chromosome is an object that I saved in an array: var chroArray = [];
This way you can attach every rectangle an event. In this case on click returns the text content of the object.
var svgNS = "http://www.w3.org/2000/svg";
var Chromosomes = ["1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20","21","22","X","Y"];
var Positions = [248956422,242193529,198295559,190214555,181538259,170805979,159345973,145138636,138394717,133797422,135086622,133275309,114364328,107043718,101991189,90338345,83257441,80373285,58617616,64444167,46709983,50818468,156040895,57227415];
var Length = Positions.length;
var Largest= Math.max.apply(Math, Positions);
var chroArray = [];
//Make SVG element the proper size
var start = 75;
var newidth=(50+100)*Length + start;
/* in this case I am setting the size of the svg using the viewBox attribute. You may change it back to width and height */ document.getElementById("RefChromosomes").setAttributeNS(null, "viewBox", `0 0 ${newidth} 300`);
class Chromosome{
constructor(o){
// the properties of the rectangle
this.props = {}
this.props.width = o.w;
this.props.height = o.h;
this.props.x = o.x;
this.props.y = 250 - o.h;
this.props.rx = 15;
this.props.ry = 15;
//the index
this.i = o.i;
// the properties of the text
this.textprops={}
this.textprops.x = this.props.x + this.props.width / 2;
this.textprops.y = 275;
// the text content
this.textContent = "CHROMSOME " + Chromosomes[this.i];
}
create(){
// a function that creates a rect element
this.chrome = document.createElementNS(svgNS,"rect");
for (var name in this.props) {
if (this.props.hasOwnProperty(name)) {
this.chrome.setAttributeNS(null, name, this.props[name]);
}
}
// save the rect in the group of rects
gchart.appendChild(this.chrome);
}
addText(){
// a function that creates a text element
this.text = document.createElementNS(svgNS,"text");
for (var name in this.textprops) {
if (this.textprops.hasOwnProperty(name)) {
this.text.setAttributeNS(null, name, this.textprops[name]);
}
this.text.textContent = this.textContent;
}
gtext.appendChild(this.text);
}
}
for (var i = 0; i < Length; i++) {
var o = {}
o.x = start + (150 * i);
o.h = Positions[i]/Largest*250;
o.w = 50;
o.i = i;
// save the chromosome in the chroArray
chroArray.push(new Chromosome(o))
}
function Draw_Chromosomes(){
chroArray.forEach(c =>{
c.create();
c.addText();
// attaching an event to every rectangle
c.chrome.addEventListener("click",()=>{
console.log(c.textContent)
})
})
}
rect{fill:blue;stroke:black;stroke-width:2}
text{font-size:12px;text-anchor:middle;}
svg{border:1px solid}
<button onclick="Draw_Chromosomes()">
Start this baby up
</button>
<!-- This is where the refrence chromosomes are displayed -->
<div id="RefChromosomes_box" width=100%>
<svg id="RefChromosomes" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" >
<g id="gchart"></g>
<g id="gtext"></g>
</svg>
</div>
<!-- This is where the output is displayed -->
<div id="SELECTED_CHROMOSOMES" width=100%>
</div>
Upvotes: 1
Reputation: 23
svg is just xml structure so you can just add an id to your different xml elements that compose your svg and select them independently like html.
Upvotes: 0