Build a complete table from data, including data that tries to be HTML.
What to build
A table with a heading row, one row per student and a footer showing the average.
Requirements
- Inside
#report, make atheadwith twothcells:NameandMark. - Make a
tbodywith onetrper student, each with twotdcells. Give the row the classtopif the mark is 80 or more. - Make a
tfootwith one row: atdwithAverage, and atdwith the average mark to 1 decimal place. - One student's name contains HTML tags. It must appear on the page as those exact characters, and must not become an element.
Constraints
Do not write any rows in the HTML, and do not use innerHTML.
Example
The footer shows Average and 70.0.
Why it works
The third name is a small example of what an attacker could type. Because textContent never reads text as HTML, the tags are displayed harmlessly, and no extra checking is needed.
Hints
Hint 1
A small helper that makes a cell with some text saves a lot of repetition.
Hint 2
Append rows to a tbody, and put the headings in a thead.
Hint 3
Setting textContent means the name with tags in it stays harmless text.
Solution
Show one correct solution (try it yourself first)
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Report</title>
<style>
.top { background: gold; }
</style>
</head>
<body>
<table id="report"></table>
<script>
const students = [
{ name: "Rahim", mark: 82 },
{ name: "Mitu", mark: 91 },
{ name: "<b>Arif</b>", mark: 67 },
{ name: "Sadia", mark: 40 },
];
const table = document.querySelector("#report");
function cell(tag, text) {
const el = document.createElement(tag);
el.textContent = text;
return el;
}
function row(...cells) {
const tr = document.createElement("tr");
tr.append(...cells);
return tr;
}
const head = document.createElement("thead");
head.append(row(cell("th", "Name"), cell("th", "Mark")));
const body = document.createElement("tbody");
for (const student of students) {
const tr = row(cell("td", student.name), cell("td", student.mark));
if (student.mark >= 80) tr.classList.add("top");
body.append(tr);
}
const total = students.reduce((sum, s) => sum + s.mark, 0);
const foot = document.createElement("tfoot");
foot.append(row(cell("td", "Average"), cell("td", (total / students.length).toFixed(1))));
table.append(head, body, foot);
</script>
</body>
</html>