Changing the direction of content on calendar design - javascript

I'm building my own version of dynamic calendar with html css and js.
I got two issues:
Small issue: The buttons of changing to the next / previous month work as expected just after the second click.
Major issue: I can't understand how to fill last month's days on the right ("from the end") direction.
This is my code:
var days = ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];
var monthnames = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];
var today = new Date();
document.querySelector('#monthChoose').value = (today.getMonth()+1);
document.querySelector('#yearChoose').value = today.getFullYear();
// next and previous buttons
document.querySelector('#nextM').addEventListener('click', function() { document.querySelector('#monthChoose').value = operator++; buildCalendar()});
document.querySelector('#prevM').addEventListener('click', function() {document.querySelector('#monthChoose').value = operator--; buildCalendar()});
// fill days of the week as title
for (var i=0; i < days.length; i++) {
document.querySelector('#weekdays').innerHTML += '<li><span>'+days[i]+'</span></li>';
}
var operator = document.querySelector('#monthChoose').value; // this will later on the function to restrict input value
function buildCalendar() {
if (operator > 12) {operator = 1};
if (operator < 1) {operator = 12};
document.querySelector('#days').innerHTML = ' '; // clear records
var month = document.querySelector('#monthChoose').value;
var year = document.querySelector('#yearChoose').value;
document.querySelector('#monthName').textContent = monthnames[month-1]; // display month name
function daysInMonth (month, year) { return new Date(year, month, 0).getDate(); } // constructor to get number of days in chosen month
var lastMonthDays = daysInMonth(month-1, year);
var currentMonthDays = daysInMonth(month, year);
var currentFirstDay = new Date(year, month-1 ,1);
currentFirstDayNum = new Date(currentFirstDay).getDay();
var currentLastDay = new Date(year, month ,1);
currentLastDayNum = new Date(currentLastDay).getDay();
// fill last month's days
// this cause issue: i need to change the content direction so it will fill from the opposite direction
for (var i=0; i < currentFirstDayNum; i++) {
document.querySelector('#days').innerHTML += '<li style="opacity: 0.5;">'+(lastMonthDays-i)+'</li>';
}
// fill the current month days
for (var i=0; i < currentMonthDays; i++) {
document.querySelector('#days').innerHTML += '<li>'+(i+1)+'</li>';
}
// fill the rest of the board
var liLength = document.querySelectorAll('#days > li').length;
var restOfBoard=0;
while (liLength < 42) {
restOfBoard+=1;
document.querySelector('#days').innerHTML += '<li style="opacity: 0.5;">'+restOfBoard+'</li>';
liLength++
}
}
buildCalendar();
ul {list-style-type: none; text-align: center; margin: 0; padding: 0;}
#month {padding: 30px 0; width: 100%; }
#month li input:first-child { display: none; } /* hide input that control months - will change with js*/
#monthName { display: block; }
#monthName { font-size: 2em; }
#month button {width: auto; padding: 0; font-size: 2em;}
#month #prevM {float: left;}
#month #nextM {float: right;}
#weekdays { padding: 10px 0; background-color: gray; }
#weekdays li {
display: inline-block;
color: white;
width: calc(100% / 7);
}
#days { padding: 10px 0; }
#days li {
display: inline-block;
width: calc(100% / 7);
height: calc(400px / 5);
}
<ul id="month">
<li><button id="prevM">❮</button> </li>
<li><button id="nextM">❯</button> </li>
<li id="monthName"></li>
<li>
<input type="number" id="monthChoose" onchange="buildCalendar()" />
<input type="number" id="yearChoose" onchange="buildCalendar()"/>
</li>
</ul>
<ul id="weekdays"></ul>
<ul id="days"></ul>
Note: will glad to hear about things i could do better with this code...
EDIT:
The expected result for the second issue is the lest days of last month. If we take October 2019: the first day is Tuesday so on this week Monday should be the 30th and Sunday the 29th. Can't understand how to fill those days in this order dynamically.

So i finally managed to solve the second problem: Gave the lastMonthDays a unique class, sort it by it content, append the sorting elements, and then proceed with the rest of code.
For this i modified this script for my needs.
Thanks everybody.

The first problem is quite easy to solve by changing
document.querySelector('#monthChoose').value = operator++;
to
document.querySelector('#monthChoose').value = ++operator;
and changing
document.querySelector('#monthChoose').value = operator--;
to
document.querySelector('#monthChoose').value = --operator;
Putting ++ after operator means you don't increase the value of operator until afer you copy its value to the "monthChoose" element, where as putting it beforehand ensures you change its value first. And of course you later use the "monthChoose" element's value to determine the actual month to be displayed.
N.B. It's unclear why you actually need two values here at all - that is just a recipe for confusion. Since operator is global, you could just use that all the way through. Alternatively you could use the "monthChoose" element to maintain state if you want to reduce your use of global variables (which generally, you should).
Here's a demo:
var days = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
var monthnames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
var today = new Date();
document.querySelector('#monthChoose').value = (today.getMonth() + 1);
document.querySelector('#yearChoose').value = today.getFullYear();
// next and previous buttons
document.querySelector('#nextM').addEventListener('click', function() {
document.querySelector('#monthChoose').value = ++operator;
buildCalendar()
});
document.querySelector('#prevM').addEventListener('click', function() {
document.querySelector('#monthChoose').value = --operator;
buildCalendar()
});
// fill days of the week as title
for (var i = 0; i < days.length; i++) {
document.querySelector('#weekdays').innerHTML += '<li><span>' + days[i] + '</span></li>';
}
var operator = document.querySelector('#monthChoose').value; // this will later on the function to restrict input value
function buildCalendar() {
if (operator > 12) {
operator = 1
};
if (operator < 1) {
operator = 12
};
document.querySelector('#days').innerHTML = ' '; // clear records
var month = document.querySelector('#monthChoose').value;
var year = document.querySelector('#yearChoose').value;
document.querySelector('#monthName').textContent = monthnames[month - 1]; // display month name
function daysInMonth(month, year) {
return new Date(year, month, 0).getDate();
} // constructor to get number of days in chosen month
var lastMonthDays = daysInMonth(month - 1, year);
var currentMonthDays = daysInMonth(month, year);
var currentFirstDay = new Date(year, month - 1, 1);
currentFirstDayNum = new Date(currentFirstDay).getDay();
var currentLastDay = new Date(year, month, 1);
currentLastDayNum = new Date(currentLastDay).getDay();
// fill last month's days
// this cause issue: i need to change the content direction so it will fill from the opposite direction
for (var i = 0; i < currentFirstDayNum; i++) {
document.querySelector('#days').innerHTML += '<li style="opacity: 0.5;">' + (lastMonthDays - i) + '</li>';
}
// fill the current month days
for (var i = 0; i < currentMonthDays; i++) {
document.querySelector('#days').innerHTML += '<li>' + (i + 1) + '</li>';
}
// fill the rest of the board
var liLength = document.querySelectorAll('#days > li').length;
var restOfBoard = 0;
while (liLength < 42) {
restOfBoard += 1;
document.querySelector('#days').innerHTML += '<li style="opacity: 0.5;">' + restOfBoard + '</li>';
liLength++
}
}
buildCalendar();
ul {
list-style-type: none;
text-align: center;
margin: 0;
padding: 0;
}
#month {
padding: 30px 0;
width: 100%;
}
#month li input:first-child {
display: none;
}
/* hide input that control months - will change with js*/
#monthName {
display: block;
}
#monthName {
font-size: 2em;
}
#month button {
width: auto;
padding: 0;
font-size: 2em;
}
#month #prevM {
float: left;
}
#month #nextM {
float: right;
}
#weekdays {
padding: 10px 0;
background-color: gray;
}
#weekdays li {
display: inline-block;
color: white;
width: calc(100% / 7);
}
#days {
padding: 10px 0;
}
#days li {
display: inline-block;
width: calc(100% / 7);
height: calc(400px / 5);
}
<ul id="month">
<li><button id="prevM">❮</button> </li>
<li><button id="nextM">❯</button> </li>
<li id="monthName"></li>
<li>
<input type="number" id="monthChoose" onchange="buildCalendar()" />
<input type="number" id="yearChoose" onchange="buildCalendar()" />
</li>
</ul>
<ul id="weekdays"></ul>
<ul id="days"></ul>
I'm afraid I don't understand precisely what you mean by your second problem. Perhaps you can give a clearer description / diagram showing what you want to happen and then I can update this answer?

Related

JS Event Calendar, to handle multiple lineedit events with their own task sets as checkboxes

I am trying to make a simple calendar app that stores locally within itself its events, and tasks
Currently it is using a single text box to store event data and does not allow task handling within the event. just a large text editable box for text input only.
So instead of having a single text box for all events on a date, how do change my code so it handles single lineedit events up to 20 events during a day each with their own associated task list
I.E: on 22nd September there are four events Event 1, Event 2, Event 3, Event 4. currently this stores as noted above single line of events not separated at all. I want to try to have individual events with their own task sets.
So example I want to try to do the following;
on click of a date within the month example 22nd Sept 22
lineEdit Event 1, Checkbox Task 1, Checkbox Task 2, Checkbox Task 3
lineEdit Event 2, Checkbox Task 1, Checkbox Task 2, Checkbox Task 3
lineEdit Event 3, Checkbox Task 1, Checkbox Task 2, Checkbox Task 3
lineEdit Event 4, Checkbox Task 1, Checkbox Task 2, Checkbox Task 3
kind of something like this;
<textarea id="evt-details" rows="5" cols="35"></textarea><br>
<input type="checkbox" value="Task 1"><label>Task2</label><br>
<input type="checkbox" value="Task 2"><label>Task2</label><br>
<input type="checkbox" value="Task 3"><label>Task 3</label><br>
But cleaner to allow multiple individual events and allow them to be individually edited, modified and deleted and still allowing for the expansion of the calendar squares to display all events on the day if multiples and I ideally want to show the task completed either by colour code- or when ticked write it beside the event "task 1 complete" for an example..
etc etc.
var cal = {
// (A) PROPERTIES
// (A1) COMMON CALENDAR
sMon : false, // Week start on Monday?
mName : ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], // Month Names
// (A2) CALENDAR DATA
data : null, // Events for the selected period
sDay : 0, sMth : 0, sYear : 0, // Current selected day, month, year
// (A3) COMMON HTML ELEMENTS
hMth : null, hYear : null, // month/year selector
hForm : null, hfHead : null, hfDate : null, hfTxt : null, hfDel : null, // event form
// (B) INIT CALENDAR
init : () => {
// (B1) GET + SET COMMON HTML ELEMENTS
cal.hMth = document.getElementById("cal-mth");
cal.hYear = document.getElementById("cal-yr");
cal.hForm = document.getElementById("cal-event");
cal.hfHead = document.getElementById("evt-head");
cal.hfDate = document.getElementById("evt-date");
cal.hfTxt = document.getElementById("evt-details");
cal.hfDel = document.getElementById("evt-del");
document.getElementById("evt-close").onclick = cal.close;
cal.hfDel.onclick = cal.del;
cal.hForm.onsubmit = cal.save;
// (B2) DATE NOW
let now = new Date(),
nowMth = now.getMonth(),
nowYear = parseInt(now.getFullYear());
// (B3) APPEND MONTHS SELECTOR
for (let i=0; i<12; i++) {
let opt = document.createElement("option");
opt.value = i;
opt.innerHTML = cal.mName[i];
if (i==nowMth) { opt.selected = true; }
cal.hMth.appendChild(opt);
}
cal.hMth.onchange = cal.list;
// (B4) APPEND YEARS SELECTOR
// Set to 10 years range. Change this as you like.
for (let i=nowYear-10; i<=nowYear+10; i++) {
let opt = document.createElement("option");
opt.value = i;
opt.innerHTML = i;
if (i==nowYear) { opt.selected = true; }
cal.hYear.appendChild(opt);
}
cal.hYear.onchange = cal.list;
// (B5) START - DRAW CALENDAR
cal.list();
},
// (C) DRAW CALENDAR FOR SELECTED MONTH
list : () => {
// (C1) BASIC CALCULATIONS - DAYS IN MONTH, START + END DAY
// Note - Jan is 0 & Dec is 11
// Note - Sun is 0 & Sat is 6
cal.sMth = parseInt(cal.hMth.value); // selected month
cal.sYear = parseInt(cal.hYear.value); // selected year
let daysInMth = new Date(cal.sYear, cal.sMth+1, 0).getDate(), // number of days in selected month
startDay = new Date(cal.sYear, cal.sMth, 1).getDay(), // first day of the month
endDay = new Date(cal.sYear, cal.sMth, daysInMth).getDay(), // last day of the month
now = new Date(), // current date
nowMth = now.getMonth(), // current month
nowYear = parseInt(now.getFullYear()), // current year
nowDay = cal.sMth==nowMth && cal.sYear==nowYear ? now.getDate() : null ;
// (C2) LOAD DATA FROM LOCALSTORAGE
cal.data = localStorage.getItem("cal-" + cal.sMth + "-" + cal.sYear);
if (cal.data==null) {
localStorage.setItem("cal-" + cal.sMth + "-" + cal.sYear, "{}");
cal.data = {};
} else { cal.data = JSON.parse(cal.data); }
// (C3) DRAWING CALCULATIONS
// Blank squares before start of month
let squares = [];
if (cal.sMon && startDay != 1) {
let blanks = startDay==0 ? 7 : startDay ;
for (let i=1; i<blanks; i++) { squares.push("b"); }
}
if (!cal.sMon && startDay != 0) {
for (let i=0; i<startDay; i++) { squares.push("b"); }
}
// Days of the month
for (let i=1; i<=daysInMth; i++) { squares.push(i); }
// Blank squares after end of month
if (cal.sMon && endDay != 0) {
let blanks = endDay==6 ? 1 : 7-endDay;
for (let i=0; i<blanks; i++) { squares.push("b"); }
}
if (!cal.sMon && endDay != 6) {
let blanks = endDay==0 ? 6 : 6-endDay;
for (let i=0; i<blanks; i++) { squares.push("b"); }
}
// (C4) DRAW HTML CALENDAR
// Get container
let container = document.getElementById("cal-container"),
cTable = document.createElement("table");
cTable.id = "calendar";
container.innerHTML = "";
container.appendChild(cTable);
// First row - Day names
let cRow = document.createElement("tr"),
days = ["Sun", "Mon", "Tue", "Wed", "Thur", "Fri", "Sat"];
if (cal.sMon) { days.push(days.shift()); }
for (let d of days) {
let cCell = document.createElement("td");
cCell.innerHTML = d;
cRow.appendChild(cCell);
}
cRow.classList.add("head");
cTable.appendChild(cRow);
// Days in Month
let total = squares.length;
cRow = document.createElement("tr");
cRow.classList.add("day");
for (let i=0; i<total; i++) {
let cCell = document.createElement("td");
if (squares[i]=="b") { cCell.classList.add("blank"); }
else {
if (nowDay==squares[i]) { cCell.classList.add("today"); }
cCell.innerHTML = `<div class="dd">${squares[i]}</div>`;
if (cal.data[squares[i]]) {
cCell.innerHTML += "<div class='evt'>" + cal.data[squares[i]] + "</div>";
}
cCell.onclick = () => { cal.show(cCell); };
}
cRow.appendChild(cCell);
if (i!=0 && (i+1)%7==0) {
cTable.appendChild(cRow);
cRow = document.createElement("tr");
cRow.classList.add("day");
}
}
// (C5) REMOVE ANY PREVIOUS ADD/EDIT EVENT DOCKET
cal.close();
},
// (D) SHOW EDIT EVENT DOCKET FOR SELECTED DAY
show : (el) => {
// (D1) FETCH EXISTING DATA
cal.sDay = el.getElementsByClassName("dd")[0].innerHTML;
let isEdit = cal.data[cal.sDay] !== undefined ;
// (D2) UPDATE EVENT FORM
cal.hfTxt.value = isEdit ? cal.data[cal.sDay] : "" ;
cal.hfHead.innerHTML = isEdit ? "EDIT EVENT" : "ADD EVENT" ;
cal.hfDate.innerHTML = `${cal.sDay} ${cal.mName[cal.sMth]} ${cal.sYear}`;
if (isEdit) { cal.hfDel.classList.remove("ninja"); }
else { cal.hfDel.classList.add("ninja"); }
cal.hForm.classList.remove("ninja");
},
// (E) CLOSE EVENT DOCKET
close : () => {
cal.hForm.classList.add("ninja");
},
// (F) SAVE EVENT
save : () => {
cal.data[cal.sDay] = cal.hfTxt.value;
localStorage.setItem(`cal-${cal.sMth}-${cal.sYear}`, JSON.stringify(cal.data));
cal.list();
return false;
},
// (G) DELETE EVENT FOR SELECTED DATE
del : () => { if (confirm("Delete event?")) {
delete cal.data[cal.sDay];
localStorage.setItem(`cal-${cal.sMth}-${cal.sYear}`, JSON.stringify(cal.data));
cal.list();
}}
};
window.addEventListener("load", cal.init);
/* (A) ENTIRE PAGE */
#cal-wrap * { font-family: arial, sans-serif; }
.ninja { display: none !important; }
/* (B) CONTAINER */
#cal-wrap { max-width: 900px; }
/* (C) PERIOD SELECTOR */
#cal-date { display: flex; }
#cal-mth, #cal-yr {
box-sizing: border-box;
padding: 10px 20px;
font-size: 1.2em;
border: 0;
}
/* (D) CALENDAR */
#calendar {
width: 100%;
border-collapse: collapse;
}
#calendar tr.head td {
font-weight: bold;
text-transform: uppercase;
color: #000000;
background: #CCFFFF;
padding: 15px;
text-align: center;
}
#calendar tr.day td {
border: 1px solid #ddd;
width: 14.28%;
padding: 15px 5px;
vertical-align: top;
}
#calendar tr.day td:hover {
background: #fff9e4;
cursor: pointer;
}
#calendar tr td.blank {
background: #f5f5f5;
}
#calendar tr td.today {
background: #ffdede;
}
#calendar .dd {
font-size: 1.2em;
color: #999;
}
#calendar .evt {
margin-top: 5px;
font-size: 0.8em;
font-weight: bold;
overflow: hidden;
color: #ff5d5d;
}
/* (E) ADD/EDIT EVENT */
#cal-event {
padding: 15px;
margin-top: 20px;
background: #f5f5f5;
border: 1px solid #ddd;
}
#cal-event h1 {
color: #333;
padding: 0;
margin: 0;
}
#evt-date {
color: #555;
margin: 10px 0;
}
#cal-event textarea {
display: block;
box-sizing: border-box;
width: 100%;
padding: 10px;
margin: 10px 0;
border: 1px solid #ddd;
min-height: 200px;
}
#cal-event input[type=button], #cal-event input[type=submit] {
padding: 10px;
margin: 5px;
font-size: 1.2em;
border: 0;
background: #ea4c4c;
color: #fff;
}
<!DOCTYPE html>
<html>
<head>
<title>Simple Javascript Calendar</title>
<link href="calendar.css" rel="stylesheet">
<script async src="calendar.js"></script>
</head>
<body>
<div id="cal-wrap">
<!-- (A) PERIOD SELECTOR -->
<div id="cal-date">
<select id="cal-mth"></select>
<select id="cal-yr"></select>
</div>
<!-- (B) CALENDAR -->
<div id="cal-container"></div>
<!-- (C) EVENT FORM -->
<form id="cal-event">
<h1 id="evt-head"></h1>
<div id="evt-date"></div>
<textarea id="evt-details" required></textarea>
<input id="evt-close" type="button" value="Close"/>
<input id="evt-del" type="button" value="Delete"/>
<input id="evt-save" type="submit" value="Save"/>
</form>
</div>
</body>
</html>
What you have here is a fine start.
You'll just store more information on your localstorage saves like
[{
"text_area" : "Text area for Nov 6",
"tasks":[
{
"label" : "Label 1",
"value" : "Value 1"
},
{
"label" : "Label 2",
"value" : "Value 2"
},
{
"label" : "Label 3",
"value" : "Value 3"
}
]
},{
"text_area" : "Another text area for Nov 6",
"tasks":[
{
"label" : "Label 1",
"value" : "Value 1"
},
{
"label" : "Label 2",
"value" : "Value 2"
},
{
"label" : "Label 3",
"value" : "Value 3"
}
]
}]
and change your form to have a container
<form id="cal-event">
<h1 id="evt-head"></h1>
<div id="evt-date"></div>
<div id="form-container"></div>
<input id="evt-close" type="button" value="Close"/>
<input id="evt-del" type="button" value="Delete"/>
<input id="evt-save" type="submit" value="Save"/>
</form>
and then in your show method you'd do something like
show: (el) => {
//...
let HTML = ''
cal.data.forEach(taskGroup => {
// define a new text area
HTML += `<textarea>${taskGroup.text_area}</textarea>`
taskGroup.tasks.forEach(task => {
HTML += `<input type="checkbox" value="${task.value}"><label>${task.label}</label>`
})
//...
})
document.getElementById('form-container').innerHTML = HTML;
//...
}
The gist is your gonna allow your data to dictate more and more what your page looks and feels like by describing more JSON.
As far as your calendar, to maximize the space and have more flexibility on amount of content you can shove in, you may want to get away from <tables> and work with something like css grid https://learncssgrid.com/
Please take this code as pseudo code to give you some ideas. Happy programming.

Changing a HTML element at a certain time and date

I have an open and closed indicator (Thanks to those who helped me!) that shows I am open from 8:00 AM to 10:00 PM and from 10:00 PM to 8:00 AM I am closed, but it shows this even on a weekend when I am not open. Can you help me make the Javascript say I am closed when it is a weekend and on a holiday like December 24-25? Below will be my current code. Thanks!
Javascript:
var messageElement = document.getElementById("message");
var circleElement = document.getElementById("circle");
const refreshStatus = () => {
// Set the current time
let currentDate = new Date().getHours();
// If the time is between 8 am and 10 pm
if (currentDate >= 8 && currentDate <= 21) {
// Update text and add classes
messageElement.innerHTML = "We are open until 10 PM";
circleElement.className = 'open-circle';
messageElement.className = 'open-p';
} else {
// 21 pm to 8 am
messageElement.innerHTML = "We are closed until 8 AM";
circleElement.className = 'closed-circle';
messageElement.className = 'closed-p';
}
}
// run when starting
refreshStatus();
// updates every 8 seconds
setInterval(refreshStatus, 8000);
CSS:
/* Start indicator CSS */
.open-circle {
position: relative;
top: 23rem;
height: 1.5625rem;
width: 1.5625rem;
background-color: #00BF13;
border-radius: 50%;
display: inline-block;
}
.open-p {
position: relative;
top: 23rem;
color: #00BF13;
font-weight: bold;
display: inline-block;
width: 8rem;
}
.closed-circle {
position: relative;
top: 23rem;
height: 1.5625rem;
width: 1.5625rem;
background-color: #ea001d;
border-radius: 50%;
display: inline-block;
}
.closed-p {
position: relative;
top: 23rem;
color: #ea001d;
font-weight: bold;
display: inline-block;
width: 8rem;
}
/* End indicator CSS */
HTML:
<!-- Start status indicator -->
<div id="circle"></div>
<p id="message">We are open until 10 PM</p>
<script src="js/open-closed-indicator.js"></script>
<!-- End status indicator -->
You can achieve this using getDate() method for the Christmas period and use getDay() to check if it's a weekend.
Days in JS are 0 = sunday and 6 = Saturday. Refer to the comments in each line for more info.
For Christmas period dates you need to check whether it's the 11 months which is December and the date is 24 or 25th December.
To show different closed messages I am using JS ternary operator which helps to write less code and get the same results.
Live working demo.
var messageElement = document.getElementById("message");
var circleElement = document.getElementById("circle");
const refreshStatus = () => {
// Get dates/time/hours
let today = new Date(); //today date
let currentTime = today.getHours(); //get hours
let areWeekends = (today.getDay() == 6 || today.getDay() == 0) //get weekends
let santaDays = (today.getMonth() == 11 && (today.getDate() == 24 || today.getDate() == 25)) //get christmas dates
//Show available if this matches
if (currentTime >= 8 && currentTime <= 21 && !areWeekends && !santaDays) {
// Update text and add classes
messageElement.innerHTML = "We are open until 10 PM";
circleElement.className = 'open-circle';
messageElement.className = 'open-p';
} else {
//change text based on weekend / christmas or not - Using ternary operator Javascript
messageElement.innerHTML = `We are closed ${areWeekends ? ' - weekend' : santaDays ? 'Christmas' : 'until 8am'}`;
circleElement.className = 'closed-circle';
messageElement.className = 'closed-p';
}
}
// run when starting
refreshStatus();
// updates every 8 seconds
setInterval(refreshStatus, 8000);
/* Start indicator CSS */
.open-circle {
position: relative;
top: 23rem;
height: 1.5625rem;
width: 1.5625rem;
background-color: #00BF13;
border-radius: 50%;
display: inline-block;
}
.open-p {
position: relative;
top: 23rem;
color: #00BF13;
font-weight: bold;
display: inline-block;
width: 8rem;
}
.closed-circle {
position: relative;
top: 23rem;
height: 1.5625rem;
width: 1.5625rem;
background-color: #ea001d;
border-radius: 50%;
display: inline-block;
}
.closed-p {
position: relative;
top: 23rem;
color: #ea001d;
font-weight: bold;
display: inline-block;
width: 8rem;
}
/* End indicator CSS */
<!-- Start status indicator -->
<div id="circle"></div>
<p id="message">We are open until 10 PM</p>
<!-- //<script src="js/open-closed-indicator.js"></script>
-->
<!-- End status indicator -->
try this
// set your holidays
const holidays = [
{'2022-12-25' : 'christmas'},
{'2022-01-29' : 'testHoliday'},
]
const refreshStatus = () => {
// added code
let date = new Date();
let dayOfWeek = date.getDay(); // 6: saturday, 0: sunday
let today = date.getFullYear() + '-' + String(date.getMonth()+1).padStart(2, '0') + '-' + date.getDate(); // 2022-01-29
let isHoliday = holidays.filter(h => h[today]).length > 0 || dayOfWeek == 6 || dayOfWeek == 9;
//
// Set the current time
let currentDate = date.getHours();
// If the time is between 8 am and 10 pm
if (currentDate >= 8 && currentDate <= 21 && !isHoliday) {
// Update text and add classes
messageElement.innerHTML = "We are open until 10 PM";
circleElement.className = "open-circle";
messageElement.className = "open-p";
} else {
// 21 pm to 8 am
messageElement.innerHTML = "We are closed until 8 AM";
circleElement.className = "closed-circle";
messageElement.className = "closed-p";
}
};

Modifying JS code to remove DatePicker option

I'm trying to add a datepicker to a page I'm creating. Since I don't know much at all about Javascript I'm modifying an example I've found at https://code-boxx.com/simple-datepicker-pure-javascript-css/. I don't want any extra pages or files as I need the form I'm creating to be entirely self-contained. I've condensed it down to this:
<!DOCTYPE html>
<html>
<head>
<title>Simple Date Picker Example</title>
<style>
/* (A) POPUP */
.picker-wrap {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background: rgba(0,0,0,0.5);
opacity: 0;
visibility: hidden;
transition: opacity 0.2s;
}
.picker-wrap.show {
opacity: 1;
visibility: visible;
}
.picker-wrap .picker {
margin: 50vh auto 0 auto;
transform: translateY(-50%);
}
/* (B) CONTAINER */
.picker {
max-width: 300px;
background: #444444;
padding: 10px;
}
/* (C) MONTH + YEAR */
.picker-m, .picker-y {
width: 50%;
padding: 5px;
box-sizing: border-box;
font-size: 16px;
}
/* (D) DAY */
.picker-d table {
color: #fff;
border-collapse: separate;
width: 100%;
margin-top: 10px;
}
.picker-d table td {
width: 14.28%; /* 7 EQUAL COLUMNS */
padding: 5px;
text-align: center;
}
/* HEADER CELLS */
.picker-d-h td {
font-weight: bold;
}
/* BLANK DATES */
.picker-d-b {
background: #4e4e4e;
}
/* TODAY */
.picker-d-td {
background: #d84f4f;
}
/* PICKABLE DATES */
.picker-d-d:hover {
cursor: pointer;
/* UNPICKABLE DATES */
.picker-d-dd {
color: #888;
background: #4e4e4e;
}
</style>
<!-- (A) LOAD DATE PICKER -->
<!--<link href="dp-dark.css" rel="stylesheet">-->
<link href="dp-light.css" rel="stylesheet" />
<script src="datepicker.js"></script>
</head>
<body>
<!-- (B) THE HTML -->
<!-- (B1) INLINE DATE PICKER -->
<input type="text" id="input-inline" placeholder="Inline" />
<div id="pick-inline"></div>
<!-- (B2) POPUP DATE PICKER -->
<input type="text" id="input-pop" placeholder="Popup" />
<!-- (C) ATTACH DATE PICKER ON LOAD -->
<script>
window.addEventListener("load", function () {
// (C1) INLINE DATE PICKER
picker.attach({
target: "input-inline",
container: "pick-inline",
});
// (C2) POPUP DATE PICKER
picker.attach({
target: "input-pop",
});
});
</script>
</body>
<script>
var picker = {
// (A) ATTACH DATEPICKER TO TARGET
// 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
attach: function (opt) {
// (A1) CREATE NEW DATEPICKER
var dp = document.createElement("div");
dp.dataset.target = opt.target;
dp.dataset.startmon = opt.startmon ? "1" : "0";
dp.classList.add("picker");
if (opt.disableday) {
dp.dataset.disableday = JSON.stringify(opt.disableday);
}
// (A2) 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",
];
// (A3) 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);
// (A4) YEAR SELECT
var yRange = 10; // 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 + yRange; 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);
// (A5) DAY SELECT
var days = document.createElement("div");
days.classList.add("picker-d");
dp.appendChild(days);
// (A6) ATTACH DATE PICKER TO TARGET CONTAINER + DRAW THE DATES
picker.draw(select);
// (A6-I) INLINE DATE PICKER
if (opt.container) {
document.getElementById(opt.container).appendChild(dp);
}
// (A6-P) POPUP DATE PICKER
else {
// (A6-P-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;
// (A6-P-2) CREATE WRAPPER
var wrapper = document.createElement("div");
wrapper.id = "picker-" + uniqueID;
wrapper.classList.add("picker-wrap");
wrapper.appendChild(dp);
// (A6-P-3) ATTACH ONCLICK TO SHOW/HIDE DATEPICKER
var target = document.getElementById(opt.target);
target.dataset.dp = uniqueID;
target.readOnly = true; // Prevent onscreen keyboar on mobile devices
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");
}
});
// (A6-P-4) ATTACH POPUP DATEPICKER TO BODY
document.body.appendChild(wrapper);
}
},
// (B) DRAW THE DAYS IN MONTH
// el : HTML reference to either year or month selector
draw: function (el) {
// (B1) 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];
// (B2) 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;
// (B3) GENERATE DATE SQUARES (IN ARRAY FIRST)
var squares = [],
disableday = null;
if (parent.dataset.disableday) {
disableday = JSON.parse(parent.dataset.disableday);
}
// (B4) 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");
}
}
// (B5) DAYS OF MONTH
// (B5-1) ALL DAYS ENABLED, JUST ADD
if (disableday == null) {
for (var i = 1; i <= daysInMonth; i++) {
squares.push([i, false]);
}
}
// (B5-2) 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;
}
}
}
// (B6) 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");
}
}
// (B7) DRAW HTML
var daynames = ["Mon", "Tue", "Wed", "Thur", "Fri", "Sat"];
if (parent.dataset.startmon == "1") {
daynames.push("Sun");
} else {
daynames.unshift("Sun");
}
// (B7-1) HTML DATE 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;
}
// (B7-2) HTML DATE CELLS
var total = squares.length,
row = table.insertRow(),
today = new Date(),
todayDate = null;
if (
today.getUTCMonth() + 1 == month &&
today.getUTCFullYear() == year
) {
todayDate = today.getUTCDate();
}
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 {
if (i == todayDate) {
cell.classList.add("picker-d-td");
}
cell.classList.add("picker-d-d");
cell.addEventListener("click", function () {
picker.pick(this);
});
}
}
}
// (B7-3) ATTACH NEW CALENDAR TO DATEPICKER
days.innerHTML = "";
days.appendChild(table);
},
// (C) CHOOSE A DATE
// el : HTML reference to selected date cell
pick: function (el) {
// (C1) GET ALL COMPONENTS
var parent = el.parentElement;
while (!parent.classList.contains("picker")) {
parent = parent.parentElement;
}
// (C2) 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;
// (C3) UPDATE SELECTED DATE
document.getElementById(parent.dataset.target).value = fullDate;
// (C4) POPUP ONLY - CLOSE THE POPUP
if (parent.dataset.popup == "1") {
document
.getElementById("picker-" + parent.dataset.dpid)
.classList.remove("show");
}
},
};
</script>
</html>
Since I don't want the inline date picker and only want the pop-up date picker, I thought all I would need to do is remove this section:
<!-- (B1) INLINE DATE PICKER -->
<input type="text" id="input-inline" placeholder="Inline"/>
<div id="pick-inline"></div>
but when I do that the pop-up stops working as well. What do I need to change to remove the inline but just keep the pop-up?
You commented the template code for the inline date picker, but you have not commented the script for inline date picker.
Comment out the below code to make your solution working.
// Comment this code block in script
picker.attach({
target: "input-inline",
container: "pick-inline",
});
Why this was throwing error?
The datepicker was trying to find a target from dom having id input-inline. Since you have commented it out, it will not be available. Thats why it was stoping the execution of javascript. The code got broken there and the lines below that is not executed. This is why your popup date picker was also not working.
Working Fiddle
window.addEventListener("load", function () {
// (C1) INLINE DATE PICKER
// picker.attach({
// target: "input-inline",
// container: "pick-inline",
// });
// (C2) POPUP DATE PICKER
picker.attach({
target: "input-pop",
});
});
var picker = {
// (A) ATTACH DATEPICKER TO TARGET
// 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
attach: function (opt) {
// (A1) CREATE NEW DATEPICKER
var dp = document.createElement("div");
dp.dataset.target = opt.target;
dp.dataset.startmon = opt.startmon ? "1" : "0";
dp.classList.add("picker");
if (opt.disableday) {
dp.dataset.disableday = JSON.stringify(opt.disableday);
}
// (A2) 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",
];
// (A3) 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);
// (A4) YEAR SELECT
var yRange = 10; // 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 + yRange; 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);
// (A5) DAY SELECT
var days = document.createElement("div");
days.classList.add("picker-d");
dp.appendChild(days);
// (A6) ATTACH DATE PICKER TO TARGET CONTAINER + DRAW THE DATES
picker.draw(select);
// (A6-I) INLINE DATE PICKER
if (opt.container) {
document.getElementById(opt.container).appendChild(dp);
}
// (A6-P) POPUP DATE PICKER
else {
// (A6-P-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;
// (A6-P-2) CREATE WRAPPER
var wrapper = document.createElement("div");
wrapper.id = "picker-" + uniqueID;
wrapper.classList.add("picker-wrap");
wrapper.appendChild(dp);
// (A6-P-3) ATTACH ONCLICK TO SHOW/HIDE DATEPICKER
var target = document.getElementById(opt.target);
target.dataset.dp = uniqueID;
target.readOnly = true; // Prevent onscreen keyboar on mobile devices
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");
}
});
// (A6-P-4) ATTACH POPUP DATEPICKER TO BODY
document.body.appendChild(wrapper);
}
},
// (B) DRAW THE DAYS IN MONTH
// el : HTML reference to either year or month selector
draw: function (el) {
// (B1) 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];
// (B2) 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;
// (B3) GENERATE DATE SQUARES (IN ARRAY FIRST)
var squares = [],
disableday = null;
if (parent.dataset.disableday) {
disableday = JSON.parse(parent.dataset.disableday);
}
// (B4) 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");
}
}
// (B5) DAYS OF MONTH
// (B5-1) ALL DAYS ENABLED, JUST ADD
if (disableday == null) {
for (var i = 1; i <= daysInMonth; i++) {
squares.push([i, false]);
}
}
// (B5-2) 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;
}
}
}
// (B6) 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");
}
}
// (B7) DRAW HTML
var daynames = ["Mon", "Tue", "Wed", "Thur", "Fri", "Sat"];
if (parent.dataset.startmon == "1") {
daynames.push("Sun");
} else {
daynames.unshift("Sun");
}
// (B7-1) HTML DATE 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;
}
// (B7-2) HTML DATE CELLS
var total = squares.length,
row = table.insertRow(),
today = new Date(),
todayDate = null;
if (
today.getUTCMonth() + 1 == month &&
today.getUTCFullYear() == year
) {
todayDate = today.getUTCDate();
}
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 {
if (i == todayDate) {
cell.classList.add("picker-d-td");
}
cell.classList.add("picker-d-d");
cell.addEventListener("click", function () {
picker.pick(this);
});
}
}
}
// (B7-3) ATTACH NEW CALENDAR TO DATEPICKER
days.innerHTML = "";
days.appendChild(table);
},
// (C) CHOOSE A DATE
// el : HTML reference to selected date cell
pick: function (el) {
// (C1) GET ALL COMPONENTS
var parent = el.parentElement;
while (!parent.classList.contains("picker")) {
parent = parent.parentElement;
}
// (C2) 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;
// (C3) UPDATE SELECTED DATE
document.getElementById(parent.dataset.target).value = fullDate;
// (C4) POPUP ONLY - CLOSE THE POPUP
if (parent.dataset.popup == "1") {
document
.getElementById("picker-" + parent.dataset.dpid)
.classList.remove("show");
}
},
};
/* (A) POPUP */
.picker-wrap {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background: rgba(0, 0, 0, 0.5);
opacity: 0;
visibility: hidden;
transition: opacity 0.2s;
}
.picker-wrap.show {
opacity: 1;
visibility: visible;
}
.picker-wrap .picker {
margin: 50vh auto 0 auto;
transform: translateY(-50%);
}
/* (B) CONTAINER */
.picker {
max-width: 300px;
background: #444444;
padding: 10px;
}
/* (C) MONTH + YEAR */
.picker-m,
.picker-y {
width: 50%;
padding: 5px;
box-sizing: border-box;
font-size: 16px;
}
/* (D) DAY */
.picker-d table {
color: #fff;
border-collapse: separate;
width: 100%;
margin-top: 10px;
}
.picker-d table td {
width: 14.28%;
/* 7 EQUAL COLUMNS */
padding: 5px;
text-align: center;
}
/* HEADER CELLS */
.picker-d-h td {
font-weight: bold;
}
/* BLANK DATES */
.picker-d-b {
background: #4e4e4e;
}
/* TODAY */
.picker-d-td {
background: #d84f4f;
}
/* PICKABLE DATES */
.picker-d-d:hover {
cursor: pointer;
/* UNPICKABLE DATES */
.picker-d-dd {
color: #888;
background: #4e4e4e;
}
}
<!-- (B) THE HTML -->
<!-- (B1) INLINE DATE PICKER -->
<!-- <input type="text" id="input-inline" placeholder="Inline" />
<div id="pick-inline"></div> -->
<!-- (B2) POPUP DATE PICKER -->
<input type="text" id="input-pop" placeholder="Popup" />

Javascript and CSS code literally appearing on my HTML page

This is a simple calendar code. And my javascript and CSS codes are literally appearing beside my calendar. Does anyone know why something like this happens? I was using an online html/css/js editor and when I made my code into an HTML file, this happened. I've spent hours looking for a fault, but I can't find anything that is problematic.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>ICSI301 - Lab 2</title>
</head>
<body>
<h1 id="year">2021 School Calendar</h1>
<div class="calendar">
</div>
</body>
</html>
<script>
var monthNamesRy = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
var daysOfTheWeekRy = ["S", "M", "T", "W", "T", "F", "S"]
var d = new Date();
var year = d.getFullYear();
var thisMonth = d.getMonth();
var today = d.getDate();
//var nthday = d.getDay();
var daysOfTheMonthDiv = document.querySelectorAll(".daysOfTheMonth");
for (var month = 0; month < 12; month++) {
createCalendar(month);
}
function createCalendar(month) {
var monthDiv = createMonthHeader(month);
var firstDayOfTheMonth = getFirstDayOfTheMonth(year, month);
var daysinmonth = daysInMonth(year, month)
var counter = 0, order = 6;
for (var i = 0; i < firstDayOfTheMonth + 7; i++) {
order++;
createDay(month, " ", order, monthDiv);
}
for (var i = firstDayOfTheMonth; i < daysInMonth(year, month) + firstDayOfTheMonth; i++) {
counter++;
order++;
createDay(month, counter, order, monthDiv);
}
for (var i = firstDayOfTheMonth + daysinmonth; i < 6 * 7; i++) {
order++;
createDay(month, " ", order, monthDiv);
}
}
function createDay(month, counter, order, monthDiv) {
var day = document.createElement("div");
if (month == thisMonth && counter == today) {
day.setAttribute("class", "to day");
} else {
day.setAttribute("class", "day");
}
day.setAttribute("style", "order:" + order);
day.innerHTML = counter;
monthDiv.appendChild(day);
}
function createMonthHeader(month) {
var calendar = document.querySelector(".calendar");
var monthDiv = document.createElement("div");
monthDiv.setAttribute("class", "month");
calendar.appendChild(monthDiv);
var h4 = document.createElement("h4");
h4.innerHTML = monthNamesRy[month];
monthDiv.appendChild(h4);
for (var i = 0; i < 7; i++) {
var hday = document.createElement("div");
hday.setAttribute("class", "day OfWeek");
hday.setAttribute("style", "order:" + i);
hday.innerHTML = daysOfTheWeekRy[i].toUpperCase();
monthDiv.appendChild(hday);
}
return monthDiv;
}
function daysInMonth(year, month) {
return new Date(year, month + 1, 0).getDate();
}
function getMonthName(month) {
return monthNamesRy[month];
}
function getDayName(day) {
return daysOfTheWeekRy[day];
}
function getFirstDayOfTheMonth(y, m) {
var firstDay = new Date(y, m, 1);
return firstDay.getDay();
}
function getLastDayOfTheMonth(y, m) {
var lastDay = new Date(y, m + 1, 0);
return lastDay.getDay();
}
</script>
<style>
body * {
margin: 0;
padding: 0;
font-family: "Times New Roman";
}
.calendar, section {
max-width: 50rem;
}
.day {
width: 1.5em;
height: 1.5em;
}
.day:nth-of-type(-n+7) {
background-color: #7CFC00;
}
.to.day {
background: aquamarine;
}
.month {
width: calc(1.5em * 8);
padding: 1em;
}
h4 {
font-size: 1em;
text-transform: uppercase;
}
h1#year {
font-size: 3em;
height: 29px;
font-weight: normal;
padding: 1em 1em .5em 1em;
margin-bottom: .5em;
color: #006400;
}
body, body * {
display: flex;
justify-content: center;
}
h4 {
justify-content: center;
flex: 1 0 100%;
}
h1 {
justify-content: center;
align-self: stretch;
}
.calendar, .month {
flex-wrap: wrap;
}
.month {
align-items: flex-start;
border: 3px double black;
margin: 5px;
}
.day {
border: 1px solid black;
align-items: center;
justify-content: center;
}
</style>
Move the script and style to the head
change this
var daysOfTheMonthDiv = document.querySelectorAll(".daysOfTheMonth");
for (var month = 0; month < 12; month++) {
createCalendar(month);
}
to
window.addEventListener("load",function() { // wait for page load
var daysOfTheMonthDiv = document.querySelectorAll(".daysOfTheMonth");
for (var month = 0; month < 12; month++) {
createCalendar(month);
}
})
As Chris noticed, you have a very disruptive style entry
body,
body * {
display: flex;
justify-content: center;
}
I moved that to just under the other body style and now had to add
script,
style {
display: none
}
to stop the disruption
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>ICSI301 - Lab 2</title>
<script>
var monthNamesRy = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
var daysOfTheWeekRy = ["S", "M", "T", "W", "T", "F", "S"]
var d = new Date();
var year = d.getFullYear();
var thisMonth = d.getMonth();
var today = d.getDate();
//var nthday = d.getDay();
window.addEventListener("load", function() {
var daysOfTheMonthDiv = document.querySelectorAll(".daysOfTheMonth");
for (var month = 0; month < 12; month++) {
createCalendar(month);
}
});
function createCalendar(month) {
var monthDiv = createMonthHeader(month);
var firstDayOfTheMonth = getFirstDayOfTheMonth(year, month);
var daysinmonth = daysInMonth(year, month)
var counter = 0,
order = 6;
for (var i = 0; i < firstDayOfTheMonth + 7; i++) {
order++;
createDay(month, " ", order, monthDiv);
}
for (var i = firstDayOfTheMonth; i < daysInMonth(year, month) + firstDayOfTheMonth; i++) {
counter++;
order++;
createDay(month, counter, order, monthDiv);
}
for (var i = firstDayOfTheMonth + daysinmonth; i < 6 * 7; i++) {
order++;
createDay(month, " ", order, monthDiv);
}
}
function createDay(month, counter, order, monthDiv) {
var day = document.createElement("div");
if (month == thisMonth && counter == today) {
day.setAttribute("class", "to day");
} else {
day.setAttribute("class", "day");
}
day.setAttribute("style", "order:" + order);
day.innerHTML = counter;
monthDiv.appendChild(day);
}
function createMonthHeader(month) {
var calendar = document.querySelector(".calendar");
var monthDiv = document.createElement("div");
monthDiv.setAttribute("class", "month");
calendar.appendChild(monthDiv);
var h4 = document.createElement("h4");
h4.innerHTML = monthNamesRy[month];
monthDiv.appendChild(h4);
for (var i = 0; i < 7; i++) {
var hday = document.createElement("div");
hday.setAttribute("class", "day OfWeek");
hday.setAttribute("style", "order:" + i);
hday.innerHTML = daysOfTheWeekRy[i].toUpperCase();
monthDiv.appendChild(hday);
}
return monthDiv;
}
function daysInMonth(year, month) {
return new Date(year, month + 1, 0).getDate();
}
function getMonthName(month) {
return monthNamesRy[month];
}
function getDayName(day) {
return daysOfTheWeekRy[day];
}
function getFirstDayOfTheMonth(y, m) {
var firstDay = new Date(y, m, 1);
return firstDay.getDay();
}
function getLastDayOfTheMonth(y, m) {
var lastDay = new Date(y, m + 1, 0);
return lastDay.getDay();
}
</script>
<style>
body * {
margin: 0;
padding: 0;
font-family: "Times New Roman";
}
body,
body * {
display: flex;
justify-content: center;
}
script,
style {
display: none
}
.calendar,
section {
max-width: 50rem;
}
.day {
width: 1.5em;
height: 1.5em;
}
.day:nth-of-type(-n+7) {
background-color: #7CFC00;
}
.to.day {
background: aquamarine;
}
.month {
width: calc(1.5em * 8);
padding: 1em;
}
h4 {
font-size: 1em;
text-transform: uppercase;
}
h1#year {
font-size: 3em;
height: 29px;
font-weight: normal;
padding: 1em 1em .5em 1em;
margin-bottom: .5em;
color: #006400;
}
h4 {
justify-content: center;
flex: 1 0 100%;
}
h1 {
justify-content: center;
align-self: stretch;
}
.calendar,
.month {
flex-wrap: wrap;
}
.month {
align-items: flex-start;
border: 3px double black;
margin: 5px;
}
.day {
border: 1px solid black;
align-items: center;
justify-content: center;
}
</style>
</head>
<body>
<h1 id="year">2021 School Calendar</h1>
<div class="calendar"></div>
</body>
</html>
This is more interesting than it seems at first. It's possible to solve the problem by moving the script to the head, but the content of script tags and style tags do not normally display in browsers. The reason they are displaying in this case is that the css is forcing the content of these tags to display.
The browser's css has
script {
display: none;
}
And this is overridden by these lines:
body, body * {
display: flex;
justify-content: center;
}
Browsers pull the invalidly-positioned tags into the body when building the DOM, and then apply this display attribute... which means the code runs, but it also shows on the page.
It can be fixed by moving the script tag, but that doesn't actually address the real cause of the problem

I want to change background image by time of day

I want to change background image during particular part of day using JavaScript. So, i want from 6:00 to 20:00 daytime pic and from 20-06 night time pic. I am learning JS last couple of months so i m quite new to this.I created clock also.
I tried last days by Google it, still nothing, no solution. Please help.
My html :
<div class="banner">
<div class="image-day" id="img-day"></div>
<div class="image-night" id="img-night"></div>
</div>
CSS:
.banner {
min-height: 100vh;
position: relative;
display: grid;
place-items: center;
text-align: center;
}
.image-day {
position: absolute;
background: url(../images/bluesky.jpg)no-repeat center center/cover;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.image-night {
position: absolute;
background: url(../images/nightime.jpg)no-repeat center center/cover;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
JS clock :
setInterval(displayClock, 500)
function displayClock() {
var time = new Date();
var hrs = time.getHours();
var min = time.getMinutes();
var sec = time.getSeconds();
if (hrs > 12) {
hrs = hrs + 0;
}
if (hrs == 0) {
hrs = 12;
}
if(hrs < 10) {
hrs = '0' + hrs;
}
if (min < 10) {
min = '0' + min;
}
if (sec < 10) {
sec = '0' + sec;
}
document.getElementById('clock').innerHTML = hrs + ':' + min + ':' + sec;
}
You can change css properties of a dom element by using the style property like :
<DOM element>.style.<css property> = <value>
In your case to change the background image you may use something like this :
document.querySelector(".banner").style.backgroundImage="url('../images/nightime.jpg')"
Since the display clock method is already running every 5 seconds you may add the following to check if hour is greater than 6 and less than 20
if(time.getHours()>=6&&time.getHours()<20)
{
document.querySelector(".banner").style.backgroundImage="url('../images/bluesky.jpg')";
}else{
document.querySelector(".banner").style.backgroundImage="url('../images/nightime.jpg')"
}
Find a demo in this bin : demo . Open the demo and try changing your system time

Categories