score:1

Accepted answer

"it becomes a huge mess". Yes it will. Let's look at part of your code. Remember that when you use append you return a selection of the appended elements:

div                  // a selection of entered div elements
   .append("form")    // append forms to the divs, return a selection of forms      
   .merge(update_5)  // merge a selection of forms with a the update selection of divs

   ...               // style the selection of divs and forms

   .append("input")  // append inputs to the selection of divs and forms
   .merge(update_5)  // merge the update selection of divs with the inputs

   ...               // style the inputs and the divs

The above is clearly going to cause elements to be appended all over the place where you don't want.

First, we're merging different types of elemenrts, and because of this, second, we're appending inputs to divs and forms when we probably don't want to. Essentially we're appending things to all sorts of things that shouldn't have things appended to them. The divs that remain each iteration get more and more contaminated with excess elements, and no where do you remove those elements (you shouldn't look to remove those excess elements, you should look to not add them in the first place).

Rather than fix the code you have as is, I'm going to suggest an approach suggested by Altocumulus in the comments: "Instead of binding data by index, which is the default, try using a key function to properly match data records": If the data for a single entry doesn't change, there is no need to update it once it is appended. Instead we only need to remove div elements for which the data has been removed, this means we only need to append and modify elements on enter:

   let update_5 = select_5.selectAll(".matches")
      .data(data,d=>d.label);
    
    update_5.exit().remove();

    // Enter new divs:
    const enter = update_5.enter()
        .append("div")
        .attr("class","matches")
    
    ...

    // Append the children to entered divs:
    enter.append("form")
       .attr("action",d => d.market)
       .attr("target","_blank")
       .style("width","100%")
       .append("input")
       .attr("type","submit")
       .attr("target","_blank")
       .style("width","100%")
       .attr("value","Jogo Betfair");

    ...

There's no need to merge here as we aren't modifying existing elements if the data for those elements still exists in the data array (regardless of index).

Here's an example with everything except the iframe (as you haven't included example data with valid paths):

    let csv1 = d3.csvParse(d3.select("#csv1").remove().text());
    let csv2 = d3.csvParse(d3.select("#csv2").remove().text());
    
    let csv = [csv1, csv2];
    let i = 0;

    
    var select_5 = d3.select("#Lista-de-Jogos-Lateral")
      .append("div")
      .attr("id","select-box-5")
      .style("width","100%")
      .style("max-height","574px");

    function update() {

        let data = csv[i++%2];
            
        let update_5 = select_5.selectAll(".matches")
            .data(data,d=>d.label);
        
        update_5.exit().remove();

        // Enter new divs:
        const enter = update_5.enter()
            .append("div")
            .attr("class","matches")
        
        // Append the children to entered divs:
        enter.append("form")
           .attr("action",d => d.market)
           .attr("target","_blank")
           .style("width","100%")
           .append("input")
           .attr("type","submit")
           .attr("target","_blank")
           .style("width","100%")
           .attr("value","Jogo Betfair");
           
        enter.append("form")
            .append("input")
            .attr("type","text")
            .attr("id",d => "barra-de-texto-para-grafico-" + d.numbergame)
            .style("width","100%")
            .attr("value", d=>d.label);
            
        enter.append("img")
            .attr("type","text")
            .attr("src","https://sitedeapostas-com.imgix.net/assets/local/Company/logos/betfair_logo_transp.png?auto=compress%2Cformat&fit=clip&q=75&w=263&s=c1691b4034fd0c4526d27ffe8b1e839c")
            .attr("name",d => "grafico-betfair-" + d.numbergame);
    }
  
  
  update();
    setInterval(update,2000);
    {
    box-sizing: border-box;
    }
    .matches {
    text-align:center;
    float: left;
    width: 355px;
    border: 1px solid white;
    border-collapse: collapse;
    }
    .column {
    text-align:center;
    float: left;
    width: 355px;
    border: 1px solid white;
    border-collapse: collapse;
    }
    .grid {
    float: left;
    width: 1431px;
    }
    .row:after {
    content: "";
    display: table;
    clear: both;
    }
    .button {
    background-color: #33ccff;
    color: black;
    font-weight: bold;
    }
    input[type=submit] {
    background-color: #33ccff;
    color: black;
    font-weight: bold;
    }
    html {
    overflow: scroll;
    overflow-x: hidden;
    }
    ::-webkit-scrollbar {
    width: 0px; /* remove scrollbar space /
    background: transparent; / optional: just make scrollbar invisible /
    }
    / optional: show position indicator in red */
    ::-webkit-scrollbar-thumb {
    background: #FF0000;
    }
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.1.1/d3.min.js"></script>
    <div style="color:white;font-weight:bold;overflow:hidden;overflow-y:scroll;" class="grid games" id="Lista-de-Jogos-Lateral">
    
    <pre id="csv1">label,value,market,numbergame
A,www.siteA.com,www.webA.com,1
B,www.siteB.com,www.webB.com,2
C,www.siteC.com,www.webC.com,3
D,www.siteD.com,www.webD.com,4</pre>
    <pre id="csv2">label,value,market,numbergame
A,www.siteA.com,www.webA.com,1
G,www.siteG.com,www.webG.com,2
C,www.siteC.com,www.webC.com,3
Z,www.siteZ.com,www.webZ.com,4
Y,www.siteY.com,www.webY.com,5</pre>
    

    
    </div>
    

The above uses d3.csvParse() instead of d3.csv() to create csv data - which allows the snippet to be entirely self-contained, this requires the use of the pre elements to hold the csv data.


Related Query