element.innerHTML is not a function and option with an object value - javascript

Hi I'm trying to do the following in javascript, basically, I have an input that I will get the input text from an array, and I need each option to have an object as a value so I can use some attributes of my object
const data = [
{
name: "SIMPLES NACIONAL – MEI",
funcionarioIncrease: 49.99,
socioIncrease: 0,
FATURAMENTO: [
{
name: "ATÉ 30.000,00",
value: 49.99,
},
{
name: "De 30.001,00 a 50.000,00 ",
value: 99.99,
},
],
},
{
name: "SIMPLES NACIONAL – SERVIÇOS",
funcionarioIncrease: 25,
socioIncrease: 25,
FATURAMENTO: [
{
name: "ATÉ 30.000,00",
value: 149.99,
},
{
name: "De 30.001,00 a 50.000,00 ",
value: 199.99,
},
],
},
];
const Modes = () => {
if (data instanceof Array) {
return data.map((value) => {
return {
name: value.name,
funcionarioIncrease: value.funcionarioIncrease,
socioIncrease: value.socioIncrease,
faturamento: value.FATURAMENTO,
};
});
} else {
return null;
}
};
let results = function () {
const modes = Modes();
let selectHeader = document.querySelectorAll(".select__header");
let selectItem = document.querySelectorAll(".select__item");
modes.map((value) => {
let element = document.createElement("div");
element.classList.add("select__item");
element.innerHTML(value.name);
});
selectHeader.forEach((item) => {
item.addEventListener("click", selectToggle);
});
selectItem.forEach((item) => {
item.addEventListener("click", selectChoose);
});
function selectToggle() {
this.parentElement.classList.toggle("is-active");
}
function selectChoose() {
let text = this.innerText,
select = this.closest(".select"),
currentText = select.querySelector(".select__current");
currentText.innerText = text;
select.classList.remove("is-active");
}
};
results();
.select {
position: relative;
width: 100%;
}
.select.is-active .select__body {
display: block;
}
.select__header {
border: 1px solid #ccc;
cursor: pointer;
display: flex;
}
.select__current {
font-size: 18px;
line-height: 24px;
padding: 8px;
}
.select__icon {
align-items: center;
display: flex;
flex-shrink: 0;
justify-content: center;
height: 40px;
margin-left: auto;
text-align: center;
width: 40px;
}
.select__body {
border: 1px solid #cccccc;
border-top: 0;
display: none;
left: 0;
position: absolute;
right: 0;
top: 100%;
}
.select__item {
cursor: pointer;
font-size: 16px;
line-height: 24px;
padding: 8px;
}
.select__item:hover {
background-color: #f2f2f2;
}
<div class="service_mode flex">
<div class="select is-active">
<div class="select__header">
<span class="select__current">Value 1</span>
<div class="select__icon">×</div>
</div>
<div class="select__body"></div>
</div>
</div>
for some reason, I am not able to map my array and add its inner HTML as the attribute name of my object and I am also not finding a way to link the option to that object.

As it says element.innerHTML is not a function. Instead of element.innerHTML(value.name);, write element.innerHTML = value.name;
So your code looks like:
modes.map((value) => {
let element = document.createElement("div");
element.classList.add("select__item");
element.innerHTML = value.name;
});

Try this below:
element.innerHTML = value.name;

Related

Why isn't my javascript code scrolling on website?

This code works great when I test it, but when it's embedded into the website it no longer scrolls down to reveal the images below. It's static. I've tried adding overflow:visible but to no avail. Any idea on what I need to change? Here is a link to the website page where it's not working. https://den-of-dreamers-45.showitpreview.com/new-page-1
Thank you!
var PHOTODATA = [{
id: 1,
category: 'cottagecore',
imageUrl: 'https://static.showit.co/file/U0ucmfm5T22dFNiq2ejzSw/118367/pexels-nadi-lindsay-4990969_1.jpg'
},
{
id: 2,
category: 'cottagecore',
imageUrl: 'https://static.showit.co/file/I1dybkKETdq4ijozGfDs3w/118367/pexels-anete-lusina-6354251.jpg'
},
{
id: 3,
category: 'cottagecore',
imageUrl: 'https://static.showit.co/file/MpOOhlgLSZ2b__8uTuKBJQ/118367/pexels-photo-10213893.jpg'
},
{
id: 4,
category: 'academia',
imageUrl: 'https://static.showit.co/file/5xDz3V4KTi63UoOKKbAlYQ/118367/ashley-winkler-yzhnw0qiqo0-unsplash.jpg'
},
{
id: 5,
category: 'academia',
imageUrl: 'https://static.showit.co/file/ybGpWcTnQmS-beO1R4LqqQ/118367/mel-poole-ppuz3fosru8-unsplash.jpg'
},
{
id: 6,
category: 'academia',
imageUrl: 'https://static.showit.co/file/9td2KJYPQuypgOrKrM20SA/118367/pexels-roman-odintsov-8349176.jpg'
},
{
id: 7,
category: 'ethereal',
imageUrl: 'https://static.showit.co/file/RjY3KcUERsWnjlKbWmkepw/118367/screen_shot_2022-02-03_at_6_43_28_pm.png'
},
{
id: 8,
category: 'ethereal',
imageUrl: 'https://static.showit.co/file/cgx9GCzlRQSoAufxS9dw3w/118367/pexels-ron-lach-10536607.jpg'
},
{
id: 9,
category: 'ethereal',
imageUrl: 'https://static.showit.co/file/FZICN6rlRkiZ4hAkdxdc0Q/118367/pexels-tatiana-twinslol-5444997.jpg'
},
{
id: 10,
category: 'tropical',
imageUrl: 'https://static.showit.co/file/iaEUuhQiQkajqRkvzCuibw/118367/pexels-alan-cabello-1173217.jpg'
},
{
id: 11,
category: 'tropical',
imageUrl: 'https://static.showit.co/file/HpWQ15TsSFKlaQEWXtcBcQ/118367/pexels-michael-block-3225531_1.jpg'
},
{
id: 12,
category: 'tropical',
imageUrl: 'https://static.showit.co/file/LXrsgIh6TA6iG0JSuAMlYw/118367/pexels-ryan-delfin-2270389.jpg'
}
];
{ /*Create a component of the filter panel*/ }
var FilterPanel = React.createClass({
displayName: "FilterPanel",
render: function() {
return /*#__PURE__*/ (
React.createElement("a", {
onClick: this.props.onClick
}, this.props.category));
}
});
{ /*Create a layout component for one photo*/ }
var Photo = React.createClass({
displayName: "Photo",
render: function() {
return /*#__PURE__*/ (
React.createElement("div", {
className: "photo-container",
"data-category": this.props.category
}, /*#__PURE__*/ React.createElement("img", {
src: this.props.imageUrl
})));
}
});
{ /*Create a final collection of photos in photoGallery*/ }
var PhotoGallery = React.createClass({
displayName: "PhotoGallery",
getInitialState: function() {
return {
displayedCategories: PHOTODATA,
active: false
};
},
toggleActive: function() {
this.setState({
active: !this.state.active
});
},
selectCategory: function(element) {
console.log('element is: ' + element);
var categoryName = element.toLowerCase();
var displayedCategories = PHOTODATA.filter(function(el) {
var searchValue = el.category.toLowerCase();
return searchValue.indexOf(categoryName) !== -1;
});
this.setState({
displayedCategories: displayedCategories
});
},
resetFilter: function(element) {
this.setState({
displayedCategories: PHOTODATA
});
},
render: function() {
var buttonClass = this.state.active ? 'active' : '';
var categoryToSelect = this.selectCategory;
var getUniqueCategories = [];
PHOTODATA.forEach(function(el) {
if (getUniqueCategories.indexOf(el.category) === -1) getUniqueCategories.push(el.category);
});
return /*#__PURE__*/ (
React.createElement("div", {
className: "overlay-photogallery"
}, /*#__PURE__*/
React.createElement("div", {
className: "filter-panel"
},
getUniqueCategories.map(function(el, i) {
var boundClick = categoryToSelect.bind(null, el);
return /*#__PURE__*/ React.createElement(FilterPanel, {
onClick: boundClick,
category: el,
key: i
});
}), /*#__PURE__*/
React.createElement("a", {
className: "resetBtn",
onClick: this.resetFilter
}, " Reset Filter ")), /*#__PURE__*/
React.createElement("div", {
className: "PhotoGallery"
},
this.state.displayedCategories.map(function(el) {
return /*#__PURE__*/ React.createElement(Photo, {
key: el.id,
imageUrl: el.imageUrl,
category: el.category
});
}))));
}
});
ReactDOM.render( /*#__PURE__*/ React.createElement(PhotoGallery, null), document.getElementById('main'));
.PhotoGallery {
display: flex;
justify-content: center;
align-items: center;
flex-wrap: wrap;
overflow: visible;
}
.photo-container {
margin: 5px;
position: relative;
animation: fadeUP .5s;
}
#media screen and (min-width: 1024px) {
.photo-container img {
max-width: 300px;
width: 100%;
}
}
#media screen and (max-width:640px) {
.photo-container img {
max-width: 140px;
width: 100%;
}
}
#keyframes fadeUP {
from {
top: -40px;
opacity: 0;
}
to {
top: 0;
opacity: 1
}
}
#media screen and (min-width: 1024px) {
.filter-panel {
display: flex;
padding: 25px;
flex-wrap: wrap;
justify-content: center;
align-items: center;
}
}
#media screen and (max-width:640px) {
.filter-panel {
display: flex;
flex-wrap: wrap;
padding: 10px;
justify-content: center;
align-items: center;
}
}
#media screen and (min-width: 1024px) {
.filter-panel a {
display: inline-block;
background: #fff;
position: relative;
padding: 10px 25px;
font-size: 16px;
color: #000;
border: 1px solid #000;
margin: 5px 15px;
transition: .25s ease-in;
border-radius: 4px;
font-family: cormorant;
letter-spacing: 0;
text-transform: lowercase;
cursor: pointer;
}
}
#media screen and (max-width:640px) {
.filter-panel a {
display: flex;
background: #fff;
position: relative;
padding: 5px 18px;
font-size: 16px;
color: #000;
border: 1px solid #000;
margin: 5px 3px;
transition: .25s ease-in;
border-radius: 4px;
font-family: cormorant;
letter-spacing: 0;
text-transform: lowercase;
cursor: pointer;
}
}
.filter-panel a:hover {
background: #fff;
}
.filter-panel a.active {
top: -8px;
}
.filter-panel a.resetBtn {
background: #b37351;
}
.filter-panel a.resetBtn:hover {
background: #b37351;
}
<title>Image filter with React.js (get from jSON)</title>
<link rel="stylesheet" href="css/style.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.0/react.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.0/react-dom.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.6.15/browser.js"></script>
<div id="main"></div>

How to check if all dom-elements in an object containing a value

I saved all dom-elements in an object. I want that my Script is able to check every time when there is some input if all input fields are empty anymore. If yes, the button should still be disabled, otherwise the forward button is enabled and the user can click to the next page.
Ways like like using querySelectorAll input field etc. are working but I want that this is working with using the object.
The "areTruthy" variable is directly true if one input field is not empty anymore but it should only be true if all input fields are true. Where is my code wrong?
window.onload = () => {
forward = document.getElementById("forward");
input = {
caseNumber: {
month: document.getElementById("month"),
year: document.getElementById("year"),
},
clientsInformation: {
gender: document.getElementById("gender"),
inpName: document.getElementById("inpName"),
},
adress: {
street: document.getElementById("street"),
houseNumber: document.getElementById("house-number"),
postCode: document.getElementById("postCode"),
city: document.getElementById("city"),
receiver: document.getElementById("receiver"),
},
};
addEventListener("input", () => {
for (parts in input) {
const areTruthy = Object.values(input[parts]).every((value) => value != "");
if (areTruthy) {
forward.style.backgroundColor = "rgb(77,55,120)";
forward.style.color = "white";
forward.disabled = false;
forward.style.transition = "1s ease";
forward.addEventListener("click", () => {
window.open("case.html");
});
} else {
forward.style.backgroundColor = "rgb(191,191,191)";
forward.style.color = "black";
forward.disabled = true;
}
}
});
};
<body>
<h3>Fill in all fields</h3>
<div id = "wrapper">
<div id = "caseNumber">
<label id = "caseLabel"></label>
<input id = "month" placeholder="Zahlenfolge">
<input id = "year" placeholder = "Jahr">
</div>
<div id = "name">
<label for = "name">Name</label>
<select id = "gender">
<option>Herr</option>
<option>Frau</option>
</select>
<input id = "inpName" placeholder = "Name">
</div>
<div id = "adress">
<label for = "adress">Adresse</label>
<div id = "adressWrapper1">
<input placeholder = "Straße" id = "street" >
<input placeholder = "Hausnummer" id = "house-number">
<input placeholder = "Postleitzahl" id = "postCode" >
</div>
<div id = "adressWrapper2">
<input placeholder = "Stadt" id = "city" >
<input placeholder = "Adressant" id = "receiver" >
</div>
</div>
</div>
</div>
<div class = "button-bar">
<div class = "nav-inner" id = "backward"><a class = "nav-inner" href= "#http://127.0.0.1:5500/pages/client.html" ></a> < Zurück</div>
<div class = "nav-inner" id = "forward"> Weiter ></div>
</div>
</body>
</html>
.navbar {
display: flex;
list-style: none;
background-color: rgb(77, 55, 120);
margin: 0;
position: fixed;
width: 100%;
gap: 4rem;
height: 50px;
text-align: center;
line-height: 45px;
left: 0;
top: 0;
}
.nav-text {
text-decoration: none;
color: white;
width: auto;
cursor: pointer;
font-size: 18px;
padding-bottom: 5px;
}
#wrapper {
margin-top: 10rem;
margin-left: 5rem;
display: sticky;
}
#caseNumber {
display: block;
}
input::placeholder {
font-size: 1rem;
text-align: center;
line-height: 19rem;
}
.button-bar {
position: fixed;
bottom: 0;
width: 100%;
display: flex;
margin: 0;
left: 0;
}
.nav-inner {
cursor: pointer;
width: 50%;
text-align: center;
line-height: 83px;
}
#backward {
background-color: rgb(101, 93, 93);
color: white;
}
#forward {
background-color: rgb(191, 191, 191);
}
h3 {
left: 20vh;
position: absolute;
font-size: 24px;
margin-top: 0.5rem;
}
#caseNumber {
position: absolute;
left: 20vh;
margin-top: 6.5rem;
text-align: left;
}
#name {
position: absolute;
left: 20vh;
margin-top: 12.5rem;
}
label {
display: inline-block;
text-align: left;
width: 140px;
font-size: 20px;
}
input,
select {
width: 30vh;
height: 5vh;
font-size: 19px;
border-radius: 5px;
border-style: solid;
border: 1px solid;
}
#adress {
position: absolute;
left: 20vh;
margin-top: 18.5rem;
max-width: 40rem;
display: block;
}
#adressWrapper1 {
display: flex;
gap:5vh;
flex-direction: column;
left: 18vh;
position: absolute;
top:0rem
}
#adressWrapper2 {
display: flex;
gap:5vh;
flex-direction: column;
position: absolute;
left: 50vh;
top:0rem
}
You are not checking input values. Also you are only checking every on child per parent object key, not on all children together so you need to lift if outside for
addEventListener("input", () => {
let allFilled = true;
for (parts in input) {
const anyEmpty = Object.values(input[parts]).some(el => el.value == "");
if (anyEmpty) {
allFilled = false;
break;
}
}
if (allFilled) {
forward.style.backgroundColor = "rgb(77,55,120)";
forward.style.color = "white";
forward.disabled = false;
forward.style.transition = "1s ease";
forward.addEventListener("click", () => {
window.open("case.html");
});
} else {
forward.style.backgroundColor = "rgb(191,191,191)";
forward.style.color = "black";
forward.disabled = true;
}
});
};
If you want to see what is exactly happening you can use this to log
const anyEmpty = Object.values(input[parts]).some((el) => {
console.log(el, el.value, el.value == "");
return el.value == "";
});

How to filter the objects based on user input and map their corresponded array?

This is bugging me quite a bit. I hope someone can help me with it. I'm doing this in React.
Here is the data (objects that have an array inside):
{
"Susan": {
"likes": [
"shopping",
"skiing",
"surfing"
],
"hates": [
"cycling",
"reading",
"cleaning"
]
},
"Andrew": {
"likes": [
"driving",
"hiking",
"coding"
],
"hates": [
"dancing",
"running",
"cleaning dishes"
]
}
}
Now, in this case, I would like to display/map both arrays ("likes" and "hates") based on user choosing "Susan" or "Andrew". I just can't seem to logical connect this.
Let's say user input is a variable:
let input = "Susan"
I have something like:
Object.values(data).filter((val) => {
if(input === val) {
return val;
}
}).map((obj) => {
return (
<div>
<p> {obj.likes} </p>
<p> {obj.hates} </p>
</div>
);
})
I know there has to be some kind of binding with the keys, but I don't know how to do that.
Your help is very much appreciated!
I think you may be overcomplicating this if I'm not misunderstanding the question.
data['Susan'] will get you an entry with the 'likes' and 'hates' arrays. You can use it like this:
const data = {
"Susan": {
"likes": [
"shopping",
"skiing",
"surfing"
],
"hates": [
"cycling",
"reading",
"cleaning"
]
},
"Andrew": {
"likes": [
"driving",
"hiking",
"coding"
],
"hates": [
"dancing",
"running",
"cleaning dishes"
]
}
}
const createDiv = (name) => {
let entry = data[name];
return (
<div>
<p> {entry.likes} </p>
<p> {entry.hates} </p>
</div>
);
}
let element = createDiv('Susan');
You should filter your data as entries i.e. Object.entries so that you retain the object key (name) and the value (likes and dislikes).
I added a debounce to the input field so that entries only get filtered/rendered when the user stops typing.
const
filteredResults = document.querySelector('#filtered-results'),
searchTerm = document.querySelector('#search-term');
const render = () => {
const filtered = searchTerm.value.trim().length
? Object.entries(data)
.filter(([key, value]) => searchTerm.value.includes(key))
: Object.entries(data);
filteredResults.innerHTML = `
<ul class="entries">
${filtered.map(([key, { likes, hates }]) => {
return `
<li>
<h1>${key}</h1>
<h2>Likes</h2>
<ul class="sublist">
${likes.map(like => `<li>${like}</li>`).join('')}
</ul>
<h2>Hates</h2>
<ul class="sublist">
${hates.map(hate => `<li>${hate}</li>`).join('')}
</ul>
</li>
`;
}).join('')}
</ul>
`;
};
const main = () => {
render();
searchTerm.addEventListener('keyup', handleKeyUp);
};
const debounce = (callback, wait) => {
let timeoutId = null;
return (...args) => {
window.clearTimeout(timeoutId);
timeoutId = window.setTimeout(() => {
callback.apply(null, args);
}, wait);
};
};
const handleKeyUp = debounce((event) => {
render();
}, 500);
const data = {
"Susan": {
"likes": [ "shopping", "skiing", "surfing" ],
"hates": [ "cycling", "reading", "cleaning" ]
},
"Andrew": {
"likes": [ "driving", "hiking", "coding" ],
"hates": [ "dancing", "running", "cleaning dishes" ]
}
};
main();
*, *:before, *:after {
box-sizing: border-box;
}
html, body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
h1, h2 {
margin: 0;
padding: 0;
font-weight: normal;
}
body {
display: flex;
flex-direction: column;
align-items: center;
padding: 1rem;
}
.entries {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
margin: 0;
padding: 0;
list-style-type: none;
gap: 1rem;
padding: 0.5rem;
}
.entries > li {
display: flex;
flex-direction: column;
min-width: 20rem;
background: #EEE;
border: thin solid #AAA;
padding: 0.5rem;
}
.entries li h1 {
font-weight: bold;
font-size: 1.25rem;
margin: 0.25rem 0 0.5rem 0;
}
.entries li h2 {
font-weight: bold;
font-size: 1rem;
margin: 0.125rem 0 0.25rem 0;
}
.sublist {
margin: 0;
padding: 0;
list-style-type: none;
}
.sublist > li {
display: inline-block;
margin-right: 0.5rem;
padding: 0.25rem;
border: thin solid #AAA;
}
<input type="text" id="search-term" placeholder="Filter by name" />
<hr />
<div id="filtered-results"></div>

push new items to an object from fields

actually i'm about to create a calendar with events, and i want to add new events with a form, let me explain.
i have:
let eventsArray = [
{
id: 'my event name',
date: '2021/08/23',
content: 'my events description',
},
];
result and demo:
https://jsfiddle.net/er73av8h/
Now, i want to populate this object through 3 field maybe (id, date and content), but i'm not sure on how i can do this.
I made a very simple example of what you want.
If my example works for you I will write a description of how this code works.
Example:
let eventsArray = [
{
id: 'my event name',
date: '2021/08/23',
content: 'my events description',
},
];
let wrp = document.getElementById('calendar');
function addInfoInCalendar() {
wrp.innerHTML = '';
for (const iterator of eventsArray) {
wrp.innerHTML += '<div>' + iterator.id + ' ' + iterator.date + ' ' + iterator.content + '</div>';
}
}
addInfoInCalendar();
let formWrp = document.getElementById('myForm');
let f_id = myForm.querySelectorAll('[name="id"]')[0];
let f_date = myForm.querySelectorAll('[name="date"]')[0];
let f_content = myForm.querySelectorAll('[name="content"]')[0];
let f_button = myForm.querySelector('button');
f_button.addEventListener('click', addNewInfo);
function addNewInfo() {
eventsArray.push({
id: f_id.value,
date: f_date.value,
content: f_content.value
});
addInfoInCalendar();
}
<div id="myForm">
<input type="text" name="id">
<input type="date" name="date">
<input type="text" name="content">
<button>Send</button>
</div>
<div id="calendar"></div>
Example 2:
In this example is your code! I added a few new lines at the end of the code and marked them with a comment.
let eventsArray = [
{
id: 'My Name',
date: '2021/08/23',
content: 'my events description',
source: '#',
},
];
let today = new Date(),
currentMonth = today.getMonth(),
currentYear = today.getFullYear();
// array for weeks
const weekdays = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
// array for month
const months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
// structure
let structureCalendar = createElement('div', window.root, {
id: 'structureCalendar',
}),
// header
calendarHeader = createElement('header', structureCalendar, {}),
// header columns left center and right
headerLeft = createElement('div', calendarHeader, { className: 'left' }),
headerCenter = createElement('div', calendarHeader, { className: 'center' }),
headerRight = createElement('div', calendarHeader, { className: 'right' }),
// inside left column
buttonPrev = createElement('button', headerLeft, { textContent: 'Previous' }),
buttonNext = createElement('button', headerLeft, { textContent: 'Next' }),
centerTitle = createElement('h1', headerCenter, {
textContent: months[currentMonth] + ' ' + currentYear,
}),
// calendar body
calendarBody = createElement('div', structureCalendar, { id: 'calendar' }),
weekdayBody = createElement('ul', calendarBody, { id: 'weekdays' }),
daysBody = createElement('ul', calendarBody, { id: 'days' });
// init calendar
showCalendar(currentMonth, currentYear);
// map week days
weekdays.map((item, i) =>
// change to monday
today.getDay() - 0 == i
? createElement('li', weekdayBody, { className: 'today', textContent: item })
: createElement('li', weekdayBody, { textContent: item })
);
// buttons next prev
buttonPrev.onclick = () => prev();
buttonNext.onclick = () => next();
// generate calendar
function showCalendar(month, year) {
// first day - 1
let firstDay = new Date(year, month).getDay() - 1;
// clear preview content
daysBody.textContent = '';
// filing data about month and in the page via DOM.
centerTitle.textContent = months[month] + ' ' + year;
// creating all cells
let date = 1;
for (let i = 0; i < 6; i++) {
//creating individual cells, filing them up with data.
for (let j = 0; j < 7; j++) {
if (i === 0 && j < firstDay) {
createElement('li', daysBody, { textContent: '' });
} else if (date > daysInMonth(month, year)) {
break;
} else {
let li = createElement('li', daysBody, {}),
info = createElement('div', li, {
className: 'info',
textContent: weekdays[j],
}),
div = createElement('div', li, { className: 'date', textContent: date });
// ----------------------------
// ----- view events
if (typeof eventsArray !== 'undefined') {
viewEvents(eventsArray, li, [year, month, date]);
}
// ----------------------------
if (date === today.getDate() && year === today.getFullYear() && month === today.getMonth()) {
li.className = 'today';
}
date++;
}
}
}
}
// view events
function viewEvents(data, where, args) {
return (
data &&
data.map((item) => {
let date = item.date.split('/'),
year = parseInt(date[0]),
month = parseInt(date[1]) - 1,
day = parseInt(date[2]);
if (year === args[0] && month === args[1] && day === args[2]) {
let event = createElement('div', where, { className: 'ev', id: item.id }),
eventDesc = createElement('div', event, { className: 'ev-desc' });
eventDesc.innerHTML = `<div class="eventFlarumCalendar">${item.content}</div>`;
event.onclick = () => alert(eventDesc.textContent);
}
})
);
}
// next month
function next() {
currentMonth = (currentMonth + 1) % 12;
currentYear = currentMonth === 11 ? currentYear + 1 : currentYear;
showCalendar(currentMonth, currentYear);
}
// previus month
function prev() {
currentMonth = currentMonth === 0 ? 11 : currentMonth - 1;
currentYear = currentMonth === 0 ? currentYear - 1 : currentYear;
showCalendar(currentMonth, currentYear);
}
function daysInMonth(iMonth, iYear) {
return 32 - new Date(iYear, iMonth, 32).getDate();
}
// --- Create element
function createElement(element, where, args) {
let d = document.createElement(element);
if (args) for (const [k, v] of Object.entries(args)) d[k] = v;
where.appendChild(d);
return d;
}
/////////////////////////////////////////////////////////////
// NEW LINES
let formWrp = document.getElementById('myForm');
let f_id = myForm.querySelectorAll('[name="id"]')[0];
let f_date = myForm.querySelectorAll('[name="date"]')[0];
let f_content = myForm.querySelectorAll('[name="content"]')[0];
let f_button = myForm.querySelector('button');
f_button.addEventListener('click', addNewInfo);
function addNewInfo() {
let nfd = f_date.value.split('-').join('/');
eventsArray.push({
id: f_id.value,
date: nfd,
content: f_content.value
});
showCalendar(currentMonth, currentYear);
}
.eventFlarumCalendar {
cursor: help;
}
#structureCalendar header {
height: 4rem;
line-height: 4rem;
text-align: center;
background: #ff6200;
color: #fdfdfd;
}
#structureCalendar header .left,
#structureCalendar header .center,
#structureCalendar header .right {
width: 100%;
float: left;
}
#structureCalendar header .left h1,
#structureCalendar header .center h1,
#structureCalendar header .right h1 {
line-height: 1.8rem;
font-size: 25px;
}
#structureCalendar header .left button,
#structureCalendar header .center button,
#structureCalendar header .right button {
background-color: #ff6200;
border: 1px solid #ff6200;
color: #fdfdfd;
padding: 0.5rem 1rem;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
margin: 0 4px;
cursor: pointer;
transition: all 500ms ease;
}
.center {
background: #ff6200;
}
#structureCalendar header .left button:hover,
#structureCalendar header .center button:hover,
#structureCalendar header .right button:hover {
background-color: #ff6200;
border-color: #ff6200;
color: #fdfdfd;
transition: all 500ms ease;
}
#calendar #days,
#calendar #weekdays {
list-style: none;
padding: 0;
margin: 0;
width: 100%;
}
#calendar #days li,
#calendar #weekdays li {
display: block;
float: left;
width: calc(100% / 7);
padding: 5px;
box-sizing: border-box;
}
#calendar #weekdays {
height: 40px;
background: #ff6200;
border-bottom: 2px solid #ff6200;
}
.contentcalflarum {
display: flow-root;
}
#calendar #weekdays li {
text-align: center;
text-transform: uppercase;
line-height: 20px;
border: none !important;
padding: 10px 6px;
color: #474747;
font-size: 13px;
font-weight: bold;
}
#calendar #weekdays .today {
background: #ff6200;
color: #fdfdfd;
}
#calendar #days li {
height: 150px;
overflow-y: auto;
background: #fdfdfd;
position: relative;
color: #ff6200;
border: 1px solid #f0f0f0;
}
#calendar #days li:hover {
background: #f0f0f0;
}
#calendar #days li .info {
position: absolute;
bottom: 2px;
right: 2px;
opacity: 0;
}
#calendar #days li .date {
text-align: center;
margin-bottom: 5px;
background: #777ffa;
color: #fdfdfd;
width: 25px;
height: 25px;
line-height: 25px;
border-radius: 50%;
float: right;
font-size: 12px;
font-weight: bold;
}
#calendar #days .today {
background: #f2f2fe;
}
#calendar #days .today:hover {
background: #c0c4fd;
}
.ev {
display: block;
background: #f2f2fe;
border: 1px solid #c0c4fd;
border-radius: 4px;
margin: 5px auto;
transition: background 500ms ease;
}
.ev:hover {
background: #777ffa;
transition: background 500ms ease;
}
.ev-desc {
padding: 0.2rem 0.5rem;
}
.ev-desc a {
text-decoration: none;
color: #ff6200;
transition: color 500ms ease;
}
.ev:hover .ev-desc a {
color: #a8adfc;
transition: color 500ms ease;
}
#media (max-width: 768px) {
#structureCalendar header {
height: auto;
text-align: center;
padding: 1rem;
}
#structureCalendar header .left,
#structureCalendar header .center,
#structureCalendar header .right {
width: 100%;
float: none;
}
#calendar #weekdays,
#calendar .null {
display: none;
}
#calendar #days li {
height: auto !important;
border: 1px solid #f0f0f0;
width: 100%;
padding: 10px;
margin-bottom: -1px;
}
#calendar #days li .info {
left: 2px;
opacity: 1;
color: #d9dbfe;
}
#calendar .date {
float: none;
}
}
<div id="myForm">
<input type="text" name="id">
<input type="date" name="date">
<input type="text" name="content">
<button>Send</button>
</div>
<div class="contentcalflarum">
<div class="calforflarum" id="root"></div>
</div>
you can write function to add event to the array
const addEvent = (id, event, content) => {
eventsArray.push({id, event, content})
}
And to access
for (let i = 0; i < eventsArray.length; i++) {
const event = eventsArray[i]
console.log(`This is id: ${event['id']}`)
console.log(`This is event: ${event['event']}`)
console.log(`This is content: ${event['content']}`)
}
You can use the current date as object property and then based on that date push your event and content. i.e:
8142021; //8 = month, 14 = date; 2021= year
let eventsArray = {
$8142021: [
{
id: 1,
name: 'my event name',
content: 'my events description',
},
{
id: 2,
name: 'my event',
content: 'my events description',
}
],
$8152021: [
{
id: 1,
name: 'my event name',
content: 'my events description',
},
{
id: 2,
name: 'my event',
content: 'my events description',
}
],
};
]

How to add a css style change when a button on different html page is clicked?

I have made some quizzes in javascript. When my users click the complete button at the end of the quiz I then want to make the box on the home page have a green outline around it so they know they have completed that quiz. The complete button is on the challenge1.html page and the item I want to put the outline round is the item in the grid on home.html. Would anyone be able to give me some advice on how to do this?
Files: home.html, challenge1.html, home.css, challenge1.css and quiz.js
home.html
<div class="grid-container">
<div class="grid-item item1">1. Discover HTML Basics and Tags</div>
<div class="grid-item item2">2. Styling HTML with Tags</div>
<div>3. Creating Links and Images</div>
<div class="grid-item item4">4. Building Features</div>
<div class="grid-item item5">5. Building Lists</div>
</div>
challenge1.html
<div class="container">
<div id="question-container" class="hide">
<div id="question">Question</div>
<div id="answer-buttons" class="btn-grid">
<button class="btn">Answer 1</button>
<button class="btn">Answer 2</button>
<button class="btn">Answer 3</button>
<button class="btn">Answer 4</button>
</div>
</div>
<div class="controls">
<button id="start-btn" class="start-btn btn">Start</button>
<button id="next-btn" class="next-btn btn hide">Next</button>
<button id="complete-btn" class="complete-btn btn hide">Complete</button>
</div>
</div>
home.css
.grid-container {
display: grid;
margin-top: 30px;
grid-gap: 10px;
background-color: #FFFFFF;
padding: 10px;
}
.grid-container3 {
display: grid;
margin-top: 30px;
grid-gap: 10px;
background-color: #FFFFFF;
padding: 10px;
margin-bottom: 100px;
}
.grid-item {
background-color: #E26CBA;
padding: 20px;
font-size: 20px;
border-radius: 20px;
font-family: 'Poppins', sans-serif;
color: #3F0068;
}
.item3 {
grid-column: 1 / span 2;
grid-row: 2;
}
challenge.css
*, *::before, *::after {
box-sizing: border-box;
font-family: 'Poppins', sans-serif;
}
:root {
--hue-neutral: 200;
--hue-wrong: 0;
--hue-correct: 145;
}
body {
--hue: var(--hue-neutral);
padding: 0;
margin: 0;
display: flex;
width: 100vw;
height: 100vh;
justify-content: center;
align-items: center;
background-color: hsl(var(--hue), 0%, 100%);
}
body.correct {
--hue: var(--hue-correct);
}
body.wrong {
--hue: var(--hue-wrong);
}
.container {
width: 800px;
max-width: 80%;
background-color: white;
border-radius: 5px;
padding: 10px;
box-shadow: 0 0 10px 2px;
}
.btn-grid {
display: grid;
grid-template-columns: repeat(2, auto);
padding: 10px;
margin: 20px 0;
}
.btn {
--hue: var(--hue-neutral);
border: 1px solid hsl(var(--hue), 100%, 20%);
background-color: hsl(var(--hue), 84%, 73%);
border-radius: 5px;
padding: 10px 10px;
margin:10px;
color: white;
outline: none;
}
.btn:hover {
border-color: black;
}
.btn.correct {
--hue: var(--hue-correct);
color: black;
}
.btn.wrong {
--hue: var(--hue-wrong);
}
.start-btn, .next-btn {
font-size: 1.5rem;
font-weight: bold;
padding: 10px 20px;
}
.complete-btn {
font-size: 1.5rem;
font-weight: bold;
padding: 10px 20px;
--hue: var(--hue-correct);
}
.controls {
display: flex;
justify-content: center;
align-items: center;
}
.hide {
display: none;
}
quiz.JS
$(document).ready(function() {
const startButton = document.getElementById('start-btn')
const nextButton = document.getElementById('next-btn')
const completeButton = document.getElementById('complete-btn')
const questionContainerElement = document.getElementById('question-container')
const questionElement = document.getElementById('question')
const answerButtonsElement = document.getElementById('answer-buttons')
let shuffledQuestions, currentQuestionIndex
startButton.addEventListener('click', startGame)
nextButton.addEventListener('click', () => {
currentQuestionIndex++
setNextQuestion()
})
function startGame() {
startButton.classList.add('hide')
shuffledQuestions = questions.sort(() => Math.random() - .5)
currentQuestionIndex = 0
questionContainerElement.classList.remove('hide')
setNextQuestion()
}
function setNextQuestion() {
resetState()
showQuestion(shuffledQuestions[currentQuestionIndex])
}
function showQuestion(question) {
questionElement.innerText = question.question
question.answers.forEach(answer => {
const button = document.createElement('button')
button.innerText = answer.text
button.classList.add('btn')
if (answer.correct) {
button.dataset.correct = answer.correct
}
button.addEventListener('click', selectAnswer)
answerButtonsElement.appendChild(button)
})
}
function resetState() {
clearStatusClass(document.body)
nextButton.classList.add('hide')
while (answerButtonsElement.firstChild) {
answerButtonsElement.removeChild(answerButtonsElement.firstChild)
}
}
function selectAnswer(e) {
const selectedButton = e.target
const correct = selectedButton.dataset.correct
setStatusClass(document.body, correct)
Array.from(answerButtonsElement.children).forEach(button => {
setStatusClass(button, button.dataset.correct)
})
if (shuffledQuestions.length > currentQuestionIndex + 1) {
nextButton.classList.remove('hide')
} else {
completeButton.innerText = 'Complete'
completeButton.classList.remove('hide')
}
}
function setStatusClass(element, correct) {
clearStatusClass(element)
if (correct) {
element.classList.add('correct')
} else {
element.classList.add('wrong')
}
}
function clearStatusClass(element) {
element.classList.remove('correct')
element.classList.remove('wrong')
}
const questions = [
{
question: 'What does HTML stand for?',
answers: [
{ text: 'Hyperlinks and Text Markup Language', correct: true },
{ text: 'Hyper Text Markup Language', correct: false },
{ text: 'Home Tool Markup Language', correct: false }
]
},
{
question: 'Which character is used to indicate an end tag?',
answers: [
{ text: '<', correct: false },
{ text: '*', correct: false },
{ text: '/', correct: true },
{ text: ';', correct: false }
]
},
{
question: 'Who is making the Web standards?',
answers: [
{ text: 'Google', correct: false },
{ text: 'Mozilla', correct: false },
{ text: 'Microsoft', correct: false },
{ text: 'The World Wide Web Consortium', correct: true }
]
},
{
question: 'What is the correct HTML for making a text input field?',
answers: [
{ text: '<input type="textfield">', correct: false },
{ text: '<input type="text">', correct: true },
{ text: '<textfield>', correct: false },
{ text: '<textinput type="text">', correct: false }
]
},
{
question: 'Choose the correct HTML element for the largest heading:',
answers: [
{ text: '<head>', correct: false },
{ text: '<h6>', correct: false },
{ text: '<heading>', correct: false },
{ text: '<h1>', correct: true }
]
}
]
});
As Steve mentioned in the comment above, sessionStorage (or localStorage) might be what you need. For instance, when the user completes the quiz, you can trigger the following action:
window.sessionStorage.setItem("challengeCompleted", "true")
Then, in your home.html page, you add something like:
let challengeCompleted = window.sessionStorage.getItem("challengeCompleted")
if (challengeCompleted !== null && Boolean(challengeCompleted)):
// Handle your css change here
let btn = document.getElementById("your-btn-id");
btn.style["border-color"] = "green";
Something along these lines. I didn't check the code and just wrote it quickly from memory so could have a mistake, but this is the idea.
Lastly, use localStorage if you want the webpage to always remember the user's performance and sessionStorage if performance resets every time the user comes into the website again.

Categories

Resources