Make onclick only affect the element, not it's children as well - javascript

I am making a personal website. I want to make it so that cliking the background changes the theme from dark to light and vice/versa. It works, but I dont want it to switch the theme if the user clicks on text, only the background of the webpage For example, if I click the text at the bottom it changes the css, but it should only do that if you click the white background.
Here is my code (Mainly checkout js/main.js, the switchTheme function and the index.html) and the website itself.

You are targeting your container class. Anytime that div (or anything in it) gets clicked, that event will fire. Try stopping the event propagation on your click event if $('this').selector === 'p' or whatever class you're using.
Also - not bad for 13 boss!
$( document ).click(function( event ) {
// if statement here
event.stopPropagation();
// else the regular behavior
});

Thanks everyone for your help! I'd almost given up and wanted to use a button to toggle it instead. The more you know!
And since this is an answer to my question: e.stopPropogation()

You can also do something like this:
document.querySelector('div').addEventListener('click', (e) => console.log("Heeeeyyy! Hoooo!"))
<div style="position: fixed; background-color: lightcoral; width: 500px; height: 180px;">
</div>
<div style="position: fixed; background-color: lightblue; width: 300px; height: 100px;">
<p>You can not click through me!</p>
</div>
Don't put the elements inside the "parent".
Move them together only by style.

How about
$("#container").on("click", "div", function(event){
event.stopPropagation();
switchTheme();
});

Add a test to see if the ID of the clicked element was actually the container.
function switchTheme( event ) {
if ( event.target.id === 'container' ) { //the container was clicked, and not a text node
if (dark) {
$("#container").css("background-color", "rgba(255,255,255,0.7);");
$("#container").css("color", "black");
dark = false;
} else {
$("#container").css("background-color", "rgba(0,0,0,0.7);");
$("#container").css("color", "white");
dark = true;
}
}
}

Try setting the following:
$("#container").on("click", "div", function(e){
e.stopPropagation();
});

Related

Stop propogation of event listener click but still allow other click events to occur within the element

I have created a fairly classic modal. Fixed modal in the middle of the screen. Semi-transparent background and a box in the middle.
The box contains some click event listeners (e.g a close X and a button that performs another action).
I want to allow the user to close the modal by clicking on the outer background.
HTML example
<div class="modal">
<div class="modal__inner">
<div class="modal_closebtn">X</div>
</div>
</div>
Currently, I have the following to handle closing the modal based on click of .modal, which covers the whole screen.
document.querySelector(".modal").addEventListener("click", () => {
this.toggleModal();
});
My problem is, this fires if you click inside the .modal__inner too.
So I tried adding an eventListener to stopPropagation()
document.querySelector(".modal__inner").addEventListener("click", e => {
e.stopPropagation();
});
This now blocks the eventListener for my .modal_closebtn and any other events that occur inside the modal.
How can I ensure that the click for the background div only works on the modal div not modal__inner or any others? Unfortunately when I review e.currentTarget after clicking inside my div it returns .modal not .modal__inner even though it does appear that I clicked inside that div.
Non jQuery solution please
To avoid the execution of querySelector too many times and gain a little of performance, store that result into a variable.
var elem = document.querySelector(".modal")
elem.addEventListener("click", (e) => {
if (e.target !== elem) return;
console.log('toggle!');
//this.toggleModal();
});
.modal {
width: 300px
height: 300px;
border: 1px solid #000
}
.modal__inner {
width: 100px
height: 100px;
border: 1px solid red
}
<div id="hola" class="modal">
Parent modal
<br>
<br>
<br>
<div id="epale" class="modal__inner">
Inner modal
<div class="modal_closebtn">X</div>
</div>
</div>
Happy coding!
The event object has the original target of the event, use that to figure out what is the source of the event.
var modal = document.querySelector(".modal");
modal.addEventListener("click", (e) => {
if (e.target !== modal) return;
this.toggleModal();
});

Trigger each div independently using same script

I'm trying to get each blue div (<div id="rectangle"></div>) to fire independently.
Right now, if you hover/click over the first one, both fire simultaneously, and if you hover/click over the second one, neither fires.
This is a common question and has been addressed elsewhere, but I've tried to implement several different versions and apply it to this particular code, and it's not working. I was hoping someone could provide some explanation to help me learn, and I can compare to the other posts I've tried out to understand what the difference is.
$('.rectangle1').hide();
$('#rectangle').on('click', function() {
clicked = !clicked;
});
$('#rectangle').hover(function() {
$('.rectangle1').slideDown()
},function() {
if (!clicked) {
$('.rectangle1').slideUp()
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="rectangle"></div>
<div class="rectangle1"></div>
<div id="rectangle"></div>
<div class="rectangle1"></div>
http://jsfiddle.net/Q5cRU/99/
One problem is that you're using id="rectangle" for two elements. According to MDN:
The id global attribute defines a unique identifier (ID) which must be unique in the whole document.
jQuery is only adding the event listeners to the first element with that ID.
The answer is simple: The event listener was only applied to the first #rectangle. jQuery does not select more than one #ID'd element. With that being said it is not semantic to use the same id on more than one element.
Here's what you are looking for: http://jsfiddle.net/Q5cRU/116/
$(document).ready(function() {
$('.rectangle1').hide();
$('.rectangle').data( 'clicked', false).click(function() {
$(this).data( 'clicked', !$(this).data('clicked'));
}).hover(
function() {
$(this).next('.rectangle1').slideDown();
},
function() {
if (!$(this).data('clicked')) {
$(this).next('.rectangle1').slideUp();
}
}
);
});
$("div.rectangle1").mouseover(function() {
$(this).stop(true, true).show();
});
Well in HTML, the id attribute must be unique per element. See this. The class attribute can be shared by multiple elements to have the same style effect or same purpose. So the first and second div can't have the same id - "rectangle". To fire event independently you can assign different id for them.
HTML:
<div>
<div class="rectangle"></div>
<div class="rectangle-hover"></div>
</div>
<div>
<div class="rectangle"></div>
<div class="rectangle-hover"></div>
</div>
CSS:
.rectangle {
width: 140px;
height: 80px;
background: #037CA9;
margin-bottom:10px;
}
.rectangle-hover {
width: 140px;
height: 150px;
background: red;
}
Javascript:
$(function(){
var clicked = false;
$('.rectangle-hover').hide();
$('.rectangle').hover(
function(){
$(this).parent().find('.rectangle-hover').slideDown();
},
function(){
if (!clicked) {
$('.rectangle-hover').slideUp()
}
}
);
});

Show div and then hide when clicking outside

I have this code:
$(function() {
$('#toggle4').click(function() {
$('.toggle4').slideToggle('fast');
return false;
});
});
Which works great and shows the '.toggle4' div but I want to hide it again when clicking outside/away from it.
So I added this:
$(document).click(function() {
$(".toggle4").hide();
});
Which works but it hides the div even when I click inside of the '.toggle4' div (it's an input box for a search form).
Any ideas? Thanks.
That's because when you click inside of .toggle4 that click event bubbles up the DOM and triggers the event you bound to the document. You should be able to fix that with something like:
$('.toggle4').click(function(e){
e.stopPropagation()
})
One possibility is to prevent the click event from bubbling up to the document if it took place inside the toggle.
$(function() {
$('#searchField').click(function() {
$('#toggle').slideToggle('fast');
return false;
});
});
$(document).click(function() {
$("#toggle").hide();
});
$("#toggle").click(function(e) {
e.stopPropagation();
});
#toggle {
width: 100px;
height: 100px;
background: red;
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="searchField">
<div id="toggle" class="toggle4"></div>

jQuery mouseenter and mouseleave problems, keep toggled div shown

I have got 1 area, and on mouseenter I am fading in the following div:
$( "area.hasmore" ).mouseenter(function() {
$(this).next(".popup").stop().fadeIn();
});
Let's say the popup appears on the right hand side. What if the user leaves the area on the left hand side? Let's fade that popup out:
$( "area.hasmore, .popup" ).mouseleave(function() {
$(".popup").fadeOut();
});
Here comes my problem: users should be able to move the cursor into the fresh opened popup to the right and maybe even click a link in there. My problem is that it fades out due to the mouseleave event on the area. One problem might be the fact that the popup is no child. As a child of the area hovering the popup would still count as being 'inside' the area I guess. So I am kind of trying to find out how to keep the popup visible when mouseentering it and mouseleaving the area.
Here's the code:
<area class="hasmore" />
<div class="popup">...
Sry if I missed a question where this exact problem is being discussed.
jsfiddle here: fiddle
You could manage what is visible in the hover instead of mouseenter and mouseleave:
Something like this:
$('div').hover(function () {
console.log(this.className);
if (this.className === 'hasmore') {
$(this).next(".popup").stop().fadeIn();
} else if (this.className !== 'hasmore' && this.className !== 'popup') {
$(".popup").fadeOut();
}
});
Here is a fiddle demonstrating
html
<div class="hasmore">hover me</div>
<div class="popup">Popup 1</div>
<div class="evenmore">stuff</div>
<div class="popup">2nd popup. don't mind me</div>
Javascript
$( ".container" ).mouseenter(function() {
$(".popup").stop().fadeIn();
});
$( "div.container" ).mouseleave(function() {
$(".popup").fadeOut();
});
CSS (include this)
.container {
display: block;
line-height: 1em;
margin: 0;
padding: 0;
}
The trick is to create a div (.container) with display: block and enclosure .hasmore and .popup inside it!

MooTools - How to get mouse position when submitting a form?

What I'm trying to do here is to show a loading box that follows cursor after submitting a form using MooTools. However, I've simplified the problem into just 1 div and 1 form.
script:
document.addEvent('domready', function(){
$('test_form').addEvent('submit', function(){
var box = $('box');
document.addEvent('mousemove', function(e){
box.setStyles({
top: e.page.y,
left: e.page.x
});
});
box.setStyle('display', 'block');
return false;
});
});
html:
<div id="box">
</div>
<form id="test_form" action="">
<label>Name: </label><input type="text" name="name" /><br/>
<input type="submit" value="Submit" />
</form>
css:
#box {
width: 50px;
height: 50px;
background-color: blue;
position: absolute;
display: none;
}
#test_form {
margin-left: 150px;
}
When the form is submitted, it will show the hidden blue div and it will follow the cursor. However, I can't make the div appear at mouse position when the form is submitted. The 'mousemove' will not fire until we move the mouse; thus, the blue div appears at position (0,0) immediately after showing. Is there a way to get the mouse position right after the form is submitted? Or is there an alternative way to do it?
Any suggestions is greatly appreciated!
Updated:
I don't want to add mouse event (mousemove) before the form is submitted. The reason is simply because I don't want the javascript to keep on checking the mouse position when it's not necessary. Just try to avoid performance issue!
basically, the submit is an event but its event.type is submit and it won't contain mouse info.
your bet is to re-arrange your javascript so it moves the box quietly all the time and just shows the box by changing display when submitted. something like that:
http://jsfiddle.net/jtLwj/
(function() {
var box = $('box');
document.addEvent('mousemove', function(e) {
box.setStyles({
top: e.page.y,
left: e.page.x
});
});
$('test_form').addEvent('submit', function(ev) {
ev.stop();
box.setStyle('display', 'block');
var sizes = box.getPosition();
box.set("html", [sizes.x, ' x ', sizes.y].join("<br/>"));
});
})();
reading the box position after submit will return your cursor :)
downside: latency of changing css for the invis box before submit.
edit better version w/o the change to dom all the time:
(function() {
var lastEventObject, eventListener = function(e) {
// keep a scoped referene of the last known mouse event object
lastEventObject = e;
};
document.addEvent('mousemove', eventListener);
document.id('test_form').addEvent('submit', function(e) {
e.stop();
// not needed anymore...
document.removeEvent("mousemove", eventListener);
// show the box at last known mouse loc
document.id("box").setStyles({
display: 'block',
left: lastEventObject.page.x,
top: lastEventObject.page.y
});
// attach to mousemove or whatever....
});
})();
this is as good as it will get, I'm afraid. the footprint of the reference to the event object is minimal at best.
fiddle: http://jsfiddle.net/dimitar/jtLwj/1/

Categories

Resources