terte Liste und schreibt sie über einen
Aufruf der Methode »setItem()« in den
»localStorage« zurück.
Einen fast identischen Ausdruck verwen-
det Zeile 27. Sie sichert die über den Auf-
ruf der Methode »delItem()« bereinigte
Liste wieder im »localStorage«. Der Filter
in Zeile 26 durchforstet das übergebene
Objekt »text«.
Template dazu
Zeile 1 von Listing 3 erzeugt ein zu-
nächst leeres HTML-Element vom Typ
»<template>« und speichert seine Re-
ferenz in der lokalen Konstanten »anot-
List«. Die folgenden Zeilen 2 bis 12 ini-
tialisieren das Template im deklarativen
Stil. Das bedeutet, sie geben ein HTML-
Codefragment in Form einer Zeichenkette
an. Das Skript weist der Zeichenkette die
Eigenschaft »innerHTML« zu und kopiert
diese so in das Template.
Listen und Knöpfchen
Die Angaben im »<style>«-Tag formatie-
ren die HTML-Liste im »<ul>«-Element
aus Zeile 10. Die Liste enthält die gespei-
cherten Kommentare. Das »<input>«-
Element in Zeile 11 dient der Eingabe
neuer Kommentare, das »<button>«-
die Methode »parse()« des globalen Json-
Objekts (Zeile 9). An dieser Stelle liest
die Methode »list Item()« das serialisierte
Feld mit Hilfe von »get Item()« aus »lo-
calStorage« und wandelt es in ein Array
zurück. Zeile 10 garantiert die Rückgabe
eines Feldes.
Die Methode »hasItem()« testet in Zeile
14 das gespeicherte Feld auf Dubletten.
Dazu durchforstet die Array-Methode
»filter()« die Liste nach Treffern. »save-
Item()« speichert einen neuen Kommen-
tar aus dem Aufrufparameter »text« (Zeile
17). Dazu hängt Zeile 20 den Wert von
»text« an die Liste der bestehenden Kom-
mentare. Zeile 21 serialisiert die erwei-
Programmieren
94
http://www.linux-magazin.de
Webentwicklung
01 (function() {
02 class AnotElement extends HTMLElement {
03 constructor() {
04 super();
05 this.attachShadow({'mode': 'open'});
06 }
07
08 listItem() {
09 const arr = JSON.parse(window.localStorage.getItem(
'annotations'));
10 return arr?arr:[];
11 }
12
13 hasItem(text) {
14 return text == '' || this.listItem().filter(stext => text ===
stext).length > 0;
15 }
16
17 saveItem(text) {
18 if (!this.hasItem(text)) {
19 const arr = this.listItem();
20 arr.push(text);
21 window.localStorage.setItem('annotations', JSON.stringify(arr));
22 }
23 }
24
25 delItem(text) {
26 const arr = this.listItem().filter(stext => text !== stext);
27 localStorage.setItem('annotations', JSON.stringify(arr.length
>0?arr:[]));
28 }
29 }
Listing 2: »anot‑list.js«
01 const anotList = document.createElement('template');
02 anotList.innerHTML = `
03 <style>
04 ul {
05 list‑style: none;
06 padding:0;
07 }
08 </style>
09 <slot></slot>
10 <ul id='list'></ul>
11 <input id="text" type="text">
12 <button id="add" type="button">+</button>`;
13
14 class AnotList extends AnotElement {
15 constructor() {
16 super();
17 this.shadowRoot.appendChild(anotList.content.cloneNode(true));
18 this.shadowRoot.querySelector('#add').addEventListener('click',
e => this.addItem());
19 this.listItem().forEach(text => this.showItem(text));
20 }
21
22 addItem() {
23 let text = this.shadowRoot.querySelector('#text').value;
24 if (!this.hasItem(text)) {
25 this.saveItem(text);
26 this.showItem(text);
27 }
28 }
29
30 showItem(text) {
31 var listed = new AnotItem(text);
32 this.shadowRoot.querySelector('#list').appendChild(listed);
33 this.shadowRoot.querySelector('#text').value = '';
34 this.shadowRoot.querySelector('#text').focus();
35 }
36 }
Listing 3: »anot‑list.js« (Fortsetzung)