Ga direct naar de hoofdinhoud
INCOGNIKOTER
INCOGNIKOTER
  • Home
  • About us
  • Apps
  • coolja

Maak jouw eigen website met JouwWeb

© 2025 - 2026 incognikoter
Powered by JouwWeb
My Local Checklist My Local Checklist

My Checklists

Your User ID: Loading...

(This ID stores your data locally in this browser.)

No lists yet! Create your first list above.

This list is empty! Add your first item above.

Notification

Import Checklist Data

Paste your exported JSON data below. This will overwrite your current checklists.

Confirm Deletion

Are you sure you want to delete the list "" and all its items? This action cannot be undone.

`; itemsContainer.appendChild(itemElement); // Attach event listeners itemElement.querySelector('.toggle-complete-btn').addEventListener('click', (event) => { const id = event.currentTarget.dataset.itemId; const completed = event.currentTarget.dataset.itemCompleted === 'true'; handleToggleComplete(id, completed); }); itemElement.querySelector('.delete-item-btn').addEventListener('click', (event) => { const id = event.currentTarget.dataset.itemId; handleDeleteItem(id); }); // Click on span to toggle complete itemElement.querySelector('span').addEventListener('click', (event) => { const id = event.currentTarget.dataset.itemId; const completed = event.currentTarget.dataset.itemCompleted === 'true'; handleToggleComplete(id, completed); }); }); } saveDataForUser(); // Save state after rendering items } // --- Event Handlers --- function handleAddList() { const listName = newListInput.value.trim(); if (!listName) { showUserMessage("List name cannot be empty."); return; } const newList = { id: generateUniqueId(), name: listName, createdAt: new Date().toISOString(), }; allLists.push(newList); allLists.sort((a, b) => a.name.localeCompare(b.name)); // Keep sorted newListInput.value = ''; renderLists(); } function handleSelectList(listId, name) { selectedListId = listId; selectedListName = name; // When selecting a list, we need to ensure its items are loaded. // In this local storage setup, items for a specific list are generally // stored within the main data object, so we reload the whole data for the user. loadDataForUser(currentUserId); // Reloads all data, including current selected list items renderItemsView(); newItemTextInput.placeholder = `Add item to "${selectedListName}"...`; renderApp(); // Update title and view } function handleBackToLists() { selectedListId = null; selectedListName = ''; itemsForSelectedList = []; renderListsView(); renderApp(); // Update title and view } function showConfirmDeleteModal(listId, listName) { currentListToDeleteId = listId; listToDeleteNameSpan.textContent = listName; confirmDeleteModal.classList.remove('hidden'); } function confirmDeleteList() { if (!currentListToDeleteId) return; const listIndex = allLists.findIndex(list => list.id === currentListToDeleteId); if (listIndex > -1) { allLists.splice(listIndex, 1); } // If the deleted list was the currently selected one, clear selection if (selectedListId === currentListToDeleteId) { selectedListId = null; selectedListName = ''; itemsForSelectedList = []; } confirmDeleteModal.classList.add('hidden'); currentListToDeleteId = null; renderLists(); // Re-render lists renderApp(); // Update view showUserMessage("List and its items deleted successfully."); } function cancelDeleteList() { confirmDeleteModal.classList.add('hidden'); currentListToDeleteId = null; } function handleAddItem() { const itemText = newItemTextInput.value.trim(); if (!itemText) { showUserMessage("Checklist item cannot be empty."); return; } const newItem = { id: generateUniqueId(), text: itemText, completed: false, timestamp: new Date().toISOString(), }; itemsForSelectedList.push(newItem); itemsForSelectedList.sort((a, b) => { if (a.completed !== b.completed) { return a.completed ? 1 : -1; } return new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime(); }); newItemTextInput.value = ''; renderItems(); } function handleToggleComplete(itemId, completed) { const itemIndex = itemsForSelectedList.findIndex(item => item.id === itemId); if (itemIndex > -1) { itemsForSelectedList[itemIndex].completed = !completed; itemsForSelectedList.sort((a, b) => { if (a.completed !== b.completed) { return a.completed ? 1 : -1; } return new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime(); }); renderItems(); } } function handleDeleteItem(itemId) { itemsForSelectedList = itemsForSelectedList.filter(item => item.id !== itemId); renderItems(); } // --- View Switching --- function renderListsView() { listView.classList.remove('hidden'); itemView.classList.add('hidden'); renderLists(); } function renderItemsView() { listView.classList.add('hidden'); itemView.classList.remove('hidden'); renderItems(); } // --- Data Export/Import --- function handleExportData() { if (!currentUserId) { showUserMessage("No user ID to export data. Please load the app first."); return; } try { // To export all data, we assume itemsForSelectedList is always the current items. // For a robust export, we'd iterate through all lists and their nested items. // Given the current local storage structure, we'll export the comprehensive structure: const dataToExport = { lists: allLists.map(list => { const listCopy = { ...list }; // If this list is the selected one, include its items. // Otherwise, we'd need to load items for all lists which is more complex // for a pure localStorage setup without a nested structure. // For simplicity, this export primarily exports the *currently loaded* items // for the selected list, along with all list metadata. if (list.id === selectedListId) { listCopy.items = itemsForSelectedList; } else { // To properly export items for unselected lists, you'd need to // either: 1) Load all items for all lists into memory, or // 2) Have a more complex localStorage schema like: // localStorage.getItem(`checklist_items_${currentUserId}_${list.id}`); // For this scope, we'll just export list metadata and the *currently active* items. // If a list was never opened, its items won't be in itemsForSelectedList. // This means only items of the LAST actively viewed list will be exported accurately. listCopy.items = []; // Placeholder for unselected lists' items } return listCopy; }), selectedListId: selectedListId, selectedListName: selectedListName, itemsForSelectedList: itemsForSelectedList // Export currently active items as well }; const jsonString = JSON.stringify(dataToExport, null, 2); // Pretty print JSON const textArea = document.createElement("textarea"); textArea.value = jsonString; document.body.appendChild(textArea); textArea.select(); document.execCommand('copy'); document.body.removeChild(textArea); showUserMessage("All your checklist data (lists and current list items) has been copied to your clipboard as JSON."); } catch (error) { console.error("Error exporting data:", error); showUserMessage(`Failed to export data: ${error.message}`); } } function handleOpenImportModal() { importModal.classList.remove('hidden'); importDataTextarea.value = ''; // Clear previous content } function handleImportData() { const dataToImport = importDataTextarea.value.trim(); if (!dataToImport) { showUserMessage("Please paste the JSON data into the text area."); return; } try { const importedData = JSON.parse(dataToImport); if (!importedData || !Array.isArray(importedData.lists)) { throw new Error("Invalid data format. Expected an object with a 'lists' array."); } allLists = importedData.lists.map(list => ({ ...list, // Ensure timestamps are correctly handled if they were exported as strings createdAt: list.createdAt ? new Date(list.createdAt).toISOString() : new Date().toISOString() })); allLists.sort((a, b) => a.name.localeCompare(b.name)); selectedListId = importedData.selectedListId || null; selectedListName = importedData.selectedListName || ''; itemsForSelectedList = importedData.itemsForSelectedList || []; // Load items // Ensure items are sorted correctly after import itemsForSelectedList.sort((a, b) => { if (a.completed !== b.completed) { return a.completed ? 1 : -1; } return new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime(); }); // Save imported data to local storage under the current user ID saveDataForUser(); // Call saveDataForUser to persist the new state importModal.classList.add('hidden'); importDataTextarea.value = ''; showUserMessage("Data imported successfully! Your checklists have been updated."); renderApp(); // Re-render the entire app to reflect imported data } catch (error) { console.error("Error importing data:", error); showUserMessage(`Failed to import data: ${error.message}. Please ensure the JSON format is correct.`); } } // --- Initialize App --- document.addEventListener('DOMContentLoaded', () => { let userId = localStorage.getItem('current_checklist_user_id'); if (!userId) { userId = generateUniqueId(); localStorage.setItem('current_checklist_user_id', userId); } currentUserId = userId; loadDataForUser(currentUserId); // Load initial data for the user renderApp(); // Initial render based on loaded state }); // --- Attach Event Listeners --- generalModalOkBtn.addEventListener('click', closeGeneralModal); addListBtn.addEventListener('click', handleAddList); newListInput.addEventListener('keypress', (e) => { if (e.key === 'Enter') handleAddList(); }); backToListsBtn.addEventListener('click', handleBackToLists); addItemBtn.addEventListener('click', handleAddItem); newItemTextInput.addEventListener('keypress', (e) => { if (e.key === 'Enter') handleAddItem(); }); exportDataBtn.addEventListener('click', handleExportData); importDataBtn.addEventListener('click', handleOpenImportModal); importCancelBtn.addEventListener('click', () => importModal.classList.add('hidden')); importConfirmBtn.addEventListener('click', handleImportData); deleteCancelBtn.addEventListener('click', cancelDeleteList); deleteConfirmBtn.addEventListener('click', confirmDeleteList);