I'm still new in javascript and learning. I want to create a date picker using html and javascript. Below is what I have tried and it's working, so my question is "how can I do it better?" My idea is to create a custom tag in HTML and allow multiple of these tags. The javascript part will then handle the build and functionality of all the custom tags. Like I said it is working, I just want to get some feedback to help making it better.
I have done everything, The HTML and javascript and both are working. See below my code:
let currentDate = new Date();let currentMonth = currentDate.getMonth();let currentYear = currentDate.getFullYear();let months = ["January", "February", "March", "April", "May", "June", "July","August", "September", "October","November", "December"];let daysOfTheMonth = ["S","M","T","W","T","F","S"];var datePickers = document.getElementsByTagName("datePicker");class Calendar { constructor(id,year, month) { this.id = id, this.year = year, this.month = month, this.header = months[this.month] + " " + this.year; } previous(calendarBody,calendarHeader,mainHeader){ this.year = (this.month === 0) ? this.year - 1 : this.year; this.month = (this.month === 0) ? 11 : this.month - 1; this.update(calendarBody,calendarHeader,mainHeader) } next(calendarBody,calendarHeader,mainHeader) { this.year = (this.month === 11) ? this.year + 1 : this.year; this.month = (this.month + 1) % 12; this.update(calendarBody,calendarHeader,mainHeader) } selectDate(date){ let year = this.year; let month = this.month; let newDate = new Date(year, month, date) const newMonth = newDate.toLocaleString('default', { month: 'short' }); var dayName = newDate.toString().split(' ')[0]; document.getElementById("topHeader_"+ this.id).innerHTML = dayName+", "+ newMonth + " "+ date document.getElementById("input_"+ this.id).value = formatDate(newDate) } update(calendarBody,calendarHeader,mainHeader){ let month = currentDate.toLocaleString('default', { month: 'short' }); let dayName = currentDate.toString().split(' ')[0]; mainHeader.innerHTML = dayName+", "+ month + " " + currentDate.getDate(); calendarHeader.innerHTML = months[this.month] + " " + this.year; calendarBody.innerHTML = ""; let firstDay = (new Date(this.year, this.month)).getDay(); let daysInMonth = 32 - new Date(this.year, this.month, 32).getDate(); let date = 1; for (let i = 0; i < 6; i++) { let row = document.createElement("tr"); for (let j = 0; j < 7; j++) { if (i === 0 && j < firstDay) { let cell = document.createElement("td"); cell.innerHTML = "" row.appendChild(cell); } else if (date > daysInMonth) { break; } else { let vm = this; let cell = document.createElement("td"); let button = document.createElement("button"); button.innerHTML = date; cell.appendChild(button); button.addEventListener('click',function(e){ vm.selectDate(e.target.innerHTML); }); if (date === currentDate.getDate() && this.year === currentDate.getFullYear() && this.month === currentDate.getMonth()) { cell.classList.add("today"); } row.appendChild(cell); date++; } } calendarBody.appendChild(row); } } createPicker(datePicker){ let vm = this; let mainHeader = document.createElement("div"); mainHeader.setAttribute("id", "topHeader_"+ vm.id) mainHeader.classList.add("topHeader"); mainHeader.innerHTML = vm.header; let calendar = document.createElement("div"); calendar.setAttribute("id", "calendar_"+vm.id); calendar.setAttribute("class", "calendar"); calendar.style.display = "none"; calendar.appendChild(mainHeader); let input = document.createElement("input"); input.setAttribute("type", "text"); input.setAttribute("id", "input_"+ vm.id); input.setAttribute("tagName", "input"); input.setAttribute("class", "datePickerInput"); input.setAttribute("calendar", "calendar_"+vm.id); input.setAttribute("placeholder", "Select a date"); datePicker.appendChild(input); let calendarHeaderContainer = document.createElement("div"); let prevButton = document.createElement("button"); prevButton.setAttribute("id", "prevButton_"+vm.id); prevButton.innerHTML = "<"; let nextButton = document.createElement("button"); nextButton.setAttribute("id", "nextButton_"+vm.id); nextButton.innerHTML = ">"; calendarHeaderContainer.appendChild(prevButton); let calendarHeader = document.createElement("div"); calendarHeader.setAttribute("id", "calendar_header_"+vm.id); calendarHeader.setAttribute("class", "calendar_header"); calendarHeader.innerHTML = vm.header; calendarHeaderContainer.appendChild(calendarHeader); calendarHeaderContainer.appendChild(nextButton); let calendarTable = document.createElement("table"); calendarTable.setAttribute("id", "calendar_body_"+vm.id); let calendarTableBody = calendarTable.createTBody(); let calendarTableHeader = calendarTable.createTHead(); calendarTableHeader.classList.add("daysOfTheMonth"); let row = document.createElement("tr"); for (let j = 0; j < daysOfTheMonth.length; j++) { let cell = document.createElement("td"); cell.innerHTML = daysOfTheMonth[j]; row.appendChild(cell); } calendarTableHeader.appendChild(row); this.update(calendarTableBody,calendarHeader,mainHeader) calendar.appendChild(calendarHeaderContainer); calendar.appendChild(calendarTable); datePicker.appendChild(calendar); input.addEventListener('click',function(e){ let calendar = document.getElementById(this.getAttribute("calendar")); if(calendar.style.display === "none"){ calendar.style.display = "block" }else{ calendar.style.display = "none" } }); nextButton.addEventListener('click',function(e){ vm.next(calendarTableBody,calendarHeader,mainHeader); }); prevButton.addEventListener('click',function(e){ vm.previous(calendarTableBody,calendarHeader,mainHeader); }); }}function formatDate(date) { var d = new Date(date), month = '' + (d.getMonth() + 1), day = '' + d.getDate(), year = d.getFullYear(); if (month.length < 2) month = '0' + month; if (day.length < 2) day = '0' + day; return [year, month, day].join('-');}for ( var x = 0; x < datePickers.length; x++) { var calendar = new Calendar(x, currentYear, currentMonth); calendar.createPicker(datePickers[x])}.calendar { width: 250px; background: gainsboro; border-radius: 5px;}.calendarHeaderContainer { display: flex; justify-content: space-between; align-items: center;}.topHeader { font-size: 20px; background: #03A9F4; padding: 10px; border-top-left-radius: 5px; border-top-right-radius: 5px;}/*Button Reset*/button { background: none; border: none;}<h1>Date Picker</h1> <datePicker></datePicker>One thing I do want to know is: I want to return the selected date for each picker and it also has to be by the id of the picker so you know what date goes where.
Thanks again, everyone.
1 Answer1
You probably are familiar with<input type="date"> but maybe you aren't satisfied by thebrowser compatibility or wanted to try your hand atreinventing-the-wheel.
Instead of creating numerous HTML elements with the Javascript Logic, have you considered using a<template> with<slot> tags and replacing values as needed.
Also, I see many variables declared withlet but only one withconst (i.e.newMonth). It is wise to useconst as a default and then when it is determined that re-assignment is necessary switch tolet.
Instead of assigning a reference tothis invm use arrow functions (because there would be no separatethis context) or else set the context of those anonymous functions tothis usingFunction.bind().
- \$\begingroup\$Sam Thank you so much for this advice i will def keep that in mind. Great great advice. I will def try to use template tags think that is the best way to go\$\endgroup\$PeterJoe– PeterJoe2019-09-03 05:48:56 +00:00CommentedSep 3, 2019 at 5:48
You mustlog in to answer this question.
Explore related questions
See similar questions with these tags.
