document.addEventListener('DOMContentLoaded', function() { console.log('DOM fully loaded and parsed.'); const paletteSelector = document.getElementById('palette-selector'); const newPaletteButton = document.getElementById('new-palette'); const newPaletteForm = document.getElementById('new-palette-form'); const createPaletteForm = document.getElementById('create-palette-form'); const addColorForm = document.getElementById('add-color-form'); const createColorForm = document.getElementById('create-color-form'); const colorEditorsDiv = document.getElementById('color-editors'); const addColorButton = document.getElementById('add-color'); const savePaletteButton = document.getElementById('save-palette'); const exportPaletteButton = document.getElementById('export-palette'); const importPaletteButton = document.getElementById('import-palette'); const importFileInput = document.getElementById('import-file'); const renamePaletteButton = document.getElementById('rename-palette'); const renamePaletteNameInput = document.getElementById('rename-palette-name'); const deletePaletteButton = document.getElementById('delete-palette'); const deleteModal = new bootstrap.Modal(document.getElementById('deleteModal'), {}); const confirmDeleteCheckbox = document.getElementById('confirmDeleteCheckbox'); const confirmDeleteButton = document.getElementById('confirmDeleteButton'); // CSRF token const csrfToken = document.querySelector('meta[name="csrf-token"]')?.getAttribute('content'); // Logging element states console.log('paletteSelector:', paletteSelector); console.log('newPaletteButton:', newPaletteButton); console.log('newPaletteForm:', newPaletteForm); console.log('createPaletteForm:', createPaletteForm); console.log('addColorForm:', addColorForm); console.log('createColorForm:', createColorForm); console.log('colorEditorsDiv:', colorEditorsDiv); console.log('addColorButton:', addColorButton); console.log('savePaletteButton:', savePaletteButton); console.log('deletePaletteButton:', deletePaletteButton); console.log('csrfToken:', csrfToken); if (!paletteSelector || !newPaletteButton || !newPaletteForm || !createPaletteForm || !addColorForm || !createColorForm || !colorEditorsDiv || !addColorButton || !savePaletteButton || !exportPaletteButton || !importPaletteButton || !importFileInput || !renamePaletteButton || !renamePaletteNameInput || !deletePaletteButton) { console.error('Missing required elements on the page.'); return; } newPaletteButton.addEventListener('click', function() { newPaletteForm.style.display = 'block'; }); createPaletteForm.addEventListener('submit', function(event) { event.preventDefault(); const formData = new FormData(createPaletteForm); console.log('Creating new palette with data:', formData); fetch('/palette-editor', { method: 'POST', body: formData, headers: { 'X-CSRF-TOKEN': csrfToken } }) .then(response => response.json()) .then(data => { console.log('Palette created:', data); fetchPalettes().then(() => { const newOption = document.createElement('option'); newOption.value = data.id; newOption.text = data.name; paletteSelector.add(newOption); paletteSelector.value = data.id; loadPaletteColors(data.id); }); newPaletteForm.style.display = 'none'; createPaletteForm.reset(); }) .catch(error => { console.error('Error creating palette:', error); }); }); paletteSelector.addEventListener('change', function() { const paletteId = paletteSelector.value; console.log('Palette selected:', paletteId); if (paletteId) { loadPaletteColors(paletteId); checkPaletteRestrictions(); } else { addColorForm.style.display = 'none'; colorEditorsDiv.innerHTML = ''; } }); addColorButton.addEventListener('click', function() { addColorEditor(); }); savePaletteButton.addEventListener('click', function() { const paletteId = createColorForm.getAttribute('data-palette-id'); const colorEditors = document.querySelectorAll('.color-editor'); const colorUpdates = []; colorEditors.forEach(editor => { const colorId = editor.getAttribute('data-color-id'); const colorName = editor.querySelector('.color-name').value; const colorHex = editor.querySelector('.color-hex-input').value; colorUpdates.push({ colorId, colorName, colorHex }); }); console.log('Saving palette with ID:', paletteId); colorUpdates.forEach(({colorId, colorName, colorHex}) => { console.log(`Saving color: ${colorName} (${colorHex}) with ID: ${colorId}`); if (colorId) { // Update existing color fetch(`/palette-editor/${paletteId}/colors/${colorId}`, { method: 'PUT', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': csrfToken }, body: JSON.stringify({ name: colorName, hex_value: colorHex }) }) .then(response => response.json()) .then(data => { console.log('Color updated:', data); }) .catch(error => { console.error('Error updating color:', error); }); } else { // Add new color fetch(`/palette-editor/${paletteId}/colors`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': csrfToken }, body: JSON.stringify({ name: colorName, hex_value: colorHex }) }) .then(response => response.json()) .then(data => { console.log('Color added:', data); editor.setAttribute('data-color-id', data.id); }) .catch(error => { console.error('Error adding color:', error); }); } }); }); exportPaletteButton.addEventListener('click', function() { const paletteId = paletteSelector.value; console.log('Exporting palette with ID:', paletteId); if (paletteId) { fetch(`/palette-editor/${paletteId}/export`) .then(response => { if (!response.ok) { throw new Error('Network response was not ok'); } return response.blob(); }) .then(blob => { const url = window.URL.createObjectURL(blob); const a = document.createElement('a'); a.style.display = 'none'; a.href = url; a.download = `${paletteSelector.options[paletteSelector.selectedIndex].text}.pal`; document.body.appendChild(a); a.click(); window.URL.revokeObjectURL(url); }) .catch(error => { console.error('Error exporting palette:', error); }); } else { alert('Please select a palette to export.'); } }); importPaletteButton.addEventListener('click', function() { importFileInput.click(); }); importFileInput.addEventListener('change', function(event) { const file = event.target.files[0]; if (file) { const formData = new FormData(); formData.append('file', file); console.log('Importing palette from file:', file.name); fetch('/palette-editor/import', { method: 'POST', body: formData, headers: { 'X-CSRF-TOKEN': csrfToken } }) .then(response => response.json()) .then(data => { console.log('Palette imported successfully', data); const newOption = document.createElement('option'); newOption.value = data.palette.id; newOption.text = data.palette.name; paletteSelector.add(newOption); paletteSelector.value = data.palette.id; loadPaletteColors(data.palette.id); }) .catch(error => { console.error('Error importing palette:', error); }); } }); renamePaletteButton.addEventListener('click', function() { const paletteId = paletteSelector.value; const newName = renamePaletteNameInput.value.trim(); console.log('Renaming palette ID:', paletteId, 'to:', newName); if (!paletteId) { alert('Please select a palette to rename.'); return; } if (!newName) { alert('Please enter a new name for the palette.'); return; } fetch(`/palette-editor/${paletteId}/rename`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': csrfToken }, body: JSON.stringify({ name: newName }) }) .then(response => { if (!response.ok) { throw new Error('Network response was not ok'); } return response.json(); }) .then(data => { console.log('Palette renamed:', data); fetchPalettes().then(() => { const option = Array.from(paletteSelector.options).find(option => option.value == paletteId); if (option) { option.text = newName; paletteSelector.value = paletteId; } loadPaletteColors(paletteId); }); }) .catch(error => { console.error('Error renaming palette:', error); }); }); deletePaletteButton.addEventListener('click', function() { const paletteId = paletteSelector.value; console.log('Preparing to delete palette ID:', paletteId); if (!paletteId) { alert('Please select a palette to delete.'); return; } // Show modal deleteModal.show(); }); confirmDeleteCheckbox.addEventListener('change', function() { confirmDeleteButton.disabled = !confirmDeleteCheckbox.checked; }); confirmDeleteButton.addEventListener('click', function() { const paletteId = paletteSelector.value; console.log('Deleting palette with ID:', paletteId); if (paletteId && confirmDeleteCheckbox.checked) { fetch(`/palette-editor/${paletteId}`, { method: 'DELETE', headers: { 'X-CSRF-TOKEN': csrfToken } }) .then(response => response.json()) .then(data => { console.log('Palette deleted:', data); fetchPalettes().then(() => { const option = Array.from(paletteSelector.options).find(option => option.value == paletteId); if (option) { paletteSelector.removeChild(option); } const defaultPaletteOption = Array.from(paletteSelector.options).find(option => option.text === 'default-colors'); if (defaultPaletteOption) { defaultPaletteOption.selected = true; loadPaletteColors(defaultPaletteOption.value); } else { paletteSelector.value = ''; colorEditorsDiv.innerHTML = ''; } }); deleteModal.hide(); }) .catch(error => { console.error('Error deleting palette:', error); }); } }); function loadPaletteColors(paletteId) { console.log('Loading colors for palette ID:', paletteId); fetch(`/palette-editor/${paletteId}/colors`) .then(response => response.json()) .then(data => { console.log('Loaded palette colors:', data); colorEditorsDiv.innerHTML = ''; data.forEach(color => { addColorEditor(color.id, color.name, color.hex_value); }); addColorForm.style.display = 'block'; createColorForm.setAttribute('data-palette-id', paletteId); }) .catch(error => { console.error('Error loading palette colors:', error); }); } function addColorEditor(colorId = '', colorName = '', colorHex = '#ffffff') { console.log(`Adding color editor for color: ${colorName} (${colorHex}) with ID: ${colorId}`); const editor = document.createElement('div'); editor.className = 'color-editor col-md-2 mb-3'; editor.setAttribute('data-color-id', colorId); editor.innerHTML = `
`; colorEditorsDiv.appendChild(editor); const deleteButton = editor.querySelector('.delete-color'); deleteButton.addEventListener('click', function() { const paletteId = createColorForm.getAttribute('data-palette-id'); if (paletteId === '1') { alert('Cannot delete colors from the default-colors palette.'); return; } console.log('Deleting color ID:', colorId, 'from palette ID:', paletteId); if (colorId) { fetch(`/palette-editor/${paletteId}/colors/${colorId}`, { method: 'DELETE', headers: { 'X-CSRF-TOKEN': csrfToken } }) .then(response => response.json()) .then(data => { console.log('Color deleted:', data.message); colorEditorsDiv.removeChild(editor); }) .catch(error => { console.error('Error deleting color:', error); }); } else { colorEditorsDiv.removeChild(editor); } }); const pickr = Pickr.create({ el: editor.querySelector('.color-picker'), theme: 'classic', // or 'monolith', or 'nano' default: colorHex, components: { preview: true, opacity: false, hue: true, interaction: { hex: true, input: true, clear: true, save: true } } }); pickr.on('save', (color, instance) => { editor.querySelector('.color-hex-input').value = color.toHEXA().toString(); pickr.hide(); }); pickr.on('clear', instance => { editor.querySelector('.color-hex-input').value = ''; }); } function fetchPalettes() { console.log('Fetching palettes from the server'); return fetch('/palette-editor') .then(response => response.json()) .then(data => { console.log('Fetched palettes:', data); paletteSelector.innerHTML = ''; data.forEach(palette => { const option = document.createElement('option'); option.value = palette.id; option.text = palette.name; paletteSelector.add(option); }); }) .catch(error => { console.error('Error fetching palettes:', error); }); } function checkPaletteRestrictions() { const paletteId = paletteSelector.value; const isDefaultPalette = paletteId === '1'; console.log('Checking restrictions for palette ID:', paletteId, 'isDefaultPalette:', isDefaultPalette); deletePaletteButton.disabled = isDefaultPalette; addColorButton.disabled = isDefaultPalette; savePaletteButton.disabled = isDefaultPalette; if (isDefaultPalette) { document.querySelectorAll('.delete-color').forEach(button => { button.disabled = true; }); } else { document.querySelectorAll('.delete-color').forEach(button => { button.disabled = false; }); } } // Load default colors on page load window.onload = function() { console.log('Page loaded, selecting default palette if available'); const defaultPaletteOption = Array.from(paletteSelector.options).find(option => option.text === 'default-colors'); if (defaultPaletteOption) { defaultPaletteOption.selected = true; loadPaletteColors(defaultPaletteOption.value); } }; });