// ---- Options ------------------------------------------- // Edit names for localization const months = [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ]; const days = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]; // Toggle displaying the current AND next month together const doubleMonthView = true; // Add or change events here. Array format: [ Name, icon, icon color ] const events = [ ["Test", "bxs-pencil", "#ff4c4c"], ["Deadline", "bxs-time", "#ff7b42"], ["Meeting", "bxs-briefcase-alt-2", "#dbc745"], ["Holiday", "bxs-flag-alt", "#57c94f"], ["Birthday", "bxs-cake", "#dd5594"], ["Event", "bxs-calendar-alt", "#4bb4cd"], ["Note", "bxs-info-circle", "#888"] ] // ---- Code ---------------------------------------------- const today = new Date(); var currentMonth = today.getMonth(); var currentYear = today.getFullYear(); // Create header row for days of the week var dayHeader = "<tr>"; for (let day in days) { dayHeader += "<th>" + days[day] + "</th>"; } dayHeader += "</tr>"; document.getElementById("thead-month").innerHTML = dayHeader; // Calendar buttons document.getElementById("previous").addEventListener("click", previous); document.getElementById("next").addEventListener("click", next); document.getElementById("month").addEventListener("change", jump); document.getElementById("year").addEventListener("change", jump); var yearDropdown = ""; for (var i = currentYear-20; i <= currentYear+20; i++) { yearDropdown += "<option value='" + i + "'>" + i + "</option>"; } document.getElementById("year").innerHTML = yearDropdown; // Get needed HTML elements const selectYear = document.getElementById("year"); const selectMonth = document.getElementById("month"); const calendarTitle = document.getElementById("monthAndYear"); const table = document.getElementById("calendar-body"); showCalendar(currentMonth, currentYear); // Displays the given month and year on the calendar. // Month starts at zero. Both args are numbers. async function showCalendar(month, year) { // Used to determine which day of the week the month starts on const firstDay = (new Date(year, month)).getDay(); // Used for the double month view. // nextYear refers to what year it is next month. const nextMonth = (month + 1) % 12; const nextYear = (month === 11) ? year + 1 : year; // Update the table with new values table.innerHTML = ""; selectYear.value = year; selectMonth.value = month; if (doubleMonthView) { calendarTitle.innerHTML = months[month] + " " + year + "<span style='font-size: 65%'> / " + months[nextMonth] + " " + nextYear+ "</span>"; } else { calendarTitle.innerHTML = months[month] + " " + year; } // Create arrays that will contain the month's day notes // and their attributes. var monthArray = []; var attributeArray = []; await makeNoteArrays(month, year, monthArray, attributeArray); if (doubleMonthView) { var nextMonthArray = []; var nextAttributeArray = []; await makeNoteArrays(nextMonth, nextYear, nextMonthArray, nextAttributeArray); } var date = 1; var weekMax = 12; var stop = false; // Loop for each week (make a table row) for (var i = 0; i < weekMax && !stop; i++) { var row = document.createElement("tr"); // Loop for each day (make a cell for every day) for (var j = 0; j < 7 && !stop; j++) { var cell; // Cells before 1st of the month (blank square) if (i === 0 && j < firstDay) { cell = createBlankCell(); } // Cells of next month (only drawn if enabled) else if (date > daysInMonth(month, year)) { if (doubleMonthView) { var nextDate = date - daysInMonth(month, year); // Cells of next NEXT month if (nextDate > daysInMonth(nextMonth, nextYear)) { // Don't draw a completely empty week if (j===0) { stop = true; continue; } cell = createBlankCell(); row.appendChild(cell); weekMax = i; continue; } cell = createCell(nextDate, nextMonth, nextYear); applyLink(cell, nextDate, nextMonth, nextYear, nextMonthArray); stylizeCell(cell, nextDate, nextMonthArray, nextAttributeArray); date++; } else { // Don't draw a completely empty week if (j===0) { stop = true; continue; } cell = createBlankCell(); weekMax = i; } } // Cells of this month else { cell = createCell(date, month, year); applyLink(cell, date, month, year, monthArray); stylizeCell(cell, date, monthArray, attributeArray); // If current cell is today if (date === today.getDate() && year === today.getFullYear() && month === today.getMonth()) { cell.className = "date-picker selected"; } row.appendChild(cell); date++; } row.appendChild(cell); } // End of day table.appendChild(row); } // End of week } // Populates monthArray with all existing day notes in that month. Each // element's index represents the day. Ex: March 5th is monthArray[5], // which would contain a note ID if the page exists. // // Also populates attributeArray with any events for the day. async function makeNoteArrays(month, year, monthArray, attributeArray) { var monthNote = await api.getMonthNote((month < 9) ? year+"-0"+(month+1) : year+"-"+(month+1) ); var monthChildren = await monthNote.getChildNotes(); for (let dayNote of monthChildren) { var indexDay = Number(dayNote.getLabel("dateNote").value.substring(8, 10)); monthArray[indexDay] = dayNote.noteId; // Look for events defined by global array (line 15) attributeArray[indexDay] = []; for (let event of events) { attributeArray[indexDay].push(dayNote.getLabels(event[0])); } } } // Returns an empty table cell for squares with no date. function createBlankCell() { var cell = document.createElement("td"); var cellText = document.createTextNode(""); cell.className = "date-picker" cell.appendChild(cellText); return cell; } // Returns a cell with the given date. function createCell(date, month, year) { var cell = document.createElement("td"); cell.setAttribute("data-date", date); cell.setAttribute("data-month", month + 1); cell.setAttribute("data-year", year); cell.setAttribute("data-month_name", months[month]); cell.className = "date-picker"; return cell; } // Adds the day number to the cell. Clicking it activates or creates // the respective day note. function applyLink(cell, date, month, year, monthArray) { // Create a string in the format YYYY-MM-DD if (month < 9) { var todayStr = year + "-0" + (month + 1); } else { var todayStr = year + "-" + (month + 1); } if (date < 10) { todayStr = todayStr + "-0" + date; } else { todayStr = todayStr + "-" + date; } // Use string for 'calendar-date' HTML attribute, which gives the // ability to create a day note by clicking the link. var link = document.createElement("a"); link.setAttribute("calendar-date", todayStr); link.innerHTML = date; link.addEventListener("click", goToDay); link.className = 'day-number'; cell.appendChild(link); // If a note already exists for this day, make a link to it. if (monthArray[date] != undefined) { link.setAttribute("data-note-path", monthArray[date]); } } // Looks through the attribute array to create any neccessary event markers // on the given calendar cell. function stylizeCell(cell, date, monthArray, attributeArray) { // Stop if there's no day note on this date if (monthArray[date] == undefined) { return; } // 'attribute' contains a two-dimensional array. // First array dictates which event type it is, second contains event descriptions. var attribute = attributeArray[date]; for(let i = 0; i < attribute.length; i++) { for(let j = 0; j < attribute[i].length; j++) { if(attribute[i][j].value != "") { var marker = document.createElement("div"); marker.classList.add("marker"); var markerIcon = document.createElement("span"); markerIcon.classList.add("bx"); // Icon is created by adding Box Icon class (see line 15) markerIcon.classList.add(events[i][1]); markerIcon.classList.add("marker-icon"); markerIcon.style.color = events[i][2]; marker.appendChild(markerIcon); marker.appendChild(document.createTextNode(" "+ attribute[i][j].value )) // Hover tooltip var tooltip = document.createElement("span"); tooltip.classList.add("marker-tooltip"); tooltip.appendChild(document.createTextNode(attribute[i][j].value)); marker.appendChild(tooltip); cell.appendChild(marker); } } } } // Returns how many days there are in the given month function daysInMonth(iMonth, iYear) { return 32 - new Date(iYear, iMonth, 32).getDate(); } // ---- Calendar event handlers --------------------------- // View the next month function next() { currentYear = (currentMonth === 11) ? currentYear + 1 : currentYear; currentMonth = (currentMonth + 1) % 12; showCalendar(currentMonth, currentYear); } // View the previous month function previous() { currentYear = (currentMonth === 0) ? currentYear - 1 : currentYear; currentMonth = (currentMonth === 0) ? 11 : currentMonth - 1; showCalendar(currentMonth, currentYear); } // View a month specified from the calendar controls function jump() { currentYear = parseInt(selectYear.value); currentMonth = parseInt(selectMonth.value); showCalendar(currentMonth, currentYear); } // Activate the clicked day note async function goToDay() { var day = await api.getDateNote(event.currentTarget.getAttribute("calendar-date")); api.activateNote(day.noteId); }