im Browser verfügbare APIs:
alert
, setTimeout
, ...)DOM:
document.querySelector("body").textContent = "hello world";
HTML APIs:
alert('hello world');
setTimeout(() => {
console.log('3 seconds have passed');
}, 3000);
Möglichkeiten:
intern, innerhalb des HTML-Codes:
<script type="module">
console.log('hallo welt');
</script>
extern, in einer separaten Datei:
<script src="main.js" type="module"></script>
"ältere" Version des Einbindens von JS:
<script></script>
"moderne" Version:
<script type="module"></script>
Auswirkungen der Verwendung von type="module"
:
DOM (Document Object Model) = JavaScript-API für Interaktion mit dem HTML-Inhalt
DOM Funktionalitäten:
Abfragen von HTML-Elementen:
document.getElementById()
document.getElementsByClassName()
document.getElementsByTagName()
document.querySelector()
document.querySelectorAll()
<div id="chat-popup">...</div>
Abfragen des DOM-Elements:
let element = document.getElementById('chat-popup');
äquivalent:
let element = document.querySelector('#chat-popup');
Abfragen von mehreren Elementen:
let inputElements = document.querySelectorAll('input');
Themen:
element.textContent = ...
element.innerText = ...
Diese beiden Properties haben ähnliche Funktionalitäten
Beispiel: Ersetzen des body-Inhalts durch den Text "hello world"
let body = document.querySelector('body');
body.textContent = 'hello world';
Zugriff auf HTML-Attribute: durch getAttribute
und setAttribute
oder durch eine entsprechende JS-Property
in HTML:
<a href="https://example.com">example</a>
Möglichkeiten in JS:
exampleLink.getAttribute("href")
exampleLink.setAttribute("href", "https://xyz.com")
exampleLink.href
exampleLink.href = "https://xyz.com"
Bei manchen HTML-Attributen weicht die entsprechende JS Property ab:
Attribut:
checkbox.setAttribute('checked', '');
checkbox.removeAttribute('checked');
DOM Property:
checkbox.checked = true;
checkbox.checked = false;
Das style
-Attribut ist ein String, die style
-Property ist ein Objekt:
element.setAttribute(
'style',
'color: #99aaff; padding: 4px;'
);
element.style.color = '#99aaff';
element.style.padding = '4px';
Zum class
-Attribut gibt es die Properties className
und classList
element.setAttribute('class', 'btn btn-primary');
element.className = 'btn btn-primary';
element.classList.add('important');
document.createElement()
element.append(...)
element.remove()
element.innerHTML
Beispiel: Erstellen eines Paragraphen mit einem Link
Vorlage:
<p>
I'm learning <a href="https://example.com">JavaScript</a>.
</p>
let p = document.createElement('p');
let link = document.createElement('a');
link.href = 'https://example.com';
link.innerText = 'JavaScript';
p.append("I'm learning ", link, ".");
Das neue Element (p
) kann in das bestehende Dokument eingefügt werden.
vorheriges Beispiel mit innerHTML
:
let p = document.createElement('p');
p.innerHTML =
'I\'m learning <a href="https://example.com">JavaScript</a>.';
Warum nicht immer innerHTML
verwenden?
Die Verwendung von innerHTML
ist gefährlich, wenn Inhalte von Benutzern bereitgestellt werden.
Beispiel: ein böswilliger Benutzer hat sich mit folgenden Daten registriert:
John
Doe
<script>prompt("Enter your credit card number:")</script>
Wenn wir innerHTML
verwenden, um den Spitznamen für andere Benutzer anzuzeigen, wird das Script in deren Browsern ausgeführt.
Bemerkung: die Verwendung von textContent
bzw. innerText
ist nicht gefährlich
Möglichkeiten, um Angriffe zu verhindern:
Vermeiden von innerHTML
oder
"escapen" von Inhalten, die aus unsicheren Quellen kommen
"Escapen" von Inhalten:
unsicherer String: <script>...</script>
"escaped" string mit HTML Entities: <script>...</script>
we can react to user interaction and other events, e.g.:
we can add functions as "event listeners":
let button = document.querySelector('#my-button');
button.addEventListener('click', () => {
console.log('click event triggered on button');
});
example: click counter - displaying a number in a div that is incremented when a button is clicked
let counterDisplay = document.createElement('div');
counterDisplay.textContent = '0';
let counterButton = document.createElement('button');
counterButton.textContent = 'increment';
counterButton.addEventListener('click', () => {
counterDisplay.textContent =
Number(counterDisplay.textContent) + 1;
});
document
.querySelector('body')
.append(counterDisplay, counterButton);
event names:
see https://www.w3schools.com/jsref/dom_obj_event.asp for a long list
exercise: Create an HTML file with various elements that have event listeners. Whenever an event occurs, log it to the console.
example output in the console:
button1: mouseenter
button1: click
button1: mouseleave
textbox1: mouseenter
textbox1: click
textbox1: input
textbox1: input
textbox1: mouseleave
When an event occurs, we can access its corresponding Event
object in JavaScript:
myButton.addEventListener('click', (event) => {
console.log('myButton was clicked');
console.log('mouse button:', event.button);
console.log('coordinates:', event.clientX, event.clientY);
});
examples:
Example: todo list
Web components = benutzerdefinierte Elemente: Können mittels JavaScript erstellt und wie reguläre HTML-Elemente verwendet werden
Beispiel: Fußzeile, die auf mehreren Seiten verwendet werden kann
<my-footer></my-footer>
Beispiel: Elemente, die eine Navigationsleiste bilden
<my-navbar>
<my-logo></my-logo>
<my-navbar-item>
<a href="...">Startseite</a>
</my-navbar-item>
<my-navbar-item>
<a href="...">Ãœber uns</a>
</my-navbar-item>
</my-navbar>
Beispiel: Kartenansicht mit verschiedenen Konfigurationsoptionen
<my-map-view lat="48.2" lon="17.5" zoom="8"></my-map-view>
Beispiel: E-Mail-Liste
<my-email-list>
<my-email from="..." to="..." title="..."></my-email>
<my-email from="..." to="..." title="..."></my-email>
</my-email-list>
Relativ einfach zu implementieren:
Komplizierter (ohne zusätzliche Tools):
debugger
Statement
Breakpoints:
Manuell weiterspringen:
Beobachten von Variablen
for ... of
getElementById
/ getElementsByClassName
/ querySelectorAll
addEventListener
innerText
/ innerHTML
preventDefault
Elemente, die standardmäßig "draggable" sind:
Frage: praktische Anwendung? / Wohin können wir ziehen?
weitere Elemente "draggable" machen:
<div draggable="true">drag me!</div>
welche Drag-Events gibt es?
und auf welchen Elementen werden diese ausgelöst?
Events des "bewegten" Elements:
Events des Ziels:
Ãœbung: mehrere "draggable" Elemente, die jeweils anzeigen, wie of sie schon "gedraggt" wurden
"drop" auf Elementen erlauben:
bei "dragenter" und "dragover" Events des Ziels .preventDefault()
aufrufen
function onDragEnter(event) {
event.preventDefault();
}
function onDragOver(event) {
event.preventDefault();
}
auf "drop" reagieren:
function onDrop(event) {
event.preventDefault();
event.target.innerText += ' drop ';
}
Übung: ein Element das mitzählt, wie oft auf es gedroppt wurde
Bei "drag start" Daten bestimmter Formate mitgeben:
function onDragStart(event) {
event.dataTransfer.setData('text/plain', 'foo bar');
event.dataTransfer.setData(
'text/html',
'<em>foo</em> bar'
);
}
Beispiel: Draggen von HTML-Inhalten nach Word und in einen Plain-Text-Editor
bei "drag start" Daten eines Bestimmten Types mitgeben:
function onDragStart(event) {
event.dataTransfer.setData('text/plain', 'foo');
}
bei "drag end" Daten auslesen:
function onDrop(event) {
event.preventDefault();
const data = event.dataTransfer.getData('text/plain');
}
Übung: verschiedene Produkte, die in den Einkaufswagen gezogen werden können
Wir können auch ein ganzes Element durch drag and drop in ein anderes Element verschieben lassen
Verfahren: Der Dateneintrag, der übergeben wird, kann die ID des Elements sein - basierend darauf können wir das verschobene Element in sein neues Elternelement verschieben