Beispiel:JS-DOM-Tut-8.html
Aus SELFHTML-Wiki
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ToDo-Liste - 3</title>
<link rel="stylesheet" media="screen" href="./Beispiel:SELFHTML-Beispiel-Grundlayout.css">
<style>
ul {list-style-type:none;}
li {
width: 20em;
display: grid;
grid-template-columns: 1.5em 1fr 2em;
margin: 0;
input {width: 0; height: 0; font-size:0; margin:0;}
label {
background: gainsboro;
border: thin solid grey;
grid-column: 1/-1;
grid-row: 1/2;
padding:0.5em;
display:grid;
grid-template-columns: 1.5em 1fr;
}
input:checked ~ label {background: #d4e3b5;}
input:checked ~ label:before {
font-size:1.5em; line-height: 1.15rem;
content: "✓ ";
color:green;
grid-column: 1/2;
grid-row: 1/2;
}
.text {
grid-column: 2/3;
grid-row: 1/2;
}
button {
background: transparent;
background-repeat: no-repeat;
background-size: contain;
border: none;
padding: 0;
margin: 0;
width: 2rem;
aspect-ratio: 1/1;
font-size: 0;
color:transparent;
grid-column: -2/-1;
grid-row: 1/2;
}
[commandfor=editSettings]{
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' viewBox='-98 -98 196 196'%3E%3Cpath id='cog' d='m-17,-55 l5-17 h20 l5,17z' style='fill:steelblue;stroke:steelBlue; stroke-width:15;stroke-linejoin:round;'/%3E%3Cuse href='%23cog' transform='rotate(60)' /%3E%3Cuse href='%23cog' transform='rotate(120)' /%3E%3Cuse href='%23cog' transform='rotate(180)' /%3E%3Cuse href='%23cog' transform='rotate(240)' /%3E%3Cuse href='%23cog' transform='rotate(300)' /%3E%3Ccircle r='45' style='fill:none;stroke:steelblue; stroke-width:30'/%3E%3C/svg%3E");
}
}
dialog {
position: relative;
padding: 2em 2em 1em 1em;
button {
font-size: 0;
color: transparent;
width: 2rem;
aspect-ratio: 1 / 1;
}
.save-button {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 480 499' style='fill:none; stroke:steelBlue;stroke-width:25' %3E%3Crect x='150' y='60' rx='10' width='180' height='100' /%3E%3Crect x='130' y='280' rx='10' width='220' height='175' /%3E%3Cpath id='outer' d='m40,80 a20,20 1,0,1 20-20 h280 a20,20 1,0,1 15,10 l90,90 v275 a 20,20 1,0,1 -20,20 h-365 a 20,20 1,0,1 -20-20 z'/%3E%3C/svg%3E");
}
.delete-button {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 499 499' style='fill:none; stroke:steelBlue;stroke-width:25' %3E%3Crect width='100%25' height='100%25' style='fill:none;stroke:%23132c39; stroke-width:1' /%3E%3Cpath id='handle' d='m169,70 v-40 h150 v40'/%3E%3Crect x='64' y='100' rx='10' width='365' height='80'/%3E%3Cpath d='m99,180 l40,280 h220 l40,-280 m-235,75 l15,160 m70,0 v-160 m80,0 l-15,160'/%3E%3C/svg%3E");
}
p {text-align: right;}
}
dialog::backdrop {
background: hsl(201 50% 40% /.5) ;
}
.planned label {
background: LightYellow ;
}
.in-work label {
background: salmon;
}
.finished label {
background: #d4e3b5;;
}
li:first-of-type {
border-radius: 0.5em 0.5em 0 0;
}
li:last-of-type {
border-bottom-left-radius: 0.5em;
border-bottom-right-radius: 0.5em;
}
</style>
<script>
'use strict';
document.addEventListener('DOMContentLoaded', function () {
const taskList = document.querySelector('#taskList');
const newTaskInput = document.querySelector('#newtask');
const addButton = document.querySelector('#add');
const editDialog = document.querySelector('#editSettings');
const editTextInput = document.querySelector('#editText');
const saveButton = document.querySelector('.save-button');
const deleteButton = document.querySelector('.delete-button');
const statusDropdown = document.querySelector('.status-dropdown');
let selectedTask = null;
let taskIdCounter = 0;
// Add new task
addButton.addEventListener('click', function () {
const taskText = newTaskInput.value.trim();
if (!taskText) {
alert('Bitte gib eine Aufgabe ein.');
return;
}
const taskId = `todo-${taskIdCounter++}`;
taskList.insertAdjacentHTML('beforeend', `
<li class="planned"> <!-- Default to "planned" -->
<input type="checkbox" id="${taskId}">
<label for="${taskId}">
<span class="text">${taskText}</span>
</label>
<button aria-label="Edit task: ${taskText}" command="show-modal" commandfor="editSettings">Bearbeiten</button>
</li>
`);
newTaskInput.value = '';
});
// Open edit dialog & load data
document.addEventListener('click', function (event) {
const editButton = event.target.closest('[commandfor="editSettings"]');
if (!editButton) return;
selectedTask = editButton.closest('li');
if (selectedTask) {
const taskText = selectedTask.querySelector('.text').textContent;
editTextInput.value = taskText;
// Load current status
const currentStatus = selectedTask.classList.contains('in-work')
? 'in-work'
: selectedTask.classList.contains('finished')
? 'finished'
: 'planned';
statusDropdown.value = currentStatus;
statusDropdown.disabled = selectedTask.classList.contains('finished'); // Disable if finished
}
});
// Save edited text and status
saveButton.addEventListener('click', function () {
if (selectedTask) {
selectedTask.querySelector('.text').textContent = editTextInput.value;
// Update task status
selectedTask.classList.remove('planned', 'in-work', 'finished');
selectedTask.classList.add(statusDropdown.value);
}
editDialog.close();
});
// Confirm delete
deleteButton.addEventListener('click', function () {
if (selectedTask) {
const confirmDelete = confirm('Bist du sicher, dass du diese Aufgabe löschen möchtest?');
if (confirmDelete) {
selectedTask.remove();
selectedTask = null;
editDialog.close();
}
}
});
// Handle checkbox toggle for "Finished"
document.addEventListener('change', function (event) {
const checkbox = event.target.closest('input[type="checkbox"]');
if (!checkbox) return;
const taskItem = checkbox.closest('li');
if (!taskItem) return;
if (checkbox.checked) {
taskItem.classList.remove('planned', 'in-work');
taskItem.classList.add('finished');
} else {
taskItem.classList.remove('finished');
taskItem.classList.add('planned'); // Default back to "Planned"
}
});
// Polyfill for command / Close dialog manually
document.addEventListener('click', (event) => {
if ('CommandEvent' in window) return; // Exit if native support exists
const commandTarget = event.target.closest('[command]');
if (commandTarget) {
const dialogId = commandTarget.getAttribute('commandfor');
const dialog = document.getElementById(dialogId);
if (dialog instanceof HTMLDialogElement) {
dialog.showModal();
}
}
});
});
</script>
</head>
<body>
<h1>ToDo-Liste - 3</h1>
<form id="controls">
<label for="newtask">Neues Vorhaben:</label>
<input id="newtask">
<button type="button" id="add">Hinzufügen!</button>
</form>
<ul id="taskList">
<li class="planned">
<input type="checkbox" checked id="${taskId}">
<label for="${taskId}">
<span class="text">Im Wiki aktiv werden!</span>
</label>
<button aria-label="Edit ${taskId}" command="show-modal" commandfor="editSettings">Bearbeiten</button>
</li>
</ul>
<dialog id="editSettings" closedby="any">
<form method="dialog">
<label for="editText">Ändere den Text:</label><br>
<input type="text" id="editText">
<button type="button" class="save-button">Speichern</button>
<p><button aria-label="Delete task: ${task}" class="delete-button">Löschen</button></p>
<select class="status-dropdown" size="3" >
<option value="planned">Planned</option>
<option value="in-work">In Work</option>
<option value="finished">Finished</option>
</select>
</form>
</dialog>
</body>
</html>