I have the following code:
const calendarHeading = (month, year) =>{
let monthH3 = document.createElement('h3')
monthH3.classList.add('calendar__heading-month')
monthH3.innerHTML = monthObjects[month].month
let yearSpan = document.createElement('span')
yearSpan.classList.add('calendar__heading-year')
yearSpan.innerHTML = year
let targetDiv = document.querySelector('.calendar__heading')
targetDiv.appendChild(monthH3)
document.querySelector('.calendar__heading-month').appendChild(yearSpan)
};
Pretty much I am creating an H3 element and a Span element.
I then attach the h3 element to the already created div in the html.
I then attach the span to the newly created h3 node.
My question is, is there a way to do this in one line? Or am I overthinking things, I am noob i am sorry :(
CodePudding user response:
You're appending two separate elements to two other separate elements, so there need to be (or should be) at least two separate statements. This could be done pretty concisely by just writing out the HTML markup instead of constructing elements with .createElement
.
const calendarHeading = (month, year) =>{
document.querySelector('.calendar__heading').insertAdjacentHTML(
'beforeend',
`<h3 >${monthObjects[month].month}</h3>`
);
document.querySelector('.calendar__heading-month').insertAdjacentHTML(
'beforeend',
`<span >${year}</span>`
);
};
That said, both this code (and your original code) has a potential vulnurability - if the year
argument or the monthObjects
object is untrustworthy (such as from an external API), inserting HTML can result in arbitrary code execution, which would be a problem in some circumstances. If that's something you might be concerned about, things will have to become more verbose (such as with your original code plus use of .textContent
instead of .innerHTML
).
CodePudding user response:
that should be enough...
const calendarHeading = (month, year) =>
{
let targetDiv = document.querySelector('.calendar__heading')
, monthH3 = document.createElement('h3')
monthH3.className = 'calendar__heading-month'
monthH3.innerHTML = `${monthObjects[month].month}<span >${year}</span>`
targetDiv.appendChild(monthH3)
}
CodePudding user response:
This would be one way to do it, it isn't exactly less lines per se, but it feels less convoluted to me. Added some comments in the code that I hope you find helpful.
I am by no means an expert, just trying to provide a different perspective.
This solution makes use of template literals and the DOMParser object to achieve what I believe you are asking.
Happy coding!
const calendarHeading = (month, year) => {
//Not sure what your month object looks like, but adjust as needed
const monthObject = {
Jan: "I am Jan",
Feb: "I am Feb",
Mar: "I am Mar",
}
//Write up your HTML as you desire using template literals
let htmlString = `<h3 >${monthObject[month]} <span >${year}</span></h3>`;
//Create a DOMParser object, parse your HTML string
const parser = new DOMParser();
const newNode = parser.parseFromString(htmlString, "text/xml");
//Select target element and append using the new node
let targetDiv = document.querySelector('.calendar__heading')
targetDiv.appendChild(newNode.documentElement);
};
//Log to console
calendarHeading("Jan", 1991)
body {
background: transparent;
/* Make it white if you need */
color: #000;
padding: 0 24px;
margin: 0;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="src/style.css">
</head>
<body>
<div ></div>
<script src="src/script.js"></script>
</body>
</html>