I am new to Javascript.
So far my code only changes the color of the text of the button, I am trying to make it where enabling the button also reveals the hidden paragraph. Always says that the arrow and answers are undefined
const buttons = document.querySelectorAll('button');
const answers = document.querySelectorAll('p');
const arrows = document.querySelectorAll('arrow');
console.log(buttons);
console.log(answers);
console.log(arrows);
buttons.forEach(button => {
button.addEventListener('click', function(){
button.style.color = 'red';
answers.style.display = 'block';
});
})
Alternate code i did was
const button = document.querySelector('button');
const answers = document.querySelector('.answer');
const arrow = document.querySelector('.arrow');
button.addEventListener('click', () => {
answers.style.display = 'block';
arrow.style.transform = 'rotate(180deg)'
});
This one worked. However, I would have to label every element in my HTML that needs to change.
Here is sample HTML:
<div >
<button>How many team members can I invite? <img src="images/icon-arrow-down.svg"></button>
<p >You can invite up to 2 additional users on the Free plan. There is no limit on
team members for the Premium plan.</p>
</div>
<div >
<button>What is the maximum file upload size?<img src="images/icon-arrow-down.svg"> </button>
<p > No more than 2GB. All files in your account must fit your allotted storage space.</p>
</div>
<div >
<button>How do I reset my password?<img src="images/icon-arrow-down.svg"></button>
<p >Click “Forgot password” from the login page or “Change password” from your profile page.
A reset link will be emailed to you.
</p>
</div>
<div >
<button>Can I cancel my subscription?<img src="images/icon-arrow-down.svg"></button>
<p >Yes! Send us a message and we’ll process your request no questions asked.</p>
</div>
<div >
<button>Do you provide additional support?<img src="images/icon-arrow-down.svg"></button>
<p >Chat and email support is available 24/7. Phone lines are open during normal business hours.</p>
CodePudding user response:
You should grab the clicked element from inside the click event handler using window.event.target
. Your problem was trying to access from your click handler to variables defined outside of its scope and having a different meaning. Everytime the click handler gets invoked it needs a strategy to fetch the clicked element and all the elements bound to its context to which you wish to change the style.
But there's a chance I didn't correctly get what you were really asking... in that case I hope to hear a feedback.
I made a demo here to show how:
const buttons = document.querySelectorAll('button');
function resetButtonStyles(){
document.querySelectorAll('div.parent.active').forEach( divactive =>{
divactive.classList.remove('active');
});
}
buttons.forEach(button => {
button.addEventListener('click', function(){
document.querySelector('div.parent.active')
?.classList.remove('active');
const clickedButton = window.event.currentTarget;
const parentDiv = clickedButton.closest('div.parent');
const boundAnswer = parentDiv.querySelector('p');
parentDiv.classList.add("active");
//clickedButton.style.color = 'red';
//boundAnswer.style.border = 'solid red 2px';
});
})
.active p{
color: red;
}
.active button{
border: solid red 2px;
}
<div >
<p>Answers 1</p>
<button>Button 1</button>
</div>
<div >
<p>Answers 2</p>
<button>Button 2</button>
</div>
<div >
<p>Answers 2</p>
<button>Button 2</button>
</div>
<div >
<p>Answers 2</p>
<button>Button 2</button>
</div>
CodePudding user response:
It sound like you're after an accordion effect.
Wrap your markup in a container so you can use event delegation.
Cache the container, and the answer elements.
When you click on a button hide all the answers, switch the arrow, and then show that button's answer.
[Note: I've used unicode in CSS to show the arrows instead of images].
// Cache the elements
const container = document.querySelector('.container');
const answers = document.querySelectorAll('.answer');
const arrows = document.querySelectorAll('.arrow');
// Add a listener to the container
container.addEventListener('click', handleClick, false);
function handleClick(e) {
// If we click a button
if (e.target.matches('button')) {
// Remove all the answers
answers.forEach(answer => answer.classList.remove('show'));
// Update the arrows
arrows.forEach(arrow => {
arrow.classList.remove('down');
arrow.classList.add('right');
});
// Get the parent of the clicked element
const parent = e.target.closest('.faq');
// Change the arrow...
const arrow = e.target.querySelector('.arrow');
arrow.classList.remove('right');
arrow.classList.add('down');
// ...and then show the answer
const answer = parent.querySelector('.answer');
answer.classList.add('show');
}
}
.answer { display: none; }
.show { display: block; }
.down:after { content: '\1F783'; }
.right:after { content: '\1F782'; }
button:hover { cursor: pointer; }
<div >
<div >
<button>How many team members can I invite?
<span ></span>
</button>
<p >You can invite up to 2 additional users on the Free plan. There is no limit on team members for the Premium plan.</p>
</div>
<div >
<button>What is the maximum file upload size?
<span ></span>
</button>
<p > No more than 2GB. All files in your account must fit your allotted storage space.</p>
</div>
<div >
<button>How do I reset my password?
<span ></span>
</button>
<p >Click “Forgot password” from the login page or “Change password” from your profile page. A reset link will be emailed to you.
</p>
</div>
<div >
<button>Can I cancel my subscription?
<span ></span>
</button>
<p >Yes! Send us a message and we’ll process your request no questions asked.</p>
</div>
</div>
CodePudding user response:
const buttons = document.getElementsByTagName('button');
const answers = document.getElementsByTagName('p');
const arrows = document.getElementsByTagName('arrow');
console.log(buttons);
console.log(answers);
console.log(arrows);
for (var j = 0; j < buttons.length; j ){
var button = buttons[j];
button.addEventListener('click', function(){
button.style.color = 'red';
for (var i = 0; i < answers.length; i ){
answers[i].style.display = 'block'
}
});
}