如何更新 HTML 的元素,这些元素是使用 CSV 文件中的数据创建的?
How to update elements of an HTML that the elements are created using data from a CSV file?
我的元素是根据每 1 分钟更新一次的 CSV file
中的数据创建的。
我正在尝试按如下方式更新这些元素:
- 删除那些数据不再在
CSV file
- 创建出现在
CSV file
中的新的
- 不编辑保留
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
它的更新示例如下(B
和 D
消失,G
、Z
和 Y
出现):
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.js
version 4
:
<script src="https://d3js.org/d3.v4.js"></script>
创建和更新的多列页面模板如下所示:
但是当它每1分钟更新一次时,它反过来了,与我预期的完全不同,其他元素消失了,只保留了 <iframe>
:
这是 <head>
中使用的 <style>
,供那些希望更轻松地重新创建页面的人使用:
<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>
“它变得一团糟”。是的,它会。让我们看一下您的部分代码。请记住,当您使用 append 时,您 return 选择了附加元素:
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 和表单。从本质上讲,我们将事物附加到各种不应附加事物的事物上。每次迭代中保留的 divs 越来越多地被多余的元素污染,并且您无法从哪里删除这些元素(您不应该删除那些多余的元素,您应该注意不要在第一个中添加它们地方)。
我不会按原样修复代码,而是建议 Altocumulus in the comments 建议的方法:“不要按索引绑定数据,这是默认设置,请尝试使用键函数来正确匹配数据记录”:如果单个条目的数据没有更改,则在追加后无需更新。相反,我们只需要删除已删除数据的 div 个元素,这意味着我们只需要在输入时追加和修改元素:
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 数据——这允许代码片段完全独立,这需要使用保存 csv 数据的 pre 元素.
我的元素是根据每 1 分钟更新一次的 CSV file
中的数据创建的。
我正在尝试按如下方式更新这些元素:
- 删除那些数据不再在
CSV file
- 创建出现在
CSV file
中的新的
- 不编辑保留
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
它的更新示例如下(B
和 D
消失,G
、Z
和 Y
出现):
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.js
version 4
:
<script src="https://d3js.org/d3.v4.js"></script>
创建和更新的多列页面模板如下所示:
但是当它每1分钟更新一次时,它反过来了,与我预期的完全不同,其他元素消失了,只保留了 <iframe>
:
这是 <head>
中使用的 <style>
,供那些希望更轻松地重新创建页面的人使用:
<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>
“它变得一团糟”。是的,它会。让我们看一下您的部分代码。请记住,当您使用 append 时,您 return 选择了附加元素:
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 和表单。从本质上讲,我们将事物附加到各种不应附加事物的事物上。每次迭代中保留的 divs 越来越多地被多余的元素污染,并且您无法从哪里删除这些元素(您不应该删除那些多余的元素,您应该注意不要在第一个中添加它们地方)。
我不会按原样修复代码,而是建议 Altocumulus in the comments 建议的方法:“不要按索引绑定数据,这是默认设置,请尝试使用键函数来正确匹配数据记录”:如果单个条目的数据没有更改,则在追加后无需更新。相反,我们只需要删除已删除数据的 div 个元素,这意味着我们只需要在输入时追加和修改元素:
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 数据——这允许代码片段完全独立,这需要使用保存 csv 数据的 pre 元素.