Calendar Dot

Monthly Calendar

Go to current week.
`); popup.document.close(); let inputField; const existingValue = getCloudValue(`${type}-${year}-${month}-${day}`); if (type === 'note') { inputField = popup.document.createElement('div'); inputField.contentEditable = true; inputField.className = 'editable'; let escapedText = escapeHTML(existingValue); let urlRegex = /(https?:\/\/[^\s]+)/g; inputField.innerHTML = escapedText.replace(urlRegex, function(url) { return '' + url + ''; }); inputField.addEventListener('click', function(e) { if (e.target.tagName === 'A') { e.preventDefault(); popup.open(e.target.href, '_blank'); } }); } else { inputField = popup.document.createElement('textarea'); inputField.value = existingValue; } popup.document.getElementById('editor-wrap').appendChild(inputField); popup.document.getElementById('printBtn').onclick = function() { popup.print(); }; popup.document.getElementById('saveBtn').onclick = function() { let valueToSave = type === 'note' ? inputField.innerText : inputField.value; setCloudValue(`${type}-${year}-${month}-${day}`, valueToSave).then(function() { if (type === 'entry') { element.value = valueToSave; element.setAttribute('data-tooltip', valueToSave); if (valueToSave.trim()) { element.parentElement.querySelector('.icon').classList.add('has-content'); } else { element.parentElement.querySelector('.icon').classList.remove('has-content'); } } else if (type === 'note') { if (valueToSave.trim()) { element.classList.add('has-content'); } else { element.classList.remove('has-content'); } } popup.close(); }).catch(function(error) { alert('Could not save: ' + error.message); }); }; } function openHourlyPopup(year, month, day, dotHourly) { const hourlyPopup = window.open('', 'hourlyPopup_' + year + '_' + month + '_' + day, 'width=500,height=1000'); const dId = dayId(year, month, day); const date = new Date(year, month, day); const dayOfWeek = daysOfWeek[date.getDay()]; hourlyPopup.document.write(` Hourly Content

Hourly Content for ${months[month]} ${day}, ${year} (${dayOfWeek})

`); hourlyPopup.document.close(); const hourlyContentEl = hourlyPopup.document.getElementById('hourly-content'); const createTimeLabel = (hour, minute) => { const ampm = hour < 12 ? 'AM' : 'PM'; const displayHour = hour % 12 || 12; return `${displayHour}:${minute < 10 ? '0' + minute : minute}${ampm}`; }; function loadHourlyContentIntoPopup() { for (let hour = 6; hour <= 24; hour++) { for (let minute = 0; minute < 60; minute += 30) { const hourContent = getCloudValue(`hourly-${dId}-${hour}-${minute}`) || ""; const timeLabel = createTimeLabel(hour, minute); const row = hourlyPopup.document.createElement('div'); row.className = 'hour'; const label = hourlyPopup.document.createElement('div'); label.className = 'time-label'; label.textContent = timeLabel; const input = hourlyPopup.document.createElement('input'); input.type = 'text'; input.className = 'hour-input'; input.id = `hour-${hour}-${minute}`; input.value = hourContent; row.appendChild(label); row.appendChild(input); hourlyContentEl.appendChild(row); } } } function saveHourlyContent() { let updates = {}; let hasContent = false; for (let hour = 6; hour <= 24; hour++) { for (let minute = 0; minute < 60; minute += 30) { const hourContent = hourlyPopup.document.getElementById(`hour-${hour}-${minute}`).value; updates[`hourly-${dId}-${hour}-${minute}`] = hourContent; if (hourContent.trim()) { hasContent = true; } } } updates[`hourly-content-${year}-${month}-${day}`] = hasContent; return db.ref(CALENDAR_PATH).update(updates).then(function() { Object.keys(updates).forEach(function(k) { cloudData[k] = updates[k]; }); var dot = window.document.querySelector('.dot-hourly[hour-day="' + dId + '"]'); if (dot) { if (hasContent) { dot.classList.add('has-content'); } else { dot.classList.remove('has-content'); } } }); } function copyHourlyContent() { let hourlyText = ''; for (let hour = 6; hour <= 24; hour++) { for (let minute = 0; minute < 60; minute += 30) { const hourContent = hourlyPopup.document.getElementById(`hour-${hour}-${minute}`).value; const timeLabel = createTimeLabel(hour, minute); if (hourContent) { hourlyText += `${timeLabel}: ${hourContent}\n`; } } } const tempTextArea = hourlyPopup.document.createElement('textarea'); tempTextArea.value = hourlyText; hourlyPopup.document.body.appendChild(tempTextArea); tempTextArea.select(); hourlyPopup.document.execCommand('copy'); hourlyPopup.document.body.removeChild(tempTextArea); hourlyPopup.alert('Hourly content copied to clipboard!'); } hourlyPopup.document.getElementById('copy-button').addEventListener('click', copyHourlyContent); hourlyPopup.document.getElementById('save-button').addEventListener('click', () => { saveHourlyContent().then(function() { hourlyPopup.close(); }).catch(function(error) { hourlyPopup.alert('Could not save hourly content: ' + error.message); }); }); hourlyPopup.document.getElementById('print-button').addEventListener('click', () => { hourlyPopup.print(); }); loadHourlyContentIntoPopup(); } document.getElementById('prev').addEventListener('click', () => { currentMonth--; if (currentMonth < 0) { currentMonth = 11; currentYear--; } loadCalendar(currentYear, currentMonth); }); document.getElementById('next').addEventListener('click', () => { currentMonth++; if (currentMonth > 11) { currentMonth = 0; currentYear++; } loadCalendar(currentYear, currentMonth); }); document.getElementById('current-day').textContent = `Today's date: ${today.toDateString()}`; document.getElementById('go-to-week').addEventListener('click', (e) => { e.preventDefault(); if (currentMonth !== today.getMonth() || currentYear !== today.getFullYear()) { currentMonth = today.getMonth(); currentYear = today.getFullYear(); loadCalendar(currentYear, currentMonth); } const firstDayIndex = new Date(today.getFullYear(), today.getMonth(), 1).getDay(); const weekOfMonth = Math.ceil((today.getDate() + firstDayIndex) / 7); if (weekOfMonth === 1) { return; } setTimeout(() => { const todayEl = document.querySelector('.today'); if (todayEl) { todayEl.closest('.day-wrapper').scrollIntoView({ behavior: 'smooth', block: 'start' }); } }, 100); }); function collectAllPopupEntries() { let allEntries = ""; const daysInMonth = new Date(currentYear, currentMonth + 1, 0).getDate(); const urlRegex = /(https?:\/\/[^\s]+)/g; for (let day = 1; day <= daysInMonth; day++) { let entry = getCloudValue(`entry-${currentYear}-${currentMonth}-${day}`); let note = getCloudValue(`note-${currentYear}-${currentMonth}-${day}`); if (entry && entry !== "") { let date = new Date(currentYear, currentMonth, day); let dayOfWeek = daysOfWeek[date.getDay()]; let escapedEntry = escapeHTML(entry); let linkedEntry = escapedEntry.replace(urlRegex, '$1').replace(/(?:\r\n|\r|\n)/g, '
'); allEntries += `*** Date ${day}, ${dayOfWeek}:
${linkedEntry}


`; } if (note && note !== "") { let date = new Date(currentYear, currentMonth, day); let dayOfWeek = daysOfWeek[date.getDay()]; let escapedNote = escapeHTML(note); let linkedNote = escapedNote.replace(urlRegex, '$1').replace(/(?:\r\n|\r|\n)/g, '
'); allEntries += `  * NOTES ${day}, ${dayOfWeek}:
${linkedNote}


`; } } return allEntries; } document.getElementById('btn-print-popups').addEventListener('click', () => { const allEntries = collectAllPopupEntries(); const popup = window.open('', 'printPopups', 'width=800,height=600'); popup.document.write(` Print Popups `); popup.document.close(); popup.print(); }); db.ref(CALENDAR_PATH).on('value', function(snapshot) { cloudData = snapshot.val() || {}; if (isUserEditing) { return; } if (suppressNextRender) { suppressNextRender = false; return; } loadCalendar(currentYear, currentMonth); }, function(error) { alert('Could not load calendar data: ' + error.message); }); loadCalendar(currentYear, currentMonth); Monthly Calendar

Go to current week.