Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trial
Anders Tellefsen
10,351 Pointswindow.onclick seems to override my second event handler
I am trying to make a contact form on my webpage show when usr clicks on a <li> tag and dissapear when a user clicks outside of the form. I have tryed evrything I could possibly think of, but every time the form shows up fine, but when it is supposed to close only on a user clicking outside of the form, it closes when the user clicks outside of the form, but also when the user clicks on any of the inputs or the forms child elements?
Here is my Javascript code:
const hideContactForm = document.getElementById('kontakt'); const showContactForm = document.getElementById('vis_kontakt'); const form = document.getElementsByClassName('mail_form')[0]; const formChildren = form.children;
showContactForm.addEventListener('click', showForm); hideContactForm.addEventListener('click', hideForm);
function showForm () { hideContactForm.style.display = "flex"; }
function hideForm (event) { for (let i = 0; i < formChildren.length; i++) { if (event.target != form) { hideContactForm.style.display = "none"; } else if (event.target == form) { hideContactForm.style.display = "flex"; } } }
Here is my html:
<div id="kontakt">
<div class="midtstill">
<form class="mail_form" action="kontakt.php" method="post">
<h2>Bestill opplæring</h2>
<input id="navn" type="text" name="name" value="" placeholder="Navn..">
<input id="email" type="email" name="email" value="" placeholder="E-mail..">
xz <input id="tlf" type="tel" name="tlf" value="" placeholder="Tlf..">
<textarea id="melding" name="message" rows="6" cols="40" placeholder="Melding.."></textarea>
<button type="submit" name="button">Kontakt meg</button>
</form>
</div>
</div>
Thanks for any replies:)
4 Answers
Wiktor Bednarz
18,647 PointsThe more elegant solution would be to attach the click event listener to the outer div element of the form.
It would more or less look sth like that:
const contactFormOuter = document.getElementById('kontakt');
const formButton = document.getElementById('vis_kontakt');
const contactFormInner = document.getElementsByClassName('midtstill')[0];
formButton.addEventListener('click', showForm);
contactFormOuter.addEventListener('click', hideForm);
function showForm () {
contactFormOuter.style.display = "flex";
}
function hideForm (event) {
if(event.target===contactFormOuter) {
contactFormOuter.style.display = "none";
}
}
Wiktor Bednarz
18,647 PointsHey there,
first of all, your only click event listeners in this code are the presumed button with an id of "vis_kontakt" and a whole form div. So you can't really expect that clicking outside of a form will hide the form. Don't know what's the styling for the form element that is in your snippet, but if it is an overlay then it's z-index position might be causing some problems if you would like to attach click event listener to anything outside of it.
The whole hideForm function you provided is black magic for me. Why are you selecting your h2 element with the established "form" constant? Why are you looping through the array of all the form element childred for each click? Why is there an else if statement that sets your form element display attribute to the value it's already got?
I think you overcomplicated the entire approach for a simple task here.
If you want to stick to the solution that form should appear on button click and dissapear on click outside of the form, then it depends on how the form is styled. If the form just enters the appends to the DOM between other elements, then select the body element itself as an event listener and exclude clicks on the form from triggering it. However if the form is an overlay that's placed in front of the rest of the DOM with proper z-index, then just select a parent of the form that is overlaying the rest of the page.
Hope this helps
Anders Tellefsen
10,351 PointsHi Wiktor Bednarz, thanks for your answer.
The form element is inside of two div elements that overlays the whole body element. I have just change my javascript code, and now it works:)
const hideContactForm = document.getElementById('kontakt'); const showContactForm = document.getElementById('vis_kontakt'); const form = document.getElementsByClassName('mail_form')[0];
showContactForm.addEventListener('click', showForm); hideContactForm.addEventListener('click', hideForm);
function showForm () { hideContactForm.style.display = "flex"; }
function hideForm (event) { const formHead = form.firstElementChild; const formName = formHead.nextElementSibling; const formMail= formName.nextElementSibling; const formTlf = formMail.nextElementSibling; const formTxt = formTlf.nextElementSibling; const formBtn = formTxt.nextElementSibling; if (event.target != form && event.target != formHead && event.target != formName && event.target != formMail && event.target != formTlf && event.target != formTxt && event.target != formBtn) { hideContactForm.style.display = "none"; } }
I first tyred to use the .children property on the const form, but that did not work. That was the reason I was using a for loop. Do you know a better way of writing this code? I would very much appreciate it since I am very new to javascript, and trying to learn as best as I can:)
Anders Tellefsen
10,351 PointsThanks a lot for your help Wiktor Bednarz!