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);