mirror of
https://github.com/thejakubruzicka/MNotes.git
synced 2025-07-10 14:34:05 +02:00
New version. Add Material UI implementation with theme customization, about dialog, and news system
This commit is contained in:
parent
5bc9c9bdb1
commit
1d58835a65
190 changed files with 12296 additions and 54 deletions
583
index.html
583
index.html
|
@ -5,56 +5,126 @@
|
|||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>MNotes</title>
|
||||
|
||||
<!-- Material Symbols -->
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200" />
|
||||
|
||||
<!-- Roboto Font (recommended for Material Design) -->
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700&display=swap" rel="stylesheet">
|
||||
|
||||
<!-- Material Symbols -->
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200" />
|
||||
|
||||
<!-- External stylesheet -->
|
||||
<link rel="stylesheet" href="style.css">
|
||||
|
||||
<!-- Material Web Components (MWC) - Using a more recent version -->
|
||||
<script type="module" src="https://cdn.jsdelivr.net/npm/@material/web@1.4.1/all.js"></script>
|
||||
<!-- Import map for Material Web Components -->
|
||||
<script type="importmap">
|
||||
{
|
||||
"imports": {
|
||||
"@material/web/": "https://esm.run/@material/web/"
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- Import Material Web Components -->
|
||||
<script type="module">
|
||||
import '@material/web/all.js';
|
||||
import {styles as typescaleStyles} from '@material/web/typography/md-typescale-styles.js';
|
||||
|
||||
// Apply typescale styles to the document
|
||||
document.adoptedStyleSheets.push(typescaleStyles.styleSheet);
|
||||
</script>
|
||||
|
||||
<style>
|
||||
/* Minimal pre-render styles to avoid FOUC and ensure basic layout */
|
||||
body {
|
||||
font-family: 'Roboto', sans-serif;
|
||||
margin: 0;
|
||||
/* Fallback colors, MWC themes will override */
|
||||
background-color: #fff;
|
||||
color: #000;
|
||||
opacity: 0; /* Initially hide body to prevent FOUC */
|
||||
transition: opacity 0.2s ease-in-out;
|
||||
}
|
||||
body.loaded {
|
||||
opacity: 1; /* Show body once MWC is likely ready */
|
||||
}
|
||||
/* Hide dialog by default to prevent flash of content if MWC is slow */
|
||||
md-dialog {
|
||||
display: none;
|
||||
}
|
||||
md-dialog[open] { /* MWC sets 'open' attribute which makes it visible */
|
||||
display: flex; /* Or block, MWC handles actual display type */
|
||||
}
|
||||
/* Theme variables and overrides */
|
||||
:root {
|
||||
/* Light theme is the default in style.css */
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
/* Dark theme overrides */
|
||||
body.dark-theme {
|
||||
background-color: #141218 !important;
|
||||
color: #E6E0E9 !important;
|
||||
}
|
||||
|
||||
/* Force Material component theming */
|
||||
body.dark-theme {
|
||||
--md-sys-color-background: #141218;
|
||||
--md-sys-color-on-background: #E6E0E9;
|
||||
--md-sys-color-surface: #1C1B1F;
|
||||
--md-sys-color-on-surface: #E6E0E9;
|
||||
--md-sys-color-primary: #D0BCFF;
|
||||
--md-sys-color-on-primary: #381E72;
|
||||
--md-sys-color-secondary: #CCC2DC;
|
||||
--md-sys-color-on-secondary: #332D41;
|
||||
--md-sys-color-surface-container: #211F26;
|
||||
--md-sys-color-surface-container-highest: #36343B;
|
||||
}
|
||||
|
||||
body.light-theme {
|
||||
background-color: #FEF7FF !important;
|
||||
color: #1D1B20 !important;
|
||||
--md-sys-color-background: #FEF7FF;
|
||||
--md-sys-color-on-background: #1D1B20;
|
||||
--md-sys-color-surface: #FDFCFB;
|
||||
--md-sys-color-on-surface: #1D1B20;
|
||||
--md-sys-color-primary: #6750A4;
|
||||
--md-sys-color-on-primary: #FFFFFF;
|
||||
--md-sys-color-secondary: #625B71;
|
||||
--md-sys-color-on-secondary: #FFFFFF;
|
||||
--md-sys-color-surface-container: #F3EDF7;
|
||||
--md-sys-color-surface-container-highest: #E6E0E9;
|
||||
}
|
||||
|
||||
/* Specific component overrides */
|
||||
body.dark-theme .note-card {
|
||||
background-color: #4A4458 !important;
|
||||
color: #E8DEF8 !important;
|
||||
}
|
||||
|
||||
body.dark-theme md-dialog {
|
||||
--md-dialog-container-color: #2B2930;
|
||||
--md-dialog-headline-color: #E6E0E9;
|
||||
--md-dialog-supporting-text-color: #E6E0E9;
|
||||
}
|
||||
|
||||
/* Base styles */
|
||||
body {
|
||||
font-family: 'Roboto', sans-serif;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
opacity: 0; /* Start hidden to prevent FOUC */
|
||||
transition: opacity 0.3s ease-in-out;
|
||||
}
|
||||
|
||||
body.loaded {
|
||||
opacity: 1; /* Show once components are defined */
|
||||
}
|
||||
|
||||
/* Force components to use theme variables */
|
||||
md-icon-button {
|
||||
--md-icon-button-icon-color: var(--md-sys-color-primary);
|
||||
}
|
||||
|
||||
#appTitle {
|
||||
color: var(--md-sys-color-primary);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<header>
|
||||
<h1 id="appTitle">MNotes</h1>
|
||||
<h1 class="md-typescale-headline-large" id="appTitle">MNotes</h1>
|
||||
<md-icon-button id="themeToggleBtn" aria-label="Toggle theme">
|
||||
<md-icon>dark_mode</md-icon> <!-- Icon will change dynamically -->
|
||||
<md-icon>dark_mode</md-icon>
|
||||
</md-icon-button>
|
||||
</header>
|
||||
|
||||
<div id="notesList">
|
||||
<div id="notesList" class="md-typescale-body-medium">
|
||||
<!-- Notes will be rendered here by JavaScript -->
|
||||
</div>
|
||||
|
||||
<md-fab aria-label="Add Note" id="addNoteFab" variant="primary">
|
||||
<md-fab aria-label="Add Note" id="addNoteFab">
|
||||
<md-icon slot="icon">add</md-icon>
|
||||
</md-fab>
|
||||
</div>
|
||||
|
@ -62,33 +132,442 @@
|
|||
<!-- Note Dialog (for creating/editing) -->
|
||||
<md-dialog id="noteDialog">
|
||||
<div slot="headline">Add/Edit Note</div>
|
||||
<form slot="content" id="noteForm" method="dialog">
|
||||
<input type="hidden" id="noteIdInput">
|
||||
<md-filled-text-field label="Title" id="noteTitleInput" required style="width: 100%; margin-bottom: 16px;"></md-filled-text-field>
|
||||
<md-outlined-text-field label="Content" id="noteContentInput" type="textarea" rows="5" required style="width: 100%; margin-bottom: 16px;"></md-outlined-text-field>
|
||||
</form>
|
||||
<div slot="content">
|
||||
<form id="noteForm">
|
||||
<input type="hidden" id="noteIdInput">
|
||||
<md-filled-text-field label="Title" id="noteTitleInput" required style="width: 100%; margin-bottom: 16px;"></md-filled-text-field>
|
||||
<md-outlined-text-field label="Content" id="noteContentInput" type="textarea" rows="5" required style="width: 100%; margin-bottom: 16px;"></md-outlined-text-field>
|
||||
</form>
|
||||
</div>
|
||||
<div slot="actions">
|
||||
<md-text-button form="noteForm" value="cancel">Cancel</md-text-button>
|
||||
<md-filled-button form="noteForm" value="save" type="submit">Save</md-filled-button>
|
||||
<md-text-button id="cancelNoteBtn">Cancel</md-text-button>
|
||||
<md-filled-button id="saveNoteBtn">Save</md-filled-button>
|
||||
</div>
|
||||
</md-dialog>
|
||||
|
||||
<!-- Confirmation Dialog -->
|
||||
<md-dialog id="confirmDeleteDialog">
|
||||
<div slot="headline">Confirm Delete</div>
|
||||
<div slot="content" class="md-typescale-body-medium">
|
||||
Are you sure you want to delete this note?
|
||||
</div>
|
||||
<div slot="actions">
|
||||
<md-text-button id="cancelDeleteBtn">Cancel</md-text-button>
|
||||
<md-filled-button id="confirmDeleteBtn">Delete</md-filled-button>
|
||||
</div>
|
||||
</md-dialog>
|
||||
|
||||
<script src="script.js"></script>
|
||||
<script>
|
||||
// Add 'loaded' class to body after MWC components are likely defined
|
||||
function showBody() {
|
||||
if (customElements.get('md-fab')) { // Check if a MWC component is defined
|
||||
document.body.classList.add('loaded');
|
||||
} else {
|
||||
// Fallback if MWC takes longer or fails for some reason
|
||||
setTimeout(() => document.body.classList.add('loaded'), 400);
|
||||
}
|
||||
}
|
||||
if (document.readyState === 'loading') {
|
||||
window.addEventListener('DOMContentLoaded', showBody);
|
||||
} else {
|
||||
showBody();
|
||||
}
|
||||
// Wait for both DOM content and Web Components to be ready
|
||||
function initApp() {
|
||||
// Check if critical components are defined
|
||||
if (!customElements.get('md-dialog') || !customElements.get('md-fab')) {
|
||||
// If components aren't ready yet, try again in a short while
|
||||
setTimeout(initApp, 100);
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('Initializing MNotes app...');
|
||||
|
||||
// DOM elements
|
||||
const notesList = document.getElementById('notesList');
|
||||
const addNoteFab = document.getElementById('addNoteFab');
|
||||
const noteDialog = document.getElementById('noteDialog');
|
||||
const confirmDeleteDialog = document.getElementById('confirmDeleteDialog');
|
||||
const noteForm = document.getElementById('noteForm');
|
||||
const noteIdInput = document.getElementById('noteIdInput');
|
||||
const noteTitleInput = document.getElementById('noteTitleInput');
|
||||
const noteContentInput = document.getElementById('noteContentInput');
|
||||
const themeToggleBtn = document.getElementById('themeToggleBtn');
|
||||
const body = document.body;
|
||||
|
||||
let notes = [];
|
||||
let currentEditingId = null;
|
||||
let noteToDeleteId = null;
|
||||
|
||||
// --- Theming ---
|
||||
function applyTheme(theme) { // theme is 'light' or 'dark'
|
||||
console.log('Applying theme:', theme);
|
||||
|
||||
// First, remove both themes to ensure clean state
|
||||
body.classList.remove('light-theme', 'dark-theme');
|
||||
|
||||
// Force the body to reset styles
|
||||
body.style.transition = 'none';
|
||||
|
||||
// Apply new theme with a small delay for better CSS processing
|
||||
setTimeout(() => {
|
||||
// Add the theme class
|
||||
body.classList.add(theme + '-theme');
|
||||
|
||||
// Force a repaint with inline styles
|
||||
body.style.backgroundColor = theme === 'dark' ? '#141218' : '#FEF7FF';
|
||||
body.style.color = theme === 'dark' ? '#E6E0E9' : '#1D1B20';
|
||||
|
||||
// Re-enable transitions
|
||||
setTimeout(() => {
|
||||
body.style.transition = 'all 0.3s ease-in-out';
|
||||
}, 50);
|
||||
|
||||
// Save preference
|
||||
localStorage.setItem('mnotes-theme', theme);
|
||||
|
||||
// Update theme toggle icon
|
||||
const icon = themeToggleBtn.querySelector('md-icon');
|
||||
if (icon) {
|
||||
if (theme === 'dark') {
|
||||
icon.textContent = 'light_mode';
|
||||
themeToggleBtn.ariaLabel = "Activate light theme";
|
||||
} else {
|
||||
icon.textContent = 'dark_mode';
|
||||
themeToggleBtn.ariaLabel = "Activate dark theme";
|
||||
}
|
||||
}
|
||||
}, 10);
|
||||
}
|
||||
|
||||
function toggleTheme() {
|
||||
console.log('Toggle theme clicked');
|
||||
const currentTheme = localStorage.getItem('mnotes-theme') ||
|
||||
(body.classList.contains('dark-theme') ? 'dark' : 'light');
|
||||
applyTheme(currentTheme === 'light' ? 'dark' : 'light');
|
||||
}
|
||||
|
||||
function loadInitialTheme() {
|
||||
const savedTheme = localStorage.getItem('mnotes-theme');
|
||||
if (savedTheme) {
|
||||
applyTheme(savedTheme);
|
||||
} else {
|
||||
// Prefer system theme if no preference saved
|
||||
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
||||
applyTheme('dark');
|
||||
} else {
|
||||
applyTheme('light'); // Default to light
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure themeToggleBtn exists before attaching event
|
||||
if (themeToggleBtn) {
|
||||
themeToggleBtn.addEventListener('click', toggleTheme);
|
||||
console.log('Theme toggle button event listener attached');
|
||||
} else {
|
||||
console.error('Theme toggle button not found');
|
||||
}
|
||||
|
||||
// --- Data Persistence ---
|
||||
function loadNotes() {
|
||||
try {
|
||||
const storedNotes = localStorage.getItem('material-notes');
|
||||
console.log('Loading notes from localStorage:', storedNotes);
|
||||
notes = storedNotes ? JSON.parse(storedNotes) : [];
|
||||
renderNotes();
|
||||
} catch (error) {
|
||||
console.error('Error loading notes:', error);
|
||||
notes = [];
|
||||
renderNotes();
|
||||
}
|
||||
}
|
||||
|
||||
function saveNotes() {
|
||||
try {
|
||||
console.log('Saving notes to localStorage:', notes);
|
||||
localStorage.setItem('material-notes', JSON.stringify(notes));
|
||||
} catch (error) {
|
||||
console.error('Error saving notes:', error);
|
||||
alert('Failed to save notes. If you\'re in private browsing mode, try regular browsing mode.');
|
||||
}
|
||||
}
|
||||
|
||||
// --- Rendering Notes ---
|
||||
function renderNotes() {
|
||||
if (!notesList) {
|
||||
console.error('Notes list element not found');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('Rendering notes:', notes);
|
||||
notesList.innerHTML = ''; // Clear existing notes
|
||||
|
||||
if (notes.length === 0) {
|
||||
const p = document.createElement('p');
|
||||
p.textContent = "No notes yet. Click the + button to add one!";
|
||||
notesList.appendChild(p);
|
||||
return;
|
||||
}
|
||||
|
||||
notes.sort((a, b) => new Date(b.lastModified) - new Date(a.lastModified)); // Sort by most recently modified
|
||||
|
||||
notes.forEach(note => {
|
||||
const noteCard = document.createElement('div');
|
||||
noteCard.className = 'note-card';
|
||||
|
||||
const elevation = document.createElement('md-elevation'); // Add MWC elevation
|
||||
elevation.setAttribute('level', '1');
|
||||
noteCard.appendChild(elevation);
|
||||
|
||||
const title = document.createElement('h3');
|
||||
title.textContent = note.title;
|
||||
title.className = 'md-typescale-headline-small';
|
||||
|
||||
const content = document.createElement('p');
|
||||
content.textContent = note.content.substring(0, 150) + (note.content.length > 150 ? '...' : '');
|
||||
content.className = 'md-typescale-body-medium';
|
||||
|
||||
const actions = document.createElement('div');
|
||||
actions.className = 'note-card-actions';
|
||||
|
||||
const editButton = document.createElement('md-icon-button');
|
||||
editButton.innerHTML = `<md-icon>edit</md-icon>`;
|
||||
editButton.ariaLabel = `Edit note: ${note.title}`;
|
||||
editButton.addEventListener('click', (e) => {
|
||||
e.stopPropagation();
|
||||
openNoteDialog(note);
|
||||
});
|
||||
|
||||
const deleteButton = document.createElement('md-icon-button');
|
||||
deleteButton.innerHTML = `<md-icon>delete</md-icon>`;
|
||||
deleteButton.ariaLabel = `Delete note: ${note.title}`;
|
||||
deleteButton.addEventListener('click', (e) => {
|
||||
e.stopPropagation();
|
||||
openDeleteDialog(note.id);
|
||||
});
|
||||
|
||||
actions.appendChild(editButton);
|
||||
actions.appendChild(deleteButton);
|
||||
|
||||
noteCard.appendChild(title);
|
||||
noteCard.appendChild(content);
|
||||
noteCard.appendChild(actions);
|
||||
notesList.appendChild(noteCard);
|
||||
});
|
||||
}
|
||||
|
||||
// --- Note Operations ---
|
||||
function openNoteDialog(note = null) {
|
||||
if (!noteDialog || !noteForm || !noteTitleInput || !noteContentInput) {
|
||||
console.error('Note dialog elements not found');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('Opening note dialog', note ? 'for editing' : 'for new note');
|
||||
noteForm.reset(); // Clear form fields
|
||||
// Reset MWC text field states (e.g. error messages)
|
||||
noteTitleInput.errorText = "";
|
||||
noteTitleInput.error = false;
|
||||
noteContentInput.errorText = "";
|
||||
noteContentInput.error = false;
|
||||
|
||||
if (note) {
|
||||
currentEditingId = note.id;
|
||||
noteTitleInput.value = note.title;
|
||||
noteContentInput.value = note.content; // Full content for editing
|
||||
|
||||
const headline = noteDialog.querySelector('[slot="headline"]');
|
||||
if (headline) headline.textContent = 'Edit Note';
|
||||
} else {
|
||||
currentEditingId = null;
|
||||
const headline = noteDialog.querySelector('[slot="headline"]');
|
||||
if (headline) headline.textContent = 'Add New Note';
|
||||
}
|
||||
|
||||
// Open the dialog
|
||||
noteDialog.open = true;
|
||||
}
|
||||
|
||||
// Direct save function - bypasses the dialog event issues
|
||||
function saveNote() {
|
||||
const title = noteTitleInput.value.trim();
|
||||
const content = noteContentInput.value.trim();
|
||||
console.log('Saving note:', { title, content });
|
||||
|
||||
let isValid = true;
|
||||
if (!title) {
|
||||
noteTitleInput.error = true;
|
||||
noteTitleInput.errorText = "Title cannot be empty.";
|
||||
isValid = false;
|
||||
} else {
|
||||
noteTitleInput.error = false;
|
||||
noteTitleInput.errorText = "";
|
||||
}
|
||||
if (!content) {
|
||||
noteContentInput.error = true;
|
||||
noteContentInput.errorText = "Content cannot be empty.";
|
||||
isValid = false;
|
||||
} else {
|
||||
noteContentInput.error = false;
|
||||
noteContentInput.errorText = "";
|
||||
}
|
||||
|
||||
if (!isValid) {
|
||||
console.log('Validation failed');
|
||||
return false;
|
||||
}
|
||||
|
||||
const now = new Date().toISOString();
|
||||
if (currentEditingId) {
|
||||
const noteIndex = notes.findIndex(n => n.id === currentEditingId);
|
||||
if (noteIndex > -1) {
|
||||
notes[noteIndex].title = title;
|
||||
notes[noteIndex].content = content;
|
||||
notes[noteIndex].lastModified = now;
|
||||
console.log('Updated existing note at index', noteIndex);
|
||||
}
|
||||
} else {
|
||||
const newNote = {
|
||||
id: Date.now().toString(),
|
||||
title,
|
||||
content,
|
||||
createdAt: now,
|
||||
lastModified: now
|
||||
};
|
||||
notes.push(newNote);
|
||||
console.log('Added new note:', newNote);
|
||||
}
|
||||
|
||||
// Close dialog, save notes and update UI
|
||||
noteDialog.open = false;
|
||||
saveNotes();
|
||||
renderNotes();
|
||||
|
||||
// Reset for next time
|
||||
currentEditingId = null;
|
||||
noteForm.reset();
|
||||
noteTitleInput.error = false;
|
||||
noteTitleInput.errorText = "";
|
||||
noteContentInput.error = false;
|
||||
noteContentInput.errorText = "";
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Handle dialog close event (just for logging/cleanup)
|
||||
function handleDialogClose(event) {
|
||||
console.log('Note dialog closed with action:', event?.detail?.action);
|
||||
|
||||
// Reset state regardless of how dialog was closed
|
||||
currentEditingId = null;
|
||||
if (noteForm) noteForm.reset();
|
||||
if (noteTitleInput) {
|
||||
noteTitleInput.error = false;
|
||||
noteTitleInput.errorText = "";
|
||||
}
|
||||
if (noteContentInput) {
|
||||
noteContentInput.error = false;
|
||||
noteContentInput.errorText = "";
|
||||
}
|
||||
}
|
||||
|
||||
function openDeleteDialog(id) {
|
||||
if (!confirmDeleteDialog) {
|
||||
console.error('Confirm delete dialog not found');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('Opening delete confirmation dialog for note ID:', id);
|
||||
noteToDeleteId = id;
|
||||
confirmDeleteDialog.open = true;
|
||||
}
|
||||
|
||||
function confirmDelete() {
|
||||
if (noteToDeleteId) {
|
||||
console.log('Deleting note with ID:', noteToDeleteId);
|
||||
notes = notes.filter(note => note.id !== noteToDeleteId);
|
||||
saveNotes();
|
||||
renderNotes();
|
||||
}
|
||||
|
||||
// Close dialog and reset state
|
||||
confirmDeleteDialog.open = false;
|
||||
noteToDeleteId = null;
|
||||
}
|
||||
|
||||
function handleDeleteDialogClose() {
|
||||
// Just reset state when dialog is closed
|
||||
console.log('Delete dialog closed');
|
||||
noteToDeleteId = null;
|
||||
}
|
||||
|
||||
// --- Event Listeners ---
|
||||
if (addNoteFab) {
|
||||
addNoteFab.addEventListener('click', () => openNoteDialog());
|
||||
console.log('Add note FAB event listener attached');
|
||||
} else {
|
||||
console.error('Add note FAB not found');
|
||||
}
|
||||
|
||||
// Dialog event listeners
|
||||
if (noteDialog) {
|
||||
noteDialog.addEventListener('closed', handleDialogClose);
|
||||
console.log('Note dialog event listener attached');
|
||||
} else {
|
||||
console.error('Note dialog not found');
|
||||
}
|
||||
|
||||
// Button event listeners
|
||||
const saveNoteBtn = document.getElementById('saveNoteBtn');
|
||||
if (saveNoteBtn) {
|
||||
saveNoteBtn.addEventListener('click', saveNote);
|
||||
console.log('Save note button event listener attached');
|
||||
} else {
|
||||
console.error('Save note button not found');
|
||||
}
|
||||
|
||||
const cancelNoteBtn = document.getElementById('cancelNoteBtn');
|
||||
if (cancelNoteBtn) {
|
||||
cancelNoteBtn.addEventListener('click', () => {
|
||||
noteDialog.open = false;
|
||||
});
|
||||
console.log('Cancel note button event listener attached');
|
||||
} else {
|
||||
console.error('Cancel note button not found');
|
||||
}
|
||||
// Delete dialog button listeners
|
||||
const confirmDeleteBtn = document.getElementById('confirmDeleteBtn');
|
||||
if (confirmDeleteBtn) {
|
||||
confirmDeleteBtn.addEventListener('click', confirmDelete);
|
||||
console.log('Confirm delete button event listener attached');
|
||||
} else {
|
||||
console.error('Confirm delete button not found');
|
||||
}
|
||||
|
||||
const cancelDeleteBtn = document.getElementById('cancelDeleteBtn');
|
||||
if (cancelDeleteBtn) {
|
||||
cancelDeleteBtn.addEventListener('click', () => {
|
||||
confirmDeleteDialog.open = false;
|
||||
noteToDeleteId = null;
|
||||
});
|
||||
console.log('Cancel delete button event listener attached');
|
||||
} else {
|
||||
console.error('Cancel delete button not found');
|
||||
}
|
||||
|
||||
if (confirmDeleteDialog) {
|
||||
confirmDeleteDialog.addEventListener('closed', handleDeleteDialogClose);
|
||||
console.log('Confirm delete dialog event listener attached');
|
||||
} else {
|
||||
console.error('Confirm delete dialog not found');
|
||||
}
|
||||
|
||||
// --- Initial Load ---
|
||||
loadInitialTheme();
|
||||
loadNotes();
|
||||
|
||||
// Show body once components are fully initialized
|
||||
document.body.classList.add('loaded');
|
||||
console.log('MNotes app initialized successfully');
|
||||
}
|
||||
|
||||
// Start initialization when DOM is loaded
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
console.log('DOM content loaded, initializing app...');
|
||||
|
||||
// Set a base theme class before components load
|
||||
document.body.classList.add('light-theme');
|
||||
|
||||
// Give a longer delay for Web Components to register
|
||||
setTimeout(initApp, 200);
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
Loading…
Add table
Add a link
Reference in a new issue