HTML van een bezoeker: tekst blijft tekst met textContent
In les 7 ontstond de HTML pas in
de browser, in de functie toon. Daar hoort de bescherming dus ook.
textContent in plaats van innerHTML
De regel blijft dezelfde als in de lessen hiervoor: de bescherming hoort op de
plek waar tekst HTML wordt. Hier is dat de browser, en daar doet textContent
wat escape op de server doet. Vervang de regel in toon in
static/js/voorbeeld.js:
voorbeeld.textContent = veld.value;
Sla het bestand op en open de link uit les 7 opnieuw:
http://127.0.0.1:8000/static/gastenboek.html?bericht=<b>vet</b>
Gebruik innerHTML alleen voor HTML die je zelf in je code schreef, net als
|safe in les 6. Voor tekst uit een veld of de URL is
textContent de goede keuze.
htmx zet het antwoord van je server ook met innerHTML in de pagina, dat is
hx-swap="innerHTML". Dat is veilig zolang je server escapet: wat htmx krijgt,
is dan al <b>, en de browser toont het als tekst.
Er gaat iets mis
Het voorbeeld blijft leeg, zonder foutmelding
Na het vervangen staat er niets meer in het voorbeeld, en de Console is leeg.
Oorzaak: er staat textcontent met een kleine c. JavaScript kent het
verschil tussen hoofdletters en kleine letters. Zo'n eigenschap bestaat niet,
maar JavaScript geeft geen fout: het zet de tekst in een nieuwe eigenschap die
de browser niet gebruikt.
Oplossing: schrijf textContent, met een hoofdletter C.
// FOUT
voorbeeld.textcontent = veld.value;
// GOED
voorbeeld.textContent = veld.value;
Opdrachten
Opdracht 1: Predict - Een ampersand
textContent staat in toon. Je opent
http://127.0.0.1:8000/static/gastenboek.html?bericht=Tom%20%26%20Jerry.
Vraag: wat staat er in het voorbeeld?
Tip
%20 is een spatie en %26 een &. Wat doet URLSearchParams met die codes?
Antwoord
Tom & Jerry. URLSearchParams maakt van de codes weer een spatie en een &,
en textContent zet de tekst erin zoals hij is. De & moest in de link een
code zijn, anders had de browser hem gelezen als het begin van een tweede
query-parameter.
Opdracht 2: Run - Beide versies
Probeer de link met <b>vet</b> eerst met innerHTML in toon, en daarna met
textContent. Typ bij allebei in de Console:
document.querySelector("#voorbeeld").innerHTML
Wat geeft de Console terug?
Antwoord
Met innerHTML: '<b>vet</b>'. In de <p> staat een echte tag.
Met textContent: '<b>vet</b>'. De browser heeft de haakjes
zelf ge-escapet, net als escape in Python, en toont ze daarom als tekst.
Zo ziet voorbeeld.js er nu uit
const veld = document.querySelector("#bericht");
const voorbeeld = document.querySelector("#voorbeeld");
function toon() {
voorbeeld.textContent = veld.value;
}
veld.addEventListener("input", toon);
const vooraf = new URLSearchParams(location.search).get("bericht");
if (vooraf) {
veld.value = vooraf;
toon();
}
main.py is in les 7 en 8 niet veranderd.
Door naar les 9: in je eigen project.