Stephan Böni - Listen

Barrels

Listen

Listen aller Art sind ein wichtiger Bestandteil von Webseiten. Sie sollen schnell geladen werden und einfach zu bedienen sein. Einmal geladene Listenelemente sollen lokal gespeichert und wiederverwendet werden. Interaktionen mit den Listenelementen sollen in Echtzeit zwischen verschiedenen Tabs/Fenstern synchronisiert werden. Dieser Artikel zeigt, wie du das mit Web-Komponenten, einem Service-Worker und dem Session-Storage realisieren kannst.

Beispiel

Die folgenden zwei Listen zeigen die Verwendung von Web-Komponenten im Zusammenspiel mit einem Service-Worker und dem Session-Storage.

Voraussetzungen

Das Konzept der Web-Komponenten sollte dir bekannt sein. Ebenso solltest du wissen, wie ein Service-Worker funktioniert. Letzter verwenden wir jedoch nur zur Synchonisation der Klick-Events zwischen mehreren Listen und Browser-Tabs/-Fenstern.

Web-Komponenten Service-Worker

Javascript

Die grunlegende Funktionalität haben wir in eine separate Klasse ausgelagert. Diese Klasse wird in der default.js geladen und initialisiert.

Javascript: default.js // Load Extend Module async function loadExtend(module) { const file = './modules/' + module.charAt(0).toLowerCase() + module.slice(1) + '.js'; const mod = await import(file); } // Load List async function loadList(element) { if (document.querySelector(element)) { await loadExtend('List'); } } // Do on DOM Ready document.addEventListener('DOMContentLoaded', () => { loadList('article-list'); });

Ich sammle die Extend-Module im Unterordner modules und nenne die Dateien wie die Klasse, aber mit Kleinbuchstaben beginnend. Die Klasse List befindet sich also in ./modules/list.js.

Du kannst dir die Klasse herunterladen.

list.js

HTML

Der benötigte HTML-Code ist sehr gering.

HTML <article-list data-template="articleCard" data-articles='["article1", "article2", "article3", "article4", "article5", "article6"]'></article-list>

Die <article-list> ist ein benutzerdefiniertes Element. Die data-Parameter definieren das zu verwendende Template (articleCard) und die Daten (article1 bis article6). Diese Informationen werden vom Javascript gelesen und verarbeitet.

Das Template und die Daten werden aus dem Session-Storage geladen. Ist dort nichts vorhanden, werden sie vom Server geladen und im Session-Storage gespeichert.

PHP

Auf dem Server wird ein PHP-Skript benötigt, welches die Daten aus der Datenbank - in unserem Fall sind dies JSON-Dateien - holt und zurückgibt. Die list.js erwartet das PHP-Script unter /includes/data.php.

PHP: data.php <?php // allow CORS if(isset($_SERVER['HTTP_ORIGIN'])) { header("Access-Control-Allow-Origin: {$_SERVER['HTTP_ORIGIN']}"); header('Access-Control-Allow-Credentials: true'); header('Access-Control-Max-Age: 86400'); } // set content type header('Content-Type: application/json; charset=utf-8'); // verify the GET parameters $data = isset($_GET['data']) ? $_GET['data'] : []; if (!is_array($data)) { $data = json_decode($data, true); } if (!is_array($data) || count($data) < 3) { $response['error'] = 'Invalid GET parameters.'; echo json_encode($response); exit; } $sessionId = $data[0]; $pool = $data[1]; $key = $data[2]; $value = isset($data[3]) ? $data[3] : null; // check if session, pool and key are not empty if ($sessionId == '' || $pool == '' || $key == '') { $response['error'] = 'Session, Pool, and Key must not be empty.'; } else { // check if the session exists $sessionFile = 'users/'.$sessionId.'.json'; if (!file_exists($sessionFile)) { $response['error'] = 'Session not found.'; } else { // check if the pool exists $poolFile = 'pools/'.$pool.'.json'; if (!file_exists($poolFile)) { $response['error'] = 'Pool '.$pool.' not found.'; } else { // check if the key exists $poolData = json_decode(file_get_contents($poolFile), true); if (!array_key_exists($key, $poolData)) { $response['error'] = 'Key '.$key.' not found.'; } else { // get data from file if (!$value) { foreach($poolData[$key] as $index => $content) { $dataFile = 'components/'.$content; if (file_exists($dataFile)) { $poolData[$key][$index] = file_get_contents($dataFile); } } $response['data'] = $poolData[$key]; } else { // update data in file $poolData[$key] = $value; if (file_put_contents($poolFile, json_encode($poolData)) !== false) { chmod($poolFile, 0666); $response['success'] = $key.' updated.'; } else { $response['error'] = $poolFile.' not saved.'; } } } } } } // send response echo json_encode($response); ?>

JSON

Jetzt fehlen uns nur noch ein paar Musterdaten. Diese speichern wir in JSON-Dateien. Die Dateien liegen im Ordner /includes/pool/. Auch diese kannst du dir herunterladen.

articles.json templates.json

Klick-Event behandeln

Die Klick-Events werden über den Service-Worker synchronisiert. Dieser sendet die Events an alle geöffneten Tabs und Fenster, die dort über die items.js behandelt werden.

Javascript: service-worker.js // Process Message from Client self.addEventListener('message', event => { self.clients.matchAll().then(clients => { clients.forEach(client => { client.postMessage(event.data); }); }); });

In unserem Beispiel wird das geklickte Item in allen Tabs/Fenstern grün markiert.

Dran bleiben

Du hast es geschafft. Abonniere meine Benachrichtigungen, um weitere News und Anleitungen von mir zu erhalten.

Feed einbinden