Search code examples
javascriptarrayssvgsubroutine

Javascript any click a value for multiple instances


I have an SVG composite image of a skeleton and what I want is that, anytime you click on a bone it changes color and a textfield gets a specific value: basically on the first click the filling of the bone becomes black and the text field gets "black", the second click "red", etc. for 206 bones!

I made a script and it works great for the first bone, but it seems that if I start clicking on a second bone, the script continue the routine from the previous instance.

Here's the code (only humerus and femurs work):

<!doctype html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<head>
<meta charset="utf-8">
<title>Documento senza titolo</title>
</head>

<body>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 1761">
    <defs>
      <style>
        svg {
          background-image: url(https://www.archeodb.it/scheletrino/skel.jpg);
          background-size: 100% 100%;
          background-repeat: no-repeat;
          max-width: 900px;
          width: 90%;
        }
        path {
          fill: transparent;
          cursor: pointer;
          transition: fill 0.2s
        }
      </style>
    </defs>
    <g>
      <path href="#" alt="Femore destro" id="Femore_sx" d="M1032 997c-1-1-11-6-12-8a12 12 0 0 1-3-7c0-3 2-4 3-6s2-4 6-5 1-2 6-1 4 1 7 3l6 5 8 4c3 1 1-1 6-1l11 1c0 1 2 1 3 5s3 5 3 10 2 6-2 9-5 4-7 9-3 5-3 9l-4 24-23 139 1 36 7 26c0 1-1 5-3 6s1 2-3 3-3 1-6 0l-3-1-7-3-5-1c-2 0-6 2-10 1s-5 1-6-3-2-2-2-7-2-3 1-9l5-9c2-1 4-5 5-8a74 74 0 0 0 4-13l2-12 21-126c1-3 3-28 2-31l-6-9a12 12 0 0 1 0-5v-10-9a52 52 0 0 0-2-6z"/>
    </g>
    <g>
      <path href="#" alt="Femore sinistro" id="Femore_dx" d="M764 987s9-2 10-4v-7-5l-10-6s-4-2-6 0l-3 2-6 5c-3 2 1 1-3 2s-4 4-6 3l-5-1-4-2c-2-1-1-1-6 1-5 3-2-2-6 5s-3 2-4 7-3 11-2 13l6 10 4 14a3006 3006 0 0 1 28 132v30c1 5-1 2 2 11s3 10 3 16-2 8-2 10l-1 2-1 4c-2 4-2 2-2 9s-1 8 1 10-4 0 3 1l8 2h4l11-4h11c5-7 5-7 5-11s2-4 0-7 0-3-3-5-5-8-6-9-10-19-11-23l-1-27-11-45-8-46-4-33a43 43 0 0 1 2-10c4-9 1-8 4-14 1-2-1-15 2-17a7 7 0 0 0 2-5 8 8 0 0 1 2-3z"/>
    </g>
    <g>
      <path href="#" alt="Omero sinistro" id="Omero_dx" d="M703 605l3-7c0-2-3-10-5-11l-6-3a14 14 0 0 0-7 1c-2 1-5 0-8 2l-4 4-3 5s-1 10 0 12 0 7 3 11 3 22 3 30l4 40c1 6 1 17-1 25s-3 32-4 37-3 17-6 20l-6 7c-1 2-3 3-3 7s-2 6-1 8 3 4 5 4l10 5 9 2c2 0 0 3 3 0s6-5 9-6 9-1 8-3l-3-5c-2-3-10-21-10-24l-1-23 3-34 1-51-1-24v-13l3-10z"/>
    </g>
    <g>
      <path href="#" alt="Omero destro" id="Omero_sx" d="M1100 613v-10c0-3 1-3 3-4l4-2 5-2a18 18 0 0 0 4 0h4l8 2c1 0 3-1 3 3s2 1 0 7l-1 5-2 4c-3 5-6 6-6 8v5l1 17c0 5-2 47-4 53s-3 10-3 15v15l2 18 7 25 10 23c1 2 3 3 0 4l-7 2-11 3-6 3c-2 2-2 3-5 2s-3 0-6-2l-8-6v-4c-1-2 4-6 5-10l3-14 1-13-1-14 1-23 4-55v-20-19l-2-8-3-8z"/>
    </g>
</svg>


<p>OMERO DESTRO: <input type="text" id="Omero_dx_txt" value="1"></p>
<p>OMERO SINISTRO: <input type="text" id="Omero_sx_txt" value="1"></p>
<p>FEMORE DESTRO: <input type="text" id="Femore_dx_txt" value="1"></p>
<p>FEMORE SINISTRO: <input type="text" id="Femore_sx_txt" value="1"></p>

<script>

//QUESTE SONO LE FUNZIONI JS CHE HO CREATO E CHE PERMETTONO DI EVIDENZIARE CON COLORI DIVERSI AD OGNI CLIC L'OSSO SELEZIONATO E CONTESTUALMENTE POPOLA I CAMPI DI TESTO CORRELATI. IL PROBLEMA E' CHE SE CLICCO SU UN OSSO DOPO AVER CLICCATO SU UN ALTRO, MI VA AVANTI LA FUNZIONE PRECEDENTEMENTE ATTIVATA!

//Femore destro
var count = 0
$("#Femore_sx").click(function() {
    count++;
    if(count == 1) {
    $('#Femore_sx').on("click", function() { $('#Femore_sx').css({ fill: "#ff0000" });});
        $('#Femore_sx_txt').val('TRASPARENTE');
    }else if(count == 2){
    $('#Femore_sx').on("click", function() { $('#Femore_sx').css({ fill: "#ffffff" });});
        $('#Femore_sx_txt').val('ROSSO');
    }else if(count == 3){
    $('#Femore_sx').on("click", function() { $('#Femore_sx').css({ fill: "#000000" });});
        $('#Femore_sx_txt').val('BIANCO');
    }else if(count == 4){
    $('#Femore_sx').on("click", function() { $('#Femore_sx').css({ fill: "" });});
        $('#Femore_sx_txt').val('NERO');
        count = 0;
    }    
})

//Femore sinistro
var count = 0
$("#Femore_dx").click(function() {
    count++;
    if(count == 1) {
    $('#Femore_dx').on("click", function() { $('#Femore_dx').css({ fill: "#ff0000" });});
        $('#Femore_dx_txt').val('TRASPARENTE');
    }else if(count == 2){
    $('#Femore_dx').on("click", function() { $('#Femore_dx').css({ fill: "#ffffff" });});
        $('#Femore_dx_txt').val('ROSSO');
    }else if(count == 3){
    $('#Femore_dx').on("click", function() { $('#Femore_dx').css({ fill: "#000000" });});
        $('#Femore_dx_txt').val('BIANCO');
    }else if(count == 4){
    $('#Femore_dx').on("click", function() { $('#Femore_dx').css({ fill: "" });});
        $('#Femore_dx_txt').val('NERO');
        count = 0;
    }    
})

//Omero destro
var count = 0
$("#Omero_sx").click(function() {
    count++;
    if(count == 1) {
    $('#Omero_sx').on("click", function() { $('#Omero_sx').css({ fill: "#ff0000" });});
        $('#Omero_sx_txt').val('TRASPARENTE');
    }else if(count == 2){
    $('#Omero_sx').on("click", function() { $('#Omero_sx').css({ fill: "#ffffff" });});
        $('#Omero_sx_txt').val('ROSSO');
    }else if(count == 3){
    $('#Omero_sx').on("click", function() { $('#Omero_sx').css({ fill: "#000000" });});
        $('#Omero_sx_txt').val('BIANCO');
    }else if(count == 4){
    $('#Omero_sx').on("click", function() { $('#Omero_sx').css({ fill: "" });});
        $('#Omero_sx_txt').val('NERO');
        count = 0;
    }    
})

//Omero sinistro
var count = 0
$("#Omero_dx").click(function() {
    count++;
    if(count == 1) {
    $('#Omero_dx').on("click", function() { $('#Omero_dx').css({ fill: "#ff0000" });});
        $('#Omero_dx_txt').val('TRASPARENTE');
    }else if(count == 2){
    $('#Omero_dx').on("click", function() { $('#Omero_dx').css({ fill: "#ffffff" });});
        $('#Omero_dx_txt').val('ROSSO');
    }else if(count == 3){
    $('#Omero_dx').on("click", function() { $('#Omero_dx').css({ fill: "#000000" });});
        $('#Omero_dx_txt').val('BIANCO');
    }else if(count == 4){
    $('#Omero_dx').on("click", function() { $('#Omero_dx').css({ fill: "" });});
        $('#Omero_dx_txt').val('NERO');
        count = 0;
    }    
})

</script>
  </body>
</html>

Solution

  • You need a more generalized solution that will do the same thing for all the bones. To do this, select by tag, not ID. Using the same "count" variable for all segments was part of your issue. You need one for the state of each element...so my solution just stashed the counter state into each element itself.

    Inside the click function $(this) refers to the current element, so you don't need to deal with all the IDs. The solution below will work for the whole diagram in one go.

    var fills = [];
    fills[1] = "#f00";
    fills[2] = "#000";
    fills[3] = "#fff";
    fills[4] = "";
    var labels = [];
    labels[1] = "TRASPARENTE";
    labels[2] = "ROSSO";
    labels[3] = "BIANCO";
    labels[4] = "NERO";
    $("path").click(function() {
        var count = $(this).data("state") || 0; // get the counter, if none, use zero
        count++;
        $(this).css({ fill: fills[count] })
        // set labels
        var myText = $(this).attr("id")+"_txt"; // get the id of the associated text field
        $("#"+myText).val(labels[count]);
    
        if(count == 4) {
          count = 0;
        }
    
        $(this).data("state", count); // assign the counter back to the element
    })