shakyP
shakyP

Reputation: 21

Javascript function in DOM generated click events for SVG

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

Answers (2)

enxaneta
enxaneta

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

hardy charles
hardy charles

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

Related Questions