Home > Software engineering >  How to update data on a page according to data from a CSV file instead of using fixed element data o
How to update data on a page according to data from a CSV file instead of using fixed element data o

Time:10-09

After the Snippet there is a complete code of my attempt in Visual Studio Code.

This model that I'll leave below uses two <pre> elements with data so that the page refreshes the page data every 2 seconds, but I would like that instead of using elements with values, I would like to refresh the page every 2 seconds with the existing data in a file called List_of_Games.csv

The data in this file updates every 1 minute and they have the same label,value,market,numbergame model as the <pre> elements.

How could I do this? I was not able to draw a model for this to be possible.


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,format&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>

I tried using it this way in Visual Studio Code but I didn't get positive feedback:

<html>
    <head>
        <style>
            {
            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;
            }
        </style>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.1.1/d3.min.js"></script>
        <script src="https://d3js.org/d3.v4.js"></script>
        <script id="auto-update-images">
            let interval_images
            window.addEventListener('DOMContentLoaded', () => {
                interval_images = setInterval(refresh_images, 1000); // refresh every 1 sec
            })
            
            function refresh_images() {
                if (!document.images) return;
                const totalimages = document.querySelectorAll("img").length - 1;
                const lastimages = parseInt(document.getElementsByTagName('img')[totalimages].getAttribute('name').replace("grafico-betfair-", ""))   1;
                for (let i = 1; i < lastimages; i  ) {
                    try {
                        document.images['grafico-betfair-'   i].src = document.getElementById('barra-de-texto-para-grafico-'   i).value;
                    } catch (e) {
                    }
                }
            }
        </script>
        <script id="random-number">
            function generateRandomIntegerInRange(min, max) {
                return Math.floor(Math.random() * (max - min   1))   min;
            }
        </script>
    </head>
    <body style="background-color:black;">
        <div style="color:white;font-weight:bold;overflow:hidden;overflow-y:scroll;" class="grid games" id="Lista-de-Jogos-Lateral">
            <script id="script-da-caixa-de-selecao-suspensa-5">
                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 = d3.csv("Lista_de_Jogos.csv");
                        
                    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,format&fit=clip&q=75&w=263&s=c1691b4034fd0c4526d27ffe8b1e839c")
                        .attr("name",d => "grafico-betfair-"   d.numbergame);
                }
                
                update();
                    setInterval(update,2000);
            </script>
        </div>
    </body>
</html>

CodePudding user response:

I've made some adjustments to your code to make it work.

  • First, I moved all the scripts tags to the end of the <body> tag and placed them in order.
  • Second, I added d3-fetch.js as a dependency and removed the duplicated d3.js one.
  • Third, I disabled all the auto update code in order to test the code and avoid becoming insane.

When I opened the HTML file with my browser without using a web server, the request for the file failed so the code didn't work. I installed Live Server in VSCode and it started to work immediately, being able to read the file and append elements to the body.

Another error I had was Uncaught TypeError: document.getElementsByTagName(...)[totalimages] is undefined as it could read the data. Once I could open the file, that error disappeared.

<html>
    <head>
        <style>
            body {
            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;
            }
        </style>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.1.1/d3.min.js"></script>
        <script src="https://cdn.jsdelivr.net/npm/d3-fetch@3"></script>
    </head>
    <body style="background-color:black;">
        <div style="color:white;font-weight:bold;overflow:hidden;overflow-y:scroll;" class="grid games" id="Lista-de-Jogos-Lateral">
        </div>
    
        <script id="script-da-caixa-de-selecao-suspensa-5">
            var select_5 = d3.select("#Lista-de-Jogos-Lateral")
            .append("div")
            .attr("id","select-box-5")
            .style("width","100%")
            .style("max-height","574px");

            async function update() {

                let data = await d3.csv("./Lista_de_Jogos.csv");
                console.log("Data from CSV file: ", {data})

                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,format&fit=clip&q=75&w=263&s=c1691b4034fd0c4526d27ffe8b1e839c")
                    .attr("name",d => "grafico-betfair-"   d.numbergame);
            }
            
            update();
            console.log("Auto CSV update is disabled!")
            //setInterval(update,2000);
        </script>
        <script id="auto-update-images">
            let interval_images
                window.addEventListener('DOMContentLoaded', () => {
                    console.log("Auto update images is disabled!")
                    interval_images = refresh_images(); //setInterval(refresh_images, 5000); // refresh every 5 sec
                })
                
            function refresh_images() {
                if (!document.images) return;
                const totalimages = document.querySelectorAll("img").length - 1;
                const lastimages = parseInt(document.getElementsByTagName('img')[totalimages].getAttribute('name').replace("grafico-betfair-", ""))   1;
                for (let i = 1; i < lastimages; i  ) {
                    try {
                        document.images['grafico-betfair-'   i].src = document.getElementById('barra-de-texto-para-grafico-'   i).value;
                    } catch (e) {
                    }
                }
            }
        </script>
        <script id="random-number">
            function generateRandomIntegerInRange(min, max) {
                return Math.floor(Math.random() * (max - min   1))   min;
            }
        </script>
    </body>
</html>

If you try to run this code with the "run code snippet" button, it will fail as it doesn't have access to the csv file. It should work with valid data, though. Your code is expecting to replace the images URL by using a field available in the csv file so make sure your data has those fields.

  • Related