diff --git a/beango/js/beango.js b/beango/js/beango.js
index bdd060f..cc8114b 100644
--- a/beango/js/beango.js
+++ b/beango/js/beango.js
@@ -50,6 +50,13 @@ const LS_MARKED_CELL_OUTLINE_OPACITY = 'beango_markedCellOutlineOpacity';
const LS_MARKED_CELL_OUTLINE_WIDTH = 'beango_markedCellOutlineWidth';
// --- Default Values ---
+const DEFAULT_SAMPLE_ITEMS = [
+ "Sample Item 1", "Sample Item 2", "Sample Item 3", "Sample Item 4", "Sample Item 5",
+ "Sample Item 6", "Sample Item 7", "Free Space", "Sample Item 9", "Sample Item 10",
+ "Sample Item 11", "Sample Item 12", "Sample Item 13", "Sample Item 14", "Sample Item 15",
+ "Sample Item 16", "Sample Item 17", "Sample Item 18", "Sample Item 19", "Sample Item 20",
+ "Sample Item 21", "Sample Item 22", "Sample Item 23", "Sample Item 24", "Sample Item 25"
+];
const DEFAULT_SOLID_COLOR = '#ff7e5f'; // Default to first color of gradient
const DEFAULT_SOLID_COLOR_OPACITY = 100; // New
const DEFAULT_GRADIENT_COLOR_1 = '#ff7e5f'; // From main page gradient
@@ -161,6 +168,39 @@ function hexToRgba(hex, opacityPercent = 100) {
return `rgba(${r}, ${g}, ${b}, ${opacity})`;
}
+// --- Event Listener Helper Functions --- START
+
+// Helper function for standard input/select elements
+function setupInputListener(elementId, eventType, saveFn, refreshFn) {
+ const element = document.getElementById(elementId);
+ if (element) {
+ element.addEventListener(eventType, () => {
+ if (saveFn) saveFn();
+ if (refreshFn) refreshFn();
+ });
+ } else {
+ console.warn(`Element with ID ${elementId} not found for listener setup.`);
+ }
+}
+
+// Helper function for opacity sliders with value display
+function setupOpacitySliderListener(sliderId, valueSpanId, saveFn, refreshFn) {
+ const slider = document.getElementById(sliderId);
+ const valueSpan = document.getElementById(valueSpanId);
+ if (slider) {
+ slider.addEventListener('input', (e) => {
+ if (valueSpan) valueSpan.textContent = e.target.value;
+ if (saveFn) saveFn();
+ if (refreshFn) refreshFn();
+ });
+ } else {
+ console.warn(`Element with ID ${sliderId} not found for listener setup.`);
+ }
+}
+
+// --- Event Listener Helper Functions --- END
+
+
// --- Functions ---
// --- Function to set the HTML background (solid or gradient) ---
@@ -957,56 +997,7 @@ function clearSearch() {
});
}
-// --- Load State on Page Load ---
-function loadFromLocalStorage() {
- const savedSize = localStorage.getItem(LS_BOARD_SIZE) || "5"; // Default to 5
- const savedItemsText = localStorage.getItem(LS_CELL_ITEMS);
- const savedDisplayedItems = localStorage.getItem(LS_DISPLAYED_ITEMS);
- const savedMarkedIndices = localStorage.getItem(LS_MARKED_INDICES);
- const configIsOpen = localStorage.getItem(LS_CONFIG_OPEN) === "true";
- const savedOriginalItemsText = localStorage.getItem(LS_ORIGINAL_ITEMS);
- // Load header text, applying default ONLY if key is missing
- let savedHeaderText = localStorage.getItem(LS_HEADER_TEXT);
- if (savedHeaderText === null) { // Check if key exists
- savedHeaderText = DEFAULT_HEADER_TEXT; // Apply default only if key missing
- }
- const savedHeaderImageUrl = localStorage.getItem(LS_HEADER_IMAGE_URL) || DEFAULT_HEADER_IMAGE_URL;
- let savedHeaderTextColor = localStorage.getItem(LS_HEADER_TEXT_COLOR);
- if (savedHeaderTextColor === null) {
- savedHeaderTextColor = DEFAULT_HEADER_TEXT_COLOR;
- }
- const savedHeaderTextOpacity = localStorage.getItem(LS_HEADER_TEXT_COLOR_OPACITY) || DEFAULT_HEADER_TEXT_COLOR_OPACITY;
- const savedHeaderBgColor = localStorage.getItem(LS_HEADER_BG_COLOR) || DEFAULT_HEADER_BG_COLOR;
- const savedHeaderBgOpacity = localStorage.getItem(LS_HEADER_BG_OPACITY) || DEFAULT_HEADER_BG_OPACITY;
- const savedMarkedColor = localStorage.getItem(LS_MARKED_COLOR) || DEFAULT_MARKED_COLOR;
- const savedMarkedColorOpacity = localStorage.getItem(LS_MARKED_COLOR_OPACITY) || DEFAULT_MARKED_COLOR_OPACITY;
- const savedMarkedImageUrl = localStorage.getItem(LS_MARKED_IMAGE_URL) || DEFAULT_MARKED_IMAGE_URL;
- const savedMarkedImageOpacity = localStorage.getItem(LS_MARKED_IMAGE_OPACITY) || DEFAULT_MARKED_IMAGE_OPACITY;
- console.log(`LOAD: LS_MARKED_IMAGE_OPACITY = ${localStorage.getItem(LS_MARKED_IMAGE_OPACITY)}, using: ${savedMarkedImageOpacity}`); // DEBUG LOG
- const savedCellBorderColor = localStorage.getItem(LS_CELL_BORDER_COLOR) || DEFAULT_CELL_BORDER_COLOR;
- const savedCellBorderOpacity = localStorage.getItem(LS_CELL_BORDER_OPACITY) || DEFAULT_CELL_BORDER_OPACITY;
- const savedCellBgColor = localStorage.getItem(LS_CELL_BG_COLOR) || DEFAULT_CELL_BG_COLOR;
- const savedCellBgOpacity = localStorage.getItem(LS_CELL_BG_OPACITY) || DEFAULT_CELL_BG_OPACITY;
- const savedCellBgImageUrl = localStorage.getItem(LS_CELL_BG_IMAGE_URL) || DEFAULT_CELL_BG_IMAGE_URL;
- const savedCellBgImageOpacity = localStorage.getItem(LS_CELL_BG_IMAGE_OPACITY) || DEFAULT_CELL_BG_IMAGE_OPACITY;
- console.log(`LOAD: LS_CELL_BG_IMAGE_OPACITY = ${localStorage.getItem(LS_CELL_BG_IMAGE_OPACITY)}, using: ${savedCellBgImageOpacity}`); // DEBUG LOG
- const savedCellTextColor = localStorage.getItem(LS_CELL_TEXT_COLOR) || DEFAULT_CELL_TEXT_COLOR;
- const savedCellTextOpacity = localStorage.getItem(LS_CELL_TEXT_OPACITY) || DEFAULT_CELL_TEXT_OPACITY;
- const savedCellOutlineColor = localStorage.getItem(LS_CELL_OUTLINE_COLOR) || DEFAULT_CELL_OUTLINE_COLOR;
- const savedCellOutlineOpacity = localStorage.getItem(LS_CELL_OUTLINE_OPACITY) || DEFAULT_CELL_OUTLINE_OPACITY;
- const savedCellOutlineWidth = localStorage.getItem(LS_CELL_OUTLINE_WIDTH) || DEFAULT_CELL_OUTLINE_WIDTH;
- const savedMarkedBorderColor = localStorage.getItem(LS_MARKED_BORDER_COLOR) || DEFAULT_MARKED_BORDER_COLOR;
- const savedMarkedBorderOpacity = localStorage.getItem(LS_MARKED_BORDER_OPACITY) || DEFAULT_MARKED_BORDER_OPACITY;
- const savedMarkedCellTextColor = localStorage.getItem(LS_MARKED_CELL_TEXT_COLOR) || DEFAULT_MARKED_CELL_TEXT_COLOR;
- const savedMarkedCellTextOpacity = localStorage.getItem(LS_MARKED_CELL_TEXT_OPACITY) || DEFAULT_MARKED_CELL_TEXT_OPACITY;
- const savedMarkedCellOutlineColor = localStorage.getItem(LS_MARKED_CELL_OUTLINE_COLOR) || DEFAULT_MARKED_CELL_OUTLINE_COLOR;
- const savedMarkedCellOutlineOpacity = localStorage.getItem(LS_MARKED_CELL_OUTLINE_OPACITY) || DEFAULT_MARKED_CELL_OUTLINE_OPACITY;
- const savedMarkedCellOutlineWidth = localStorage.getItem(LS_MARKED_CELL_OUTLINE_WIDTH) || DEFAULT_MARKED_CELL_OUTLINE_WIDTH;
- const savedBoardBgColor = localStorage.getItem(LS_BOARD_BG_COLOR) || DEFAULT_BOARD_BG_COLOR;
- const savedBoardBgColorOpacity = localStorage.getItem(LS_BOARD_BG_COLOR_OPACITY) || DEFAULT_BOARD_BG_COLOR_OPACITY;
- const savedBoardBgImageUrl = localStorage.getItem(LS_BOARD_BG_IMAGE_URL) || DEFAULT_BOARD_BG_IMAGE_URL;
-
- // Restore Config Pane State
+function loadPaneState(configIsOpen) {
const pane = document.getElementById('config-pane');
if (configIsOpen) {
pane.classList.remove('config-pane-closed');
@@ -1015,55 +1006,95 @@ function loadFromLocalStorage() {
pane.classList.remove('config-pane-open');
pane.classList.add('config-pane-closed');
}
+}
- // Restore Config Inputs
- const size = parseInt(savedSize, 10); // Parse size here
- document.getElementById('board-size').value = savedSize;
+function generateDefaultBoard() {
+ // --- No saved board state, GENERATE DEFAULT board ---
+ console.log('No saved board state found. Generating default 5x5 board.');
+ const defaultSize = 5;
+ currentItems = [...DEFAULT_SAMPLE_ITEMS]; // Set global variable
+ displayedItems = shuffleArray([...DEFAULT_SAMPLE_ITEMS]); // Set global variable
+ const originalItems = [...DEFAULT_SAMPLE_ITEMS]; // For text area
- // Restore Board only if essential data exists
- if (savedDisplayedItems) {
- try {
- displayedItems = JSON.parse(savedDisplayedItems); // Restore displayed items array
- // *** ADDED: Restore currentItems as well ***
- if (savedItemsText) {
- try {
- currentItems = JSON.parse(savedItemsText);
- if (!Array.isArray(currentItems)) {
- console.warn('Loaded LS_CELL_ITEMS was not an array, resetting.');
- currentItems = [];
- }
- } catch (e) {
- showNotification('Error parsing saved cell item pool (LS_CELL_ITEMS). Board may not randomize correctly.', 'warning');
- currentItems = []; // Reset on parse error
- }
- } else {
- // If LS_CELL_ITEMS doesn't exist but LS_DISPLAYED_ITEMS does, it's an inconsistent state.
- // We could try to reconstruct currentItems from displayedItems, but it might lack padding/slicing info.
- // For now, log a warning and reset currentItems.
- console.warn('Inconsistent state: LS_DISPLAYED_ITEMS exists but LS_CELL_ITEMS is missing. Randomization might fail.');
- currentItems = [];
- }
- // *** END ADDED section ***
- } catch (e) {
- showNotification('Error parsing saved board state. Please generate again.', 'error');
- localStorage.removeItem(LS_DISPLAYED_ITEMS);
- localStorage.removeItem(LS_MARKED_INDICES);
- displayedItems = [];
- document.getElementById('bingo-board').innerHTML = '
Error loading board. Generate New.
';
- return; // Stop board restore
+ const board = document.getElementById('bingo-board');
+ board.innerHTML = ''; // Clear placeholder or previous error message
+ board.style.gridTemplateColumns = `repeat(${defaultSize}, minmax(0, 1fr))`;
+
+ // Update UI inputs to reflect default
+ document.getElementById('board-size').value = defaultSize;
+ document.getElementById('cell-contents').value = originalItems.join('\n');
+
+ displayedItems.forEach((item, index) => {
+ const cell = document.createElement("div");
+ cell.classList.add("bingo-cell", "cursor-pointer");
+ cell.dataset.index = index;
+ cell.onclick = () => selectCell(cell);
+
+ const textSpan = document.createElement("span");
+ textSpan.classList.add("bingo-cell-text");
+ textSpan.textContent = item;
+ cell.appendChild(textSpan);
+
+ applyCellStyle(cell); // Apply default styles
+
+ // No marked cells on default board
+ board.appendChild(cell);
+ });
+
+ // Save this default state immediately
+ saveBoardState();
+ showNotification('Generated default 5x5 board.', 'info');
+ // --- End GENERATE DEFAULT board ---
+}
+
+function generateBoardFromSavedState(savedDisplayedItems, savedItemsText, savedMarkedIndices, size) {
+
+ console.log("Found saved board state. Loading..."); // Log loading source
+ try {
+ displayedItems = JSON.parse(savedDisplayedItems); // Restore displayed items array
+ // *** ADDED: Restore currentItems as well ***
+ if (savedItemsText) {
+ try {
+ currentItems = JSON.parse(savedItemsText);
+ if (!Array.isArray(currentItems)) {
+ console.warn('Loaded LS_CELL_ITEMS was not an array, resetting.');
+ currentItems = [];
+ }
+ } catch (e) {
+ showNotification('Error parsing saved cell item pool (LS_CELL_ITEMS). Board may not randomize correctly.', 'warning');
+ currentItems = []; // Reset on parse error
+ }
+ } else {
+ // If LS_CELL_ITEMS doesn't exist but LS_DISPLAYED_ITEMS does, it's an inconsistent state.
+ console.warn('Inconsistent state: LS_DISPLAYED_ITEMS exists but LS_CELL_ITEMS is missing. Randomization might fail.');
+ currentItems = [];
}
+ // *** END ADDED section ***
+ } catch (e) {
+ showNotification('Error parsing saved board state. Please generate again.', 'error');
+ localStorage.removeItem(LS_DISPLAYED_ITEMS);
+ localStorage.removeItem(LS_MARKED_INDICES);
+ localStorage.removeItem(LS_CELL_ITEMS); // Also remove potentially corrupted items
+ displayedItems = [];
+ currentItems = []; // Also reset currentItems
+ document.getElementById('bingo-board').innerHTML = 'Error loading board. Generate New.
';
+ // Don't return yet, let style loading proceed with defaults
+ }
- const requiredItems = size * size;
-
- // Check if the loaded data is consistent
- if (!Array.isArray(displayedItems) || displayedItems.length !== requiredItems) {
- showNotification("Saved board data mismatch. Please generate again.", 'warning');
- localStorage.removeItem(LS_DISPLAYED_ITEMS);
- localStorage.removeItem(LS_MARKED_INDICES);
- document.getElementById('bingo-board').innerHTML = 'Data Mismatch. Generate New.
';
- return; // Stop loading the board state
- }
+ const requiredItems = size * size;
+ // Check if the loaded data is consistent
+ if (!Array.isArray(displayedItems) || displayedItems.length !== requiredItems) {
+ showNotification("Saved board data mismatch. Please generate again.", 'warning');
+ localStorage.removeItem(LS_DISPLAYED_ITEMS);
+ localStorage.removeItem(LS_MARKED_INDICES);
+ localStorage.removeItem(LS_CELL_ITEMS);
+ displayedItems = [];
+ currentItems = [];
+ document.getElementById('bingo-board').innerHTML = 'Data Mismatch. Generate New.
';
+ // Don't return yet
+ } else {
+ // --- Populate board from SAVED state ---
const board = document.getElementById('bingo-board');
board.innerHTML = ''; // Clear placeholder
board.style.gridTemplateColumns = `repeat(${size}, minmax(0, 1fr))`;
@@ -1073,36 +1104,27 @@ function loadFromLocalStorage() {
displayedItems.forEach((item, index) => {
const cell = document.createElement("div");
cell.classList.add("bingo-cell", "cursor-pointer");
- // cell.textContent = item; // OLD WAY
- cell.dataset.index = index; // Ensure index is set for loading marks correctly
+ cell.dataset.index = index;
cell.onclick = () => selectCell(cell);
- // applyCellStyle(cell); // Apply default cell style first <-- MOVED DOWN
- // NEW: Create span for text content
const textSpan = document.createElement("span");
textSpan.classList.add("bingo-cell-text");
textSpan.textContent = item;
cell.appendChild(textSpan);
- applyCellStyle(cell); // <-- MOVED HERE: Apply styles AFTER text span exists
+ applyCellStyle(cell); // Apply default styles first
if (markedIndices.includes(index)) {
- cell.classList.add("marked"); // Apply saved mark using 'marked' class
- // Apply dynamic marked styles AFTER adding the class and default styles
- applyMarkedCellStyle(cell); // <-- RE-ADDED this call
+ cell.classList.add("marked");
+ applyMarkedCellStyle(cell); // Apply marked styles if needed
}
board.appendChild(cell);
});
- // equalizeCellSizes(); // <--- REMOVED FROM HERE
- } else {
- // If no saved board state, show the default message
- const board = document.getElementById('bingo-board');
- // Check if board div exists and has no children before adding message
- if (board && board.children.length === 0) {
- board.innerHTML = 'Generate a board using the config panel!
';
- }
}
+ // --- End populate board from SAVED state ---
+}
+function restoreBackgroundSettings() {
// --- Restore Background Settings ---
const savedBackgroundType = localStorage.getItem(LS_BACKGROUND_TYPE) || 'gradient'; // Default to gradient
const savedSolidColor = localStorage.getItem(LS_SOLID_COLOR) || DEFAULT_SOLID_COLOR;
@@ -1129,351 +1151,222 @@ function loadFromLocalStorage() {
toggleBackgroundControls();
setBackground();
// --- End Restore Background Settings ---
+}
- // --- Restore Header Settings ---
- document.getElementById('header-text-input').value = savedHeaderText;
- document.getElementById('header-image-url-input').value = savedHeaderImageUrl;
- document.getElementById('header-text-color-picker').value = savedHeaderTextColor;
- document.getElementById('header-text-color-opacity-slider').value = savedHeaderTextOpacity;
- if(document.getElementById('header-text-color-opacity-value')) document.getElementById('header-text-color-opacity-value').textContent = savedHeaderTextOpacity; // Update display span
+function restoreHeaderSettings(savedHeaderText, savedHeaderImageUrl, savedHeaderTextColor, savedHeaderTextOpacity, savedHeaderBgColor, savedHeaderBgOpacity) {
+ _restoreInputSetting('header-text-input', savedHeaderText);
+ _restoreInputSetting('header-image-url-input', savedHeaderImageUrl);
+ _restoreColorPickerSetting('header-text-color-picker', savedHeaderTextColor);
+ _restoreOpacitySetting('header-text-color-opacity-slider', 'header-text-color-opacity-value', savedHeaderTextOpacity);
// Restore header background inputs
- document.getElementById('header-bg-color-picker').value = savedHeaderBgColor;
- document.getElementById('header-bg-opacity-slider').value = savedHeaderBgOpacity;
- if(document.getElementById('header-bg-opacity-value')) document.getElementById('header-bg-opacity-value').textContent = savedHeaderBgOpacity;
+ _restoreColorPickerSetting('header-bg-color-picker', savedHeaderBgColor);
+ _restoreOpacitySetting('header-bg-opacity-slider', 'header-bg-opacity-value', savedHeaderBgOpacity);
+
applyHeaderBgStyle(); // Apply header background style
updateHeaderDisplay(); // Apply the loaded header content
- // --- End Restore Header Settings ---
+}
- // --- Restore Marked Style Settings ---
- document.getElementById('marked-color-picker').value = savedMarkedColor;
- document.getElementById('marked-color-opacity-slider').value = savedMarkedColorOpacity;
- if(document.getElementById('marked-color-opacity-value')) document.getElementById('marked-color-opacity-value').textContent = savedMarkedColorOpacity;
- document.getElementById('marked-image-url-input').value = savedMarkedImageUrl;
- const markedImageOpacitySlider = document.getElementById('marked-image-opacity-slider');
- const markedImageOpacityValueSpan = document.getElementById('marked-image-opacity-value');
- if (markedImageOpacitySlider) markedImageOpacitySlider.value = savedMarkedImageOpacity;
- if (markedImageOpacityValueSpan) markedImageOpacityValueSpan.textContent = savedMarkedImageOpacity;
+function restoreMarkedStyleSettings(savedMarkedColor, savedMarkedColorOpacity, savedMarkedImageUrl, savedMarkedImageOpacity, savedMarkedBorderColor, savedMarkedBorderOpacity, savedMarkedCellTextColor, savedMarkedCellTextOpacity, savedMarkedCellOutlineColor, savedMarkedCellOutlineOpacity, savedMarkedCellOutlineWidth) {
+ // Marked Color
+ _restoreColorPickerSetting('marked-color-picker', savedMarkedColor);
+ _restoreOpacitySetting('marked-color-opacity-slider', 'marked-color-opacity-value', savedMarkedColorOpacity);
- document.getElementById('marked-border-color-picker').value = savedMarkedBorderColor;
- const markedBorderOpacitySlider = document.getElementById('marked-border-opacity-slider');
- const markedBorderOpacityValueSpan = document.getElementById('marked-border-opacity-value');
- if (markedBorderOpacitySlider) markedBorderOpacitySlider.value = savedMarkedBorderOpacity;
- if (markedBorderOpacityValueSpan) markedBorderOpacityValueSpan.textContent = savedMarkedBorderOpacity;
+ // Marked Image
+ _restoreInputSetting('marked-image-url-input', savedMarkedImageUrl);
+ _restoreOpacitySetting('marked-image-opacity-slider', 'marked-image-opacity-value', savedMarkedImageOpacity);
- // Restore marked text styles
- document.getElementById('marked-cell-text-color-picker').value = savedMarkedCellTextColor;
- const markedCellTextOpacitySlider = document.getElementById('marked-cell-text-opacity-slider');
- const markedCellTextOpacityValueSpan = document.getElementById('marked-cell-text-opacity-value');
- if (markedCellTextOpacitySlider) markedCellTextOpacitySlider.value = savedMarkedCellTextOpacity;
- if (markedCellTextOpacityValueSpan) markedCellTextOpacityValueSpan.textContent = savedMarkedCellTextOpacity;
+ // Marked Border
+ _restoreColorPickerSetting('marked-border-color-picker', savedMarkedBorderColor);
+ _restoreOpacitySetting('marked-border-opacity-slider', 'marked-border-opacity-value', savedMarkedBorderOpacity);
- document.getElementById('marked-cell-outline-color-picker').value = savedMarkedCellOutlineColor;
- const markedCellOutlineOpacitySlider = document.getElementById('marked-cell-outline-opacity-slider');
- const markedCellOutlineOpacityValueSpan = document.getElementById('marked-cell-outline-opacity-value');
- if (markedCellOutlineOpacitySlider) markedCellOutlineOpacitySlider.value = savedMarkedCellOutlineOpacity;
- if (markedCellOutlineOpacityValueSpan) markedCellOutlineOpacityValueSpan.textContent = savedMarkedCellOutlineOpacity;
+ // Marked Text Color
+ _restoreColorPickerSetting('marked-cell-text-color-picker', savedMarkedCellTextColor);
+ _restoreOpacitySetting('marked-cell-text-opacity-slider', 'marked-cell-text-opacity-value', savedMarkedCellTextOpacity);
- document.getElementById('marked-cell-outline-width-input').value = savedMarkedCellOutlineWidth;
+ // Marked Text Outline
+ _restoreColorPickerSetting('marked-cell-outline-color-picker', savedMarkedCellOutlineColor);
+ _restoreOpacitySetting('marked-cell-outline-opacity-slider', 'marked-cell-outline-opacity-value', savedMarkedCellOutlineOpacity);
+ _restoreInputSetting('marked-cell-outline-width-input', savedMarkedCellOutlineWidth);
+}
- // refreshMarkedCellStyles(); // Apply the loaded marked styles <-- MOVED DOWN
- // --- End Restore Marked Style Settings ---
+// Helper function to restore opacity slider and value display
+function _restoreOpacitySetting(sliderId, valueSpanId, savedOpacityValue) {
+ const slider = document.getElementById(sliderId);
+ const valueSpan = document.getElementById(valueSpanId);
+ if (slider) {
+ slider.value = savedOpacityValue;
+ }
+ if (valueSpan) {
+ valueSpan.textContent = savedOpacityValue;
+ }
+}
- // --- Restore Default Cell Style Settings ---
- document.getElementById('cell-border-color-picker').value = savedCellBorderColor;
- const cellBorderOpacitySlider = document.getElementById('cell-border-opacity-slider');
- const cellBorderOpacityValueSpan = document.getElementById('cell-border-opacity-value');
- if (cellBorderOpacitySlider) cellBorderOpacitySlider.value = savedCellBorderOpacity;
- if (cellBorderOpacityValueSpan) cellBorderOpacityValueSpan.textContent = savedCellBorderOpacity;
+// Helper function to restore a color picker value
+function _restoreColorPickerSetting(pickerId, savedColorValue) {
+ const picker = document.getElementById(pickerId);
+ if (picker) {
+ picker.value = savedColorValue;
+ }
+}
- document.getElementById('cell-background-color-picker').value = savedCellBgColor;
- const cellBackgroundOpacitySlider = document.getElementById('cell-background-opacity-slider');
- const cellBackgroundOpacityValueSpan = document.getElementById('cell-background-opacity-value');
- if (cellBackgroundOpacitySlider) cellBackgroundOpacitySlider.value = savedCellBgOpacity;
- if (cellBackgroundOpacityValueSpan) cellBackgroundOpacityValueSpan.textContent = savedCellBgOpacity;
+// Helper function to restore a generic input value
+function _restoreInputSetting(inputId, savedValue) {
+ const input = document.getElementById(inputId);
+ if (input) {
+ input.value = savedValue;
+ }
+}
- document.getElementById('cell-background-image-url-input').value = savedCellBgImageUrl;
- const cellBackgroundImageOpacitySlider = document.getElementById('cell-background-image-opacity-slider');
- const cellBackgroundImageOpacityValueSpan = document.getElementById('cell-background-image-opacity-value');
- if (cellBackgroundImageOpacitySlider) cellBackgroundImageOpacitySlider.value = savedCellBgImageOpacity;
- if (cellBackgroundImageOpacityValueSpan) cellBackgroundImageOpacityValueSpan.textContent = savedCellBgImageOpacity;
+function restoreCellStyleSettings(savedCellBorderColor, savedCellBorderOpacity, savedCellBgColor, savedCellBgOpacity, savedCellBgImageUrl, savedCellBgImageOpacity, savedCellTextColor, savedCellTextOpacity, savedCellOutlineColor, savedCellOutlineOpacity, savedCellOutlineWidth) {
+ // Border
+ _restoreColorPickerSetting('cell-border-color-picker', savedCellBorderColor);
+ _restoreOpacitySetting('cell-border-opacity-slider', 'cell-border-opacity-value', savedCellBorderOpacity);
- // Restore text styles
- document.getElementById('cell-text-color-picker').value = savedCellTextColor;
- const cellTextOpacitySlider = document.getElementById('cell-text-opacity-slider');
- const cellTextOpacityValueSpan = document.getElementById('cell-text-opacity-value');
- if (cellTextOpacitySlider) cellTextOpacitySlider.value = savedCellTextOpacity;
- if (cellTextOpacityValueSpan) cellTextOpacityValueSpan.textContent = savedCellTextOpacity;
- document.getElementById('cell-outline-color-picker').value = savedCellOutlineColor;
- const cellOutlineOpacitySlider = document.getElementById('cell-outline-opacity-slider');
- const cellOutlineOpacityValueSpan = document.getElementById('cell-outline-opacity-value');
- if (cellOutlineOpacitySlider) cellOutlineOpacitySlider.value = savedCellOutlineOpacity;
- if (cellOutlineOpacityValueSpan) cellOutlineOpacityValueSpan.textContent = savedCellOutlineOpacity;
- document.getElementById('cell-outline-width-input').value = savedCellOutlineWidth;
+ // Background Color
+ _restoreColorPickerSetting('cell-background-color-picker', savedCellBgColor);
+ _restoreOpacitySetting('cell-background-opacity-slider', 'cell-background-opacity-value', savedCellBgOpacity);
- // Styles are applied during board creation loop above
- // --- End Restore Default Cell Style Settings ---
+ // Background Image
+ _restoreInputSetting('cell-background-image-url-input', savedCellBgImageUrl);
+ _restoreOpacitySetting('cell-background-image-opacity-slider', 'cell-background-image-opacity-value', savedCellBgImageOpacity);
- // --- Restore Board Background Settings ---
- document.getElementById('board-bg-color-picker').value = savedBoardBgColor;
- document.getElementById('board-bg-image-url-input').value = savedBoardBgImageUrl;
- document.getElementById('board-bg-color-opacity-slider').value = savedBoardBgColorOpacity;
- const boardBgOpacitySlider = document.getElementById('board-bg-color-opacity-slider');
- const boardBgOpacityValueSpan = document.getElementById('board-bg-color-opacity-value');
- if (boardBgOpacitySlider) boardBgOpacitySlider.value = savedBoardBgColorOpacity;
- if (boardBgOpacityValueSpan) boardBgOpacityValueSpan.textContent = savedBoardBgColorOpacity;
+ // Text Color
+ _restoreColorPickerSetting('cell-text-color-picker', savedCellTextColor);
+ _restoreOpacitySetting('cell-text-opacity-slider', 'cell-text-opacity-value', savedCellTextOpacity);
+
+ // Outline Color
+ _restoreColorPickerSetting('cell-outline-color-picker', savedCellOutlineColor);
+ _restoreOpacitySetting('cell-outline-opacity-slider', 'cell-outline-opacity-value', savedCellOutlineOpacity);
+
+ // Outline Width
+ _restoreInputSetting('cell-outline-width-input', savedCellOutlineWidth);
+}
+
+function restoreBoardBgSettings(savedBoardBgColor, savedBoardBgColorOpacity, savedBoardBgImageUrl) {
+ _restoreColorPickerSetting('board-bg-color-picker', savedBoardBgColor);
+ _restoreInputSetting('board-bg-image-url-input', savedBoardBgImageUrl);
+ _restoreOpacitySetting('board-bg-color-opacity-slider', 'board-bg-color-opacity-value', savedBoardBgColorOpacity);
applyBoardBgStyle(); // Apply loaded style
- // --- End Restore Board Background Settings ---
+}
- // Restore the textarea with the original user input if available
- if (savedOriginalItemsText) {
- try {
- const originalItems = JSON.parse(savedOriginalItemsText);
- document.getElementById('cell-contents').value = originalItems.join('\n');
- } catch (e) {
- showNotification('Error parsing saved original items.', 'error');
- localStorage.removeItem(LS_ORIGINAL_ITEMS);
- // Fallback to cell items if original fails
- if (savedItemsText) {
- try {
- document.getElementById('cell-contents').value = JSON.parse(savedItemsText).join('\n');
- } catch { /* ignore inner error */ }
+function restoreSavedItems(savedDisplayedItems, savedItemsText, savedOriginalItemsText) {
+ // Restore the textarea with the original user input if available (or fallback)
+ // Note: If default board was generated, textarea was already set above.
+ // This part primarily handles the case where board existed but original items might be missing.
+ if (savedDisplayedItems) { // Only run this textarea logic if we didn't just generate default
+ if (savedOriginalItemsText) {
+ try {
+ const originalItemsFromStorage = JSON.parse(savedOriginalItemsText);
+ // Only update textarea if it wasn't populated by default gen
+ if (document.getElementById('cell-contents').value === '') {
+ document.getElementById('cell-contents').value = originalItemsFromStorage.join('\n');
+ }
+ } catch (e) {
+ showNotification('Error parsing saved original items.', 'error');
+ localStorage.removeItem(LS_ORIGINAL_ITEMS);
+ // Fallback to cell items if original fails and textarea is empty
+ if (savedItemsText && document.getElementById('cell-contents').value === '') {
+ try {
+ document.getElementById('cell-contents').value = JSON.parse(savedItemsText).join('\n');
+ } catch { /* ignore inner error */ }
+ }
+ }
+ } else if (savedItemsText && document.getElementById('cell-contents').value === '') {
+ // If no original items saved, use the cell items as fallback for textarea
+ try {
+ document.getElementById('cell-contents').value = JSON.parse(savedItemsText).join('\n');
+ } catch (e) {
+ // Already handled loading currentItems above, just ensure textarea is cleared on error
+ document.getElementById('cell-contents').value = '';
}
}
- } else if (savedItemsText) {
- // If no original items saved, use the cell items as fallback for textarea
- try {
- document.getElementById('cell-contents').value = JSON.parse(savedItemsText).join('\n');
- } catch (e) {
- // Already handled loading currentItems above, just ensure textarea is cleared on error
- document.getElementById('cell-contents').value = '';
- }
+ }
+}
+
+// --- Load State on Page Load ---
+function loadFromLocalStorage() {
+ const savedSize = localStorage.getItem(LS_BOARD_SIZE); // Keep checking for size first
+ const savedItemsText = localStorage.getItem(LS_CELL_ITEMS);
+ const savedDisplayedItems = localStorage.getItem(LS_DISPLAYED_ITEMS);
+ const savedMarkedIndices = localStorage.getItem(LS_MARKED_INDICES);
+ const configIsOpen = localStorage.getItem(LS_CONFIG_OPEN) === "true";
+ const savedOriginalItemsText = localStorage.getItem(LS_ORIGINAL_ITEMS);
+ // Load header text, applying default ONLY if key is missing
+ let savedHeaderText = localStorage.getItem(LS_HEADER_TEXT);
+ if (savedHeaderText === null) { // Check if key exists
+ savedHeaderText = DEFAULT_HEADER_TEXT; // Apply default only if key missing
+ }
+ const savedHeaderImageUrl = localStorage.getItem(LS_HEADER_IMAGE_URL) || DEFAULT_HEADER_IMAGE_URL;
+ let savedHeaderTextColor = localStorage.getItem(LS_HEADER_TEXT_COLOR);
+ if (savedHeaderTextColor === null) {
+ savedHeaderTextColor = DEFAULT_HEADER_TEXT_COLOR;
+ }
+ const savedHeaderTextOpacity = localStorage.getItem(LS_HEADER_TEXT_COLOR_OPACITY) || DEFAULT_HEADER_TEXT_COLOR_OPACITY;
+ const savedHeaderBgColor = localStorage.getItem(LS_HEADER_BG_COLOR) || DEFAULT_HEADER_BG_COLOR;
+ const savedHeaderBgOpacity = localStorage.getItem(LS_HEADER_BG_OPACITY) || DEFAULT_HEADER_BG_OPACITY;
+ const savedMarkedColor = localStorage.getItem(LS_MARKED_COLOR) || DEFAULT_MARKED_COLOR;
+ const savedMarkedColorOpacity = localStorage.getItem(LS_MARKED_COLOR_OPACITY) || DEFAULT_MARKED_COLOR_OPACITY;
+ const savedMarkedImageUrl = localStorage.getItem(LS_MARKED_IMAGE_URL) || DEFAULT_MARKED_IMAGE_URL;
+ const savedMarkedImageOpacity = localStorage.getItem(LS_MARKED_IMAGE_OPACITY) || DEFAULT_MARKED_IMAGE_OPACITY;
+ const savedCellBorderColor = localStorage.getItem(LS_CELL_BORDER_COLOR) || DEFAULT_CELL_BORDER_COLOR;
+ const savedCellBorderOpacity = localStorage.getItem(LS_CELL_BORDER_OPACITY) || DEFAULT_CELL_BORDER_OPACITY;
+ const savedCellBgColor = localStorage.getItem(LS_CELL_BG_COLOR) || DEFAULT_CELL_BG_COLOR;
+ const savedCellBgOpacity = localStorage.getItem(LS_CELL_BG_OPACITY) || DEFAULT_CELL_BG_OPACITY;
+ const savedCellBgImageUrl = localStorage.getItem(LS_CELL_BG_IMAGE_URL) || DEFAULT_CELL_BG_IMAGE_URL;
+ const savedCellBgImageOpacity = localStorage.getItem(LS_CELL_BG_IMAGE_OPACITY) || DEFAULT_CELL_BG_IMAGE_OPACITY;
+ const savedCellTextColor = localStorage.getItem(LS_CELL_TEXT_COLOR) || DEFAULT_CELL_TEXT_COLOR;
+ const savedCellTextOpacity = localStorage.getItem(LS_CELL_TEXT_OPACITY) || DEFAULT_CELL_TEXT_OPACITY;
+ const savedCellOutlineColor = localStorage.getItem(LS_CELL_OUTLINE_COLOR) || DEFAULT_CELL_OUTLINE_COLOR;
+ const savedCellOutlineOpacity = localStorage.getItem(LS_CELL_OUTLINE_OPACITY) || DEFAULT_CELL_OUTLINE_OPACITY;
+ const savedCellOutlineWidth = localStorage.getItem(LS_CELL_OUTLINE_WIDTH) || DEFAULT_CELL_OUTLINE_WIDTH;
+ const savedMarkedBorderColor = localStorage.getItem(LS_MARKED_BORDER_COLOR) || DEFAULT_MARKED_BORDER_COLOR;
+ const savedMarkedBorderOpacity = localStorage.getItem(LS_MARKED_BORDER_OPACITY) || DEFAULT_MARKED_BORDER_OPACITY;
+ const savedMarkedCellTextColor = localStorage.getItem(LS_MARKED_CELL_TEXT_COLOR) || DEFAULT_MARKED_CELL_TEXT_COLOR;
+ const savedMarkedCellTextOpacity = localStorage.getItem(LS_MARKED_CELL_TEXT_OPACITY) || DEFAULT_MARKED_CELL_TEXT_OPACITY;
+ const savedMarkedCellOutlineColor = localStorage.getItem(LS_MARKED_CELL_OUTLINE_COLOR) || DEFAULT_MARKED_CELL_OUTLINE_COLOR;
+ const savedMarkedCellOutlineOpacity = localStorage.getItem(LS_MARKED_CELL_OUTLINE_OPACITY) || DEFAULT_MARKED_CELL_OUTLINE_OPACITY;
+ const savedMarkedCellOutlineWidth = localStorage.getItem(LS_MARKED_CELL_OUTLINE_WIDTH) || DEFAULT_MARKED_CELL_OUTLINE_WIDTH;
+ const savedBoardBgColor = localStorage.getItem(LS_BOARD_BG_COLOR) || DEFAULT_BOARD_BG_COLOR;
+ const savedBoardBgColorOpacity = localStorage.getItem(LS_BOARD_BG_COLOR_OPACITY) || DEFAULT_BOARD_BG_COLOR_OPACITY;
+ const savedBoardBgImageUrl = localStorage.getItem(LS_BOARD_BG_IMAGE_URL) || DEFAULT_BOARD_BG_IMAGE_URL;
+
+ // Restore Config Pane State
+ loadPaneState(configIsOpen);
+
+ // Determine board size (use saved, or default 5)
+ const size = parseInt(savedSize || "5", 10);
+ document.getElementById('board-size').value = size; // Update input regardless of board source
+
+ // Restore Board only if essential data exists
+ if (savedDisplayedItems) {
+ generateBoardFromSavedState(savedDisplayedItems, savedItemsText, savedMarkedIndices, size);
+ } else {
+ generateDefaultBoard();
}
- // Update container width based on loaded size - REMOVED
- // updateBoardContainerMaxWidth(size);
- // updateBoardContainerMaxWidth(size, '#board-header');
+ restoreBackgroundSettings();
- // --- Add Event Listeners for Default Cell Style Controls ---
- document.getElementById('cell-border-color-picker').addEventListener('input', () => {
- saveCellStyleSettings();
- refreshCellStyles(); // Update all non-marked cells
- });
- document.getElementById('cell-border-opacity-slider').addEventListener('input', (e) => {
- if(document.getElementById('cell-border-opacity-value')) document.getElementById('cell-border-opacity-value').textContent = e.target.value;
- saveCellStyleSettings();
- refreshCellStyles(); // Update all non-marked cells
- });
- document.getElementById('cell-background-color-picker').addEventListener('input', () => {
- saveCellStyleSettings();
- refreshCellStyles();
- });
- document.getElementById('cell-background-opacity-slider').addEventListener('input', (e) => {
- if(document.getElementById('cell-background-opacity-value')) document.getElementById('cell-background-opacity-value').textContent = e.target.value;
- saveCellStyleSettings();
- refreshCellStyles();
- });
- document.getElementById('cell-background-image-url-input').addEventListener('input', () => {
- saveCellStyleSettings();
- refreshCellStyles();
- });
+ restoreHeaderSettings(
+ savedHeaderText, savedHeaderImageUrl, savedHeaderTextColor, savedHeaderTextOpacity,
+ savedHeaderBgColor, savedHeaderBgOpacity
+ );
- // --- Add Event Listeners for Text Style Controls ---
- document.getElementById('cell-text-color-picker').addEventListener('input', () => {
- saveCellStyleSettings();
- refreshCellStyles();
- });
- document.getElementById('cell-text-opacity-slider').addEventListener('input', (e) => {
- if(document.getElementById('cell-text-opacity-value')) document.getElementById('cell-text-opacity-value').textContent = e.target.value;
- saveCellStyleSettings();
- refreshCellStyles();
- });
- document.getElementById('cell-outline-color-picker').addEventListener('input', () => {
- saveCellStyleSettings();
- refreshCellStyles();
- });
- document.getElementById('cell-outline-opacity-slider').addEventListener('input', (e) => {
- if(document.getElementById('cell-outline-opacity-value')) document.getElementById('cell-outline-opacity-value').textContent = e.target.value;
- saveCellStyleSettings();
- refreshCellStyles();
- });
- document.getElementById('cell-outline-width-input').addEventListener('input', () => {
- saveCellStyleSettings();
- refreshCellStyles();
- });
+ restoreMarkedStyleSettings(
+ savedMarkedColor, savedMarkedColorOpacity, savedMarkedImageUrl, savedMarkedImageOpacity,
+ savedMarkedBorderColor, savedMarkedBorderOpacity, savedMarkedCellTextColor, savedMarkedCellTextOpacity,
+ savedMarkedCellOutlineColor, savedMarkedCellOutlineOpacity, savedMarkedCellOutlineWidth
+ );
- // --- Add Event Listeners for Board Background Controls ---
- document.getElementById('board-bg-color-picker').addEventListener('input', () => {
- saveBoardBgSettings();
- applyBoardBgStyle();
- });
- document.getElementById('board-bg-image-url-input').addEventListener('input', () => {
- saveBoardBgSettings();
- applyBoardBgStyle();
- });
- document.getElementById('board-bg-color-opacity-slider').addEventListener('input', (e) => {
- if(document.getElementById('board-bg-color-opacity-value')) document.getElementById('board-bg-color-opacity-value').textContent = e.target.value;
- saveBoardBgSettings();
- applyBoardBgStyle();
- });
+ restoreCellStyleSettings(
+ savedCellBorderColor, savedCellBorderOpacity, savedCellBgColor, savedCellBgOpacity,
+ savedCellBgImageUrl, savedCellBgImageOpacity, savedCellTextColor, savedCellTextOpacity,
+ savedCellOutlineColor, savedCellOutlineOpacity, savedCellOutlineWidth
+ );
- // --- Search Listener ---
- const searchInput = document.getElementById('search-input');
- if (searchInput) {
- searchInput.addEventListener('input', () => {
- const searchTerm = searchInput.value.trim().toLowerCase();
- const cells = document.querySelectorAll('#bingo-board .bingo-cell');
+ restoreBoardBgSettings(savedBoardBgColor, savedBoardBgColorOpacity, savedBoardBgImageUrl);
- // Split search term into words
- const searchWords = searchTerm.split(/\s+/).filter(word => word.length > 0);
+ restoreSavedItems(savedDisplayedItems, savedItemsText, savedOriginalItemsText);
- cells.forEach(cell => {
- const textSpan = cell.querySelector('.bingo-cell-text');
- let isMatch = false;
- if (textSpan && searchWords.length > 0) {
- const cellText = textSpan.textContent.trim().toLowerCase();
- // Check if ALL search words are included in the cell text
- isMatch = searchWords.every(word => cellText.includes(word));
- }
-
- // Add or remove highlight based on match status
- if (isMatch) {
- cell.classList.add('highlighted');
- } else {
- cell.classList.remove('highlighted');
- }
- });
- });
- }
-
- // --- Other Listeners ---
- window.addEventListener('resize', equalizeCellSizes);
- equalizeCellSizes(); // Initial call after load
-
- // --- Add Event Listeners for Marked Text Style Controls ---
- document.getElementById("marked-cell-text-color-picker").addEventListener("input", () => {
- saveMarkedStyleSettings();
- refreshMarkedCellStyles();
- });
- document.getElementById("marked-cell-text-opacity-slider").addEventListener("input", (e) => {
- if(document.getElementById("marked-cell-text-opacity-value")) document.getElementById("marked-cell-text-opacity-value").textContent = e.target.value;
- saveMarkedStyleSettings();
- refreshMarkedCellStyles();
- });
- document.getElementById("marked-cell-outline-color-picker").addEventListener("input", () => {
- saveMarkedStyleSettings();
- refreshMarkedCellStyles();
- });
- document.getElementById("marked-cell-outline-opacity-slider").addEventListener("input", (e) => {
- if(document.getElementById("marked-cell-outline-opacity-value")) document.getElementById("marked-cell-outline-opacity-value").textContent = e.target.value;
- saveMarkedStyleSettings();
- refreshMarkedCellStyles();
- });
- document.getElementById("marked-cell-outline-width-input").addEventListener("input", () => {
- saveMarkedStyleSettings();
- refreshMarkedCellStyles();
- });
-
- // --- Add Event Listeners for Default Cell Style Controls ---
- document.getElementById("cell-border-color-picker").addEventListener("input", () => {
- saveCellStyleSettings();
- refreshCellStyles(); // Update all non-marked cells
- });
- document.getElementById("cell-border-opacity-slider").addEventListener("input", (e) => {
- if(document.getElementById("cell-border-opacity-value")) document.getElementById("cell-border-opacity-value").textContent = e.target.value;
- saveCellStyleSettings();
- refreshCellStyles(); // Update all non-marked cells
- });
- document.getElementById("cell-background-color-picker").addEventListener("input", () => {
- saveCellStyleSettings();
- refreshCellStyles();
- });
- document.getElementById("cell-background-opacity-slider").addEventListener("input", (e) => {
- if(document.getElementById("cell-background-opacity-value")) document.getElementById("cell-background-opacity-value").textContent = e.target.value;
- saveCellStyleSettings();
- refreshCellStyles();
- });
- document.getElementById("cell-background-image-url-input").addEventListener("input", () => {
- saveCellStyleSettings();
- refreshCellStyles();
- });
- document.getElementById("cell-text-color-picker").addEventListener("input", () => {
- saveCellStyleSettings();
- refreshCellStyles();
- });
- document.getElementById("cell-text-opacity-slider").addEventListener("input", (e) => {
- if(document.getElementById("cell-text-opacity-value")) document.getElementById("cell-text-opacity-value").textContent = e.target.value;
- saveCellStyleSettings();
- refreshCellStyles();
- });
- document.getElementById("cell-outline-color-picker").addEventListener("input", () => {
- saveCellStyleSettings();
- refreshCellStyles();
- });
- document.getElementById("cell-outline-opacity-slider").addEventListener("input", (e) => {
- if(document.getElementById("cell-outline-opacity-value")) document.getElementById("cell-outline-opacity-value").textContent = e.target.value;
- saveCellStyleSettings();
- refreshCellStyles();
- });
- document.getElementById("cell-outline-width-input").addEventListener("input", () => {
- saveCellStyleSettings();
- refreshCellStyles();
- });
-
- clearSearch(); // Clear search highlights and input
- saveBoardState(); // Save the new randomized state (including cleared marks)
- //clearMarks(false); // Clear visual marks
-
- // Apply marked styles *after* all other styles/settings are restored
- refreshMarkedCellStyles(); // <-- Keep here
-
- // Equalize sizes as the very last step after all content and styles are set
- equalizeCellSizes(); // <-- MOVED HERE
-
- // --- Add Event Listeners for Default Cell Style Controls ---
- document.getElementById('cell-border-color-picker').addEventListener('input', () => {
- saveCellStyleSettings();
- refreshCellStyles(); // Update all non-marked cells
- });
- document.getElementById('cell-border-opacity-slider').addEventListener('input', (e) => {
- if(document.getElementById('cell-border-opacity-value')) document.getElementById('cell-border-opacity-value').textContent = e.target.value;
- saveCellStyleSettings();
- refreshCellStyles(); // Update all non-marked cells
- });
- document.getElementById('cell-background-color-picker').addEventListener('input', () => {
- saveCellStyleSettings();
- refreshCellStyles();
- });
- document.getElementById('cell-background-opacity-slider').addEventListener('input', (e) => {
- if(document.getElementById('cell-background-opacity-value')) document.getElementById('cell-background-opacity-value').textContent = e.target.value;
- saveCellStyleSettings();
- refreshCellStyles();
- });
- document.getElementById('cell-background-image-url-input').addEventListener('input', () => {
- saveCellStyleSettings();
- refreshCellStyles();
- });
- document.getElementById('cell-text-color-picker').addEventListener('input', () => {
- saveCellStyleSettings();
- refreshCellStyles();
- });
- document.getElementById('cell-text-opacity-slider').addEventListener('input', (e) => {
- if(document.getElementById('cell-text-opacity-value')) document.getElementById('cell-text-opacity-value').textContent = e.target.value;
- saveCellStyleSettings();
- refreshCellStyles();
- });
- document.getElementById('cell-outline-color-picker').addEventListener('input', () => {
- saveCellStyleSettings();
- refreshCellStyles();
- });
- document.getElementById('cell-outline-opacity-slider').addEventListener('input', (e) => {
- if(document.getElementById('cell-outline-opacity-value')) document.getElementById('cell-outline-opacity-value').textContent = e.target.value;
- saveCellStyleSettings();
- refreshCellStyles();
- });
- document.getElementById('cell-outline-width-input').addEventListener('input', () => {
- saveCellStyleSettings();
- refreshCellStyles();
- });
}
// --- Function to make all cells square and equal size ---
@@ -1611,170 +1504,66 @@ document.addEventListener('DOMContentLoaded', () => {
// Load state first thing
loadFromLocalStorage();
- // --- Add Event Listeners for Background Controls ---
+ // --- Event Listeners Setup using Helpers ---
+
+ // Background Controls
document.querySelectorAll('input[name="background-type"]').forEach(radio => {
radio.addEventListener('change', () => {
toggleBackgroundControls();
- setBackground();
- saveBackgroundSettings();
+ setBackground(); // Apply the change visually
+ saveBackgroundSettings(); // Save the setting
});
});
- document.getElementById('background-color-picker').addEventListener('input', () => {
- setBackground();
- saveBackgroundSettings();
- });
- document.getElementById('background-color-opacity-slider').addEventListener('input', (e) => {
- if(document.getElementById('background-color-opacity-value')) document.getElementById('background-color-opacity-value').textContent = e.target.value;
- setBackground();
- saveBackgroundSettings();
- });
- document.getElementById('gradient-color-1').addEventListener('input', () => {
- setBackground();
- saveBackgroundSettings();
- });
- document.getElementById('gradient-color-1-opacity-slider').addEventListener('input', (e) => {
- if(document.getElementById('gradient-color-1-opacity-value')) document.getElementById('gradient-color-1-opacity-value').textContent = e.target.value;
- setBackground();
- saveBackgroundSettings();
- });
- document.getElementById('gradient-color-2').addEventListener('input', () => {
- setBackground();
- saveBackgroundSettings();
- });
- document.getElementById('gradient-color-2-opacity-slider').addEventListener('input', (e) => {
- if(document.getElementById('gradient-color-2-opacity-value')) document.getElementById('gradient-color-2-opacity-value').textContent = e.target.value;
- setBackground();
- saveBackgroundSettings();
- });
- document.getElementById('gradient-direction').addEventListener('change', () => {
- setBackground();
- saveBackgroundSettings();
- });
+ setupInputListener('background-color-picker', 'input', saveBackgroundSettings, setBackground);
+ setupOpacitySliderListener('background-color-opacity-slider', 'background-color-opacity-value', saveBackgroundSettings, setBackground);
+ setupInputListener('gradient-color-1', 'input', saveBackgroundSettings, setBackground);
+ setupOpacitySliderListener('gradient-color-1-opacity-slider', 'gradient-color-1-opacity-value', saveBackgroundSettings, setBackground);
+ setupInputListener('gradient-color-2', 'input', saveBackgroundSettings, setBackground);
+ setupOpacitySliderListener('gradient-color-2-opacity-slider', 'gradient-color-2-opacity-value', saveBackgroundSettings, setBackground);
+ setupInputListener('gradient-direction', 'change', saveBackgroundSettings, setBackground);
- // --- Add Event Listeners for Header Controls ---
- document.getElementById('header-text-input').addEventListener('input', () => {
- saveHeaderSettings(); // Save the new text first
- updateHeaderDisplay(); // Then update display from saved state
- });
- document.getElementById('header-image-url-input').addEventListener('input', () => {
- saveHeaderSettings(); // Save the new URL first
- updateHeaderDisplay(); // Then update display from saved state
- });
- document.getElementById('header-text-color-picker').addEventListener('input', () => {
- saveHeaderSettings();
- updateHeaderDisplay();
- });
- document.getElementById('header-text-color-opacity-slider').addEventListener('input', (e) => {
- if(document.getElementById('header-text-color-opacity-value')) document.getElementById('header-text-color-opacity-value').textContent = e.target.value;
- saveHeaderSettings();
- updateHeaderDisplay();
- });
- document.getElementById('header-bg-color-picker').addEventListener('input', () => {
- saveHeaderSettings();
- applyHeaderBgStyle();
- });
- document.getElementById('header-bg-opacity-slider').addEventListener('input', (e) => {
- if(document.getElementById('header-bg-opacity-value')) document.getElementById('header-bg-opacity-value').textContent = e.target.value;
- saveHeaderSettings();
- applyHeaderBgStyle();
- });
+ // Header Controls
+ setupInputListener('header-text-input', 'input', saveHeaderSettings, updateHeaderDisplay);
+ setupInputListener('header-image-url-input', 'input', saveHeaderSettings, updateHeaderDisplay);
+ setupInputListener('header-text-color-picker', 'input', saveHeaderSettings, updateHeaderDisplay);
+ setupOpacitySliderListener('header-text-color-opacity-slider', 'header-text-color-opacity-value', saveHeaderSettings, updateHeaderDisplay);
+ setupInputListener('header-bg-color-picker', 'input', saveHeaderSettings, applyHeaderBgStyle);
+ setupOpacitySliderListener('header-bg-opacity-slider', 'header-bg-opacity-value', saveHeaderSettings, applyHeaderBgStyle);
- // --- Add Event Listeners for Marked Style Controls ---
- document.getElementById('marked-color-picker').addEventListener('input', () => {
- saveMarkedStyleSettings();
- refreshMarkedCellStyles();
- });
- document.getElementById('marked-color-opacity-slider').addEventListener('input', (e) => {
- if(document.getElementById('marked-color-opacity-value')) document.getElementById('marked-color-opacity-value').textContent = e.target.value;
- saveMarkedStyleSettings();
- refreshMarkedCellStyles();
- });
- document.getElementById('marked-image-url-input').addEventListener('input', () => {
- saveMarkedStyleSettings();
- refreshMarkedCellStyles();
- });
- document.getElementById('marked-image-opacity-slider').addEventListener('input', (e) => {
- if(document.getElementById('marked-image-opacity-value')) document.getElementById('marked-image-opacity-value').textContent = e.target.value;
- saveMarkedStyleSettings();
- refreshMarkedCellStyles();
- });
- document.getElementById('marked-border-color-picker').addEventListener('input', () => {
- saveMarkedStyleSettings();
- refreshMarkedCellStyles();
- });
- document.getElementById('marked-border-opacity-slider').addEventListener('input', (e) => {
- if(document.getElementById('marked-border-opacity-value')) document.getElementById('marked-border-opacity-value').textContent = e.target.value;
- saveMarkedStyleSettings();
- refreshMarkedCellStyles();
- });
+ // Marked Style Controls
+ setupInputListener('marked-color-picker', 'input', saveMarkedStyleSettings, refreshMarkedCellStyles);
+ setupOpacitySliderListener('marked-color-opacity-slider', 'marked-color-opacity-value', saveMarkedStyleSettings, refreshMarkedCellStyles);
+ setupInputListener('marked-image-url-input', 'input', saveMarkedStyleSettings, refreshMarkedCellStyles);
+ setupOpacitySliderListener('marked-image-opacity-slider', 'marked-image-opacity-value', saveMarkedStyleSettings, refreshMarkedCellStyles);
+ setupInputListener('marked-border-color-picker', 'input', saveMarkedStyleSettings, refreshMarkedCellStyles);
+ setupOpacitySliderListener('marked-border-opacity-slider', 'marked-border-opacity-value', saveMarkedStyleSettings, refreshMarkedCellStyles);
+ // Marked Text Styles
+ setupInputListener('marked-cell-text-color-picker', 'input', saveMarkedStyleSettings, refreshMarkedCellStyles);
+ setupOpacitySliderListener('marked-cell-text-opacity-slider', 'marked-cell-text-opacity-value', saveMarkedStyleSettings, refreshMarkedCellStyles);
+ setupInputListener('marked-cell-outline-color-picker', 'input', saveMarkedStyleSettings, refreshMarkedCellStyles);
+ setupOpacitySliderListener('marked-cell-outline-opacity-slider', 'marked-cell-outline-opacity-value', saveMarkedStyleSettings, refreshMarkedCellStyles);
+ setupInputListener('marked-cell-outline-width-input', 'input', saveMarkedStyleSettings, refreshMarkedCellStyles);
- // --- Add Event Listeners for Default Cell Style Controls ---
- document.getElementById('cell-border-color-picker').addEventListener('input', () => {
- saveCellStyleSettings();
- refreshCellStyles(); // Update all non-marked cells
- });
- document.getElementById('cell-border-opacity-slider').addEventListener('input', (e) => {
- if(document.getElementById('cell-border-opacity-value')) document.getElementById('cell-border-opacity-value').textContent = e.target.value;
- saveCellStyleSettings();
- refreshCellStyles(); // Update all non-marked cells
- });
- document.getElementById('cell-background-color-picker').addEventListener('input', () => {
- saveCellStyleSettings();
- refreshCellStyles();
- });
- document.getElementById('cell-background-opacity-slider').addEventListener('input', (e) => {
- if(document.getElementById('cell-background-opacity-value')) document.getElementById('cell-background-opacity-value').textContent = e.target.value;
- saveCellStyleSettings();
- refreshCellStyles();
- });
- document.getElementById('cell-background-image-url-input').addEventListener('input', () => {
- saveCellStyleSettings();
- refreshCellStyles();
- });
- document.getElementById('cell-background-image-opacity-slider').addEventListener('input', (e) => {
- if(document.getElementById('cell-background-image-opacity-value')) document.getElementById('cell-background-image-opacity-value').textContent = e.target.value;
- saveCellStyleSettings();
- refreshCellStyles();
- });
- // --- Add Event Listeners for Text Style Controls ---
- document.getElementById('cell-text-color-picker').addEventListener('input', () => {
- saveCellStyleSettings();
- refreshCellStyles();
- });
- document.getElementById('cell-text-opacity-slider').addEventListener('input', (e) => {
- if(document.getElementById('cell-text-opacity-value')) document.getElementById('cell-text-opacity-value').textContent = e.target.value;
- saveCellStyleSettings();
- refreshCellStyles();
- });
- document.getElementById('cell-outline-color-picker').addEventListener('input', () => {
- saveCellStyleSettings();
- refreshCellStyles();
- });
- document.getElementById('cell-outline-opacity-slider').addEventListener('input', (e) => {
- if(document.getElementById('cell-outline-opacity-value')) document.getElementById('cell-outline-opacity-value').textContent = e.target.value;
- saveCellStyleSettings();
- refreshCellStyles();
- });
- document.getElementById('cell-outline-width-input').addEventListener('input', () => {
- saveCellStyleSettings();
- refreshCellStyles();
- });
+ // Default Cell Style Controls
+ setupInputListener('cell-border-color-picker', 'input', saveCellStyleSettings, refreshCellStyles);
+ setupOpacitySliderListener('cell-border-opacity-slider', 'cell-border-opacity-value', saveCellStyleSettings, refreshCellStyles);
+ setupInputListener('cell-background-color-picker', 'input', saveCellStyleSettings, refreshCellStyles);
+ setupOpacitySliderListener('cell-background-opacity-slider', 'cell-background-opacity-value', saveCellStyleSettings, refreshCellStyles);
+ setupInputListener('cell-background-image-url-input', 'input', saveCellStyleSettings, refreshCellStyles);
+ setupOpacitySliderListener('cell-background-image-opacity-slider', 'cell-background-image-opacity-value', saveCellStyleSettings, refreshCellStyles);
+ // Default Text Styles
+ setupInputListener('cell-text-color-picker', 'input', saveCellStyleSettings, refreshCellStyles);
+ setupOpacitySliderListener('cell-text-opacity-slider', 'cell-text-opacity-value', saveCellStyleSettings, refreshCellStyles);
+ setupInputListener('cell-outline-color-picker', 'input', saveCellStyleSettings, refreshCellStyles);
+ setupOpacitySliderListener('cell-outline-opacity-slider', 'cell-outline-opacity-value', saveCellStyleSettings, refreshCellStyles);
+ setupInputListener('cell-outline-width-input', 'input', saveCellStyleSettings, refreshCellStyles);
+
+ // Board Background Controls
+ setupInputListener('board-bg-color-picker', 'input', saveBoardBgSettings, applyBoardBgStyle);
+ setupInputListener('board-bg-image-url-input', 'input', saveBoardBgSettings, applyBoardBgStyle);
+ setupOpacitySliderListener('board-bg-color-opacity-slider', 'board-bg-color-opacity-value', saveBoardBgSettings, applyBoardBgStyle);
- // --- Add Event Listeners for Board Background Controls ---
- document.getElementById('board-bg-color-picker').addEventListener('input', () => {
- saveBoardBgSettings();
- applyBoardBgStyle();
- });
- document.getElementById('board-bg-image-url-input').addEventListener('input', () => {
- saveBoardBgSettings();
- applyBoardBgStyle();
- });
- document.getElementById('board-bg-color-opacity-slider').addEventListener('input', (e) => {
- if(document.getElementById('board-bg-color-opacity-value')) document.getElementById('board-bg-color-opacity-value').textContent = e.target.value;
- saveBoardBgSettings();
- applyBoardBgStyle();
- });
// --- Search Listener ---
const searchInput = document.getElementById('search-input');
@@ -1782,8 +1571,6 @@ document.addEventListener('DOMContentLoaded', () => {
searchInput.addEventListener('input', () => {
const searchTerm = searchInput.value.trim().toLowerCase();
const cells = document.querySelectorAll('#bingo-board .bingo-cell');
-
- // Split search term into words
const searchWords = searchTerm.split(/\s+/).filter(word => word.length > 0);
cells.forEach(cell => {
@@ -1791,23 +1578,26 @@ document.addEventListener('DOMContentLoaded', () => {
let isMatch = false;
if (textSpan && searchWords.length > 0) {
const cellText = textSpan.textContent.trim().toLowerCase();
- // Check if ALL search words are included in the cell text
isMatch = searchWords.every(word => cellText.includes(word));
}
-
- // Add or remove highlight based on match status
- if (isMatch) {
- cell.classList.add('highlighted');
- } else {
- cell.classList.remove('highlighted');
- }
+ cell.classList.toggle('highlighted', isMatch); // More concise toggle
});
});
+ clearSearch(); // Clear search on initial load after setting up listener
}
// --- Other Listeners ---
window.addEventListener('resize', equalizeCellSizes);
- equalizeCellSizes(); // Initial call after load
+ equalizeCellSizes(); // <-- MOVED HERE
+
+ clearSearch(); // Clear search highlights and input
+ saveBoardState(); // Save the new randomized state (including cleared marks)
+
+ // Apply marked styles *after* all other styles/settings are restored
+ refreshMarkedCellStyles(); // <-- Keep here
+
+ // Equalize sizes as the very last step after all content and styles are set
+ equalizeCellSizes(); // <-- MOVED HERE
});
// --- Settings Import/Export ---