【问题标题】:How to update elements of an HTML that the elements are created using data from a CSV file?如何更新使用 CSV 文件中的数据创建元素的 HTML 元素?
【发布时间】:2021-11-20 23:40:58
【问题描述】:

我的元素是根据CSV file 中的数据创建的,每 1 分钟更新一次。

我正在尝试按如下方式更新这些元素:

  1. 删除那些数据不再在CSV file
  2. 创建出现在CSV file 中的新的
  3. 保留CSV file 中仍存在的内容而不进行编辑

CSV 文件如下所示:

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

它的更新示例如下(消失的 BD 并出现 GZY):

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

要调用每 1 分钟更新一次数据的函数,我使用此脚本:

<script id="auto-update-csv">
    let interval_csv
    window.addEventListener('DOMContentLoaded', () => {
        interval_csv = setInterval(refresh_csv, 30000); // refresh every 60 secs
    })
    
    function refresh_csv() {
        d3.csv("Lista_de_Jogos.csv", function(data){caixa_suspensa_5(data)});
    }
</script>

包含此作业的自动更新调用的函数(创建元素并更新)的通用脚本描述如下:

<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 valorparaiframe(iframevalue) {
                let link = iframevalue;
                let newurl = link.split("OB_EV")[1];
                newurl = newurl.split("/")[0];
                    return "https://sports.staticcache.org/scoreboards/scoreboards-football/index.html?eventId=" + newurl;
            }
            
            function caixa_suspensa_5(data) {
            let update_5 = select_5.selectAll("div")
                .data(data);
            update_5.exit().remove();
            const div = update_5.enter().append("div").attr("class","matches")

            div.append("iframe").merge(update_5)
                .attr("src",d => valorparaiframe(d.value))
                .style("width","100%")
                .style("height","282");

            div.append("form").merge(update_5)
                .attr("action",d => d.market)
                .attr("target","_blank")
                .style("width","100%")
                
                .append("input").merge(update_5)
                .attr("type","submit")
                .attr("target","_blank")
                .style("width","100%")
                .attr("value","Jogo Betfair")

            div.append("form").merge(update_5)
                
                .append("input").merge(update_5)
                .attr("type","text")
                .attr("id",d => "barra-de-texto-para-grafico-" + d.numbergame)
                .style("width","100%")

            div.append("img").merge(update_5)
                .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)
            }
            d3.csv("Lista_de_Jogos.csv", function(data){caixa_suspensa_5(data)});
        </script>
    </div>
</body>

正如所见,我尝试使用这部分来尝试更新元素:

let update_5 = select_5.selectAll("div")
    .data(data);
update_5.exit().remove();
const div = update_5.enter().append("div").attr("class","matches")

但是当触发器被激活时,它会变得一团糟,新元素被创建而旧元素没有被正确删除。

我应该使用哪种模型才能根据我的需要工作?

我用d3.jsversion 4

<script src="https://d3js.org/d3.v4.js"></script>

包含多个已创建和更新列的页面模板如下所示:

但是当它每 1 分钟更新一次时,它会扭转这种局面,与我的预期完全不同,其他元素消失并只保留 &lt;iframe&gt;:

这是&lt;head&gt; 中使用的&lt;style&gt;,供那些希望更轻松地重新创建页面的人使用:

<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>

【问题讨论】:

  • 不要按索引绑定数据,这是默认的,尝试使用键函数正确匹配数据记录:.data(data, d =&gt; d.label);。有关详细信息,请参阅 selection.data([data[, key]]) 上的 docs
  • 从版本 5 开始,可以等到加载 CSV 文件。示例:d3.text(window.location.protocol + '//' + window.location.host + '/car_data.csv').then( (data) =&gt; { var parsedCSV = d3.csvParseRows(data); &lt;...&gt; });

标签: javascript html csv d3.js


【解决方案1】:

“它变得一团糟”。是的,它会。让我们看一下您的部分代码。请记住,当您使用 append 时,您会返回附加元素的选择:

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

上面的内容显然会导致元素被附加到你不想要的地方。

首先,我们正在合并不同类型的元素,因此,其次,我们在可能不希望的情况下将输入附加到 div 和表单。本质上,我们将事物附加到各种不应该附加事物的事物上。每次迭代中保留的 div 越来越多地被多余的元素污染,并且没有在哪里删除这些元素(你不应该删除那些多余的元素,你应该首先不要添加它们)。

我将建议Altocumulus in the comments建议的方法,而不是按原样修复您的代码:“而不是按索引绑定数据,这是默认设置,尝试使用键函数正确匹配数据记录":如果单个条目的数据没有变化,则附加后无需更新。相反,我们只需要删除已删除数据的 div 元素,这意味着我们只需要在 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");

    ...

这里不需要合并,因为如果这些元素的数据仍然存在于数据数组中(无论索引如何),我们不会修改现有元素。

这是一个示例,其中包含除 iframe 之外的所有内容(因为您没有包含具有有效路径的示例数据):

    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>
    

上面使用 d3.csvParse() 而不是 d3.csv() 来创建 csv 数据 - 这允许 sn-p 完全独立,这需要使用 pre 元素来保存csv 数据.

【讨论】:

  • 嗨@AndrewReid 非常感谢你的帮助,它让我明白了很多,但我最终怀疑我如何使用这个模型,但使用来自名为@987654327 的文件的数据@,这样我就不需要创建另一个脚本来直接在 HTML 中创建文本,例如 csv1csv2。你能帮帮我吗?
  • 如有必要,我可以给你更多的赏金积分,这样你就可以在处理文件方面帮助我。
猜你喜欢
  • 2019-04-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-09-23
  • 2014-04-16
  • 2018-05-21
  • 2019-01-07
相关资源
最近更新 更多