// FIXME ****************************************************************************** // // The datepicker's "Time" section doesn't work. This really needs to be fixed before // the next big RTTY Roundup or Field Day where there may be a lot of hams that want // to use this feature to only reference their log starting when the contest starts. // Which isn't always 00:00 UTC. // ************************************************************************************ // var picker = { attach: function (opt) { // attach() : attach datepicker to target // opt : options (object) // target : datepicker will populate this field // container : datepicker will be generated in this container // startmon : start on Monday (default false) // disableday : array of days to disable, e.g. [2,7] to disable Tue and Sun // (A) Create new datepicker var dp = document.createElement("div"); dp.dataset.target = opt.target; dp.dataset.fire = opt.fire; dp.dataset.startmon = opt.startmon ? "1" : "0"; dp.classList.add("picker"); if (opt.disableday) { dp.dataset.disableday = JSON.stringify(opt.disableday); } // (B) Default to current month + year // ! NOTE: UTC+0 ! var today = new Date(), thisMonth = today.getUTCMonth(), // Note: Jan is 0 thisYear = today.getUTCFullYear(), months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; // (C) Month select var select = document.createElement("select"), option = null; select.classList.add("picker-m"); for (var mth in months) { option = document.createElement("option"); option.value = parseInt(mth) + 1; option.text = months[mth]; select.appendChild(option); } select.selectedIndex = thisMonth; select.addEventListener("change", function() { picker.draw(this); }); dp.appendChild(select); // (D) Year select var yRange = 100; // Year range to show, I.E. from thisYear-yRange to thisYear+yRange select = document.createElement("select"); select.classList.add("picker-y"); for (var y = thisYear - yRange; y < thisYear + 20; y++) { option = document.createElement("option"); option.value = y; option.text = y; select.appendChild(option); } select.selectedIndex = yRange; select.addEventListener("change", function() { picker.draw(this); }); dp.appendChild(select); // (E) Day select var days = document.createElement("div"); days.classList.add("picker-d"); dp.appendChild(days); // (F) Attach date picker to target container + draw the dates picker.draw(select); // (F1) Popup datepicker if (opt.container == 1) { // Mark this as a "popup" var uniqueID = 0; while (document.getElementById("picker-" + uniqueID) != null) { uniqueID = Math.floor(Math.random() * (100 - 2)) + 1; } dp.dataset.popup = "1"; dp.dataset.dpid = uniqueID; // Create wrapper var wrapper = document.createElement("div"); wrapper.id = "picker-" + uniqueID; wrapper.classList.add("picker-wrap"); wrapper.appendChild(dp); // Attach onclick to show/hide datepicker var target = document.getElementById(opt.target); target.dataset.dp = uniqueID; target.onfocus = function () { document.getElementById("picker-" + this.dataset.dp).classList.add("show"); }; wrapper.addEventListener("click", function (evt) { if (evt.target.classList.contains("picker-wrap")) { this.classList.remove("show"); } }); // Attach popup datepicker to document document.documentElement.appendChild(wrapper); } // (F2) Inline datepicker else { document.getElementById(opt.container).appendChild(dp); } }, draw: function (el) { // draw() : draw the days in month // el : HTML reference to either year or month selector // (A) Get date picker components var parent = el.parentElement, year = parent.getElementsByClassName("picker-y")[0].value, month = parent.getElementsByClassName("picker-m")[0].value, days = parent.getElementsByClassName("picker-d")[0]; // (B) Date range calculation // ! NOTE: UTC+0 ! var daysInMonth = new Date(Date.UTC(year, month, 0)).getUTCDate(), startDay = new Date(Date.UTC(year, month - 1, 1)).getUTCDay(), // Note: Sun = 0 endDay = new Date(Date.UTC(year, month - 1, daysInMonth)).getUTCDay(), startDay = startDay == 0 ? 7 : startDay, endDay = endDay == 0 ? 7 : endDay; // (C) Generate date squares (in array first) var squares = [], disableday = null; if (parent.dataset.disableday) { disableday = JSON.parse(parent.dataset.disableday); } // (C1) Empty squares before first day of month if (parent.dataset.startmon == "1" && startDay != 1) { for (var i = 1; i < startDay; i++) { squares.push("B"); } } if (parent.dataset.startmon == "0" && startDay != 7) { for (var i = 0; i < startDay; i++) { squares.push("B"); } } // (C2) Days of month // All days enabled, just add if (disableday == null) { for (var i = 1; i <= daysInMonth; i++) { squares.push([i, false]); } } // Some days disabled else { var thisday = startDay; for (var i = 1; i <= daysInMonth; i++) { // Check if day is disabled var disabled = disableday.includes(thisday); // Day of month, disabled squares.push([i, disabled]); // Next day thisday++; if (thisday == 8) { thisday = 1; } } } // (C2) Empty squares after last day of month if (parent.dataset.startmon == "1" && endDay != 7) { for (var i = endDay; i < 7; i++) { squares.push("B"); } } if (parent.dataset.startmon == "0" && endDay != 6) { for (var i = endDay; i < (endDay == 7 ? 13 : 6); i++) { squares.push("B"); } } // (D) Draw HTML var daynames = ["Mon", "Tue", "Wed", "Thur", "Fri", "Sat"]; if (parent.dataset.startmon == "1") { daynames.push("Sun"); } else { daynames.unshift("Sun"); } // (D1) Header var table = document.createElement("table"), row = table.insertRow() cell = null; row.classList.add("picker-d-h"); for (let d of daynames) { cell = row.insertCell(); cell.innerHTML = d; } // (D2) Date cells var total = squares.length; row = table.insertRow(); for (var i = 0; i < total; i++) { if (i != total && i % 7 == 0) { row = table.insertRow(); } cell = row.insertCell(); if (squares[i] == "B") { cell.classList.add("picker-d-b"); } else { cell.innerHTML = squares[i][0]; // Not allowed to choose this day if (squares[i][1]) { cell.classList.add("picker-d-dd"); } // Allowed to choose this day else { cell.classList.add("picker-d-d"); cell.addEventListener("click", function() { picker.pick(this); }); } } } // (D3) Attach new calendar to datepicker days.innerHTML = ""; days.appendChild(table); }, pick: function (el) { // pick() : choose a date // el : HTML reference to selected date cell // (A) Get all components var parent = el.parentElement; while (!parent.classList.contains("picker")) { parent = parent.parentElement; } // (B) Get full selected year month day var year = parent.getElementsByClassName("picker-y")[0].value, month = parent.getElementsByClassName("picker-m")[0].value, day = el.innerHTML; // YYYY-MM-DD Format // ! CHANGE FORMAT HERE IF YOU WANT ! if (parseInt(month) < 10) { month = "0" + month; } if (parseInt(day) < 10) { day = "0" + day; } var fullDate = year + "-" + month + "-" + day; // (C) Update selected date document.getElementById(parent.dataset.target).value = fullDate; if (parent.dataset.fire.length > 0) { window[parent.dataset.fire](); } // (D) Popup only - close the popup if (parent.dataset.popup == "1") { document.getElementById("picker-" + parent.dataset.dpid).classList.remove("show"); } } };