4
\$\begingroup\$

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.

Sᴀᴍ Onᴇᴌᴀ's user avatar
Sᴀᴍ Onᴇᴌᴀ
29.6k16 gold badges46 silver badges203 bronze badges
askedAug 26, 2019 at 7:30
PeterJoe's user avatar
\$\endgroup\$

1 Answer1

2
\$\begingroup\$

You probably are familiar with<input type="date"> but maybe you aren't satisfied by thebrowser compatibility or wanted to try your hand at.

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().

answeredSep 2, 2019 at 3:21
Sᴀᴍ Onᴇᴌᴀ's user avatar
\$\endgroup\$
1
  • \$\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\$CommentedSep 3, 2019 at 5:48

You mustlog in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.