Disable mouse events on overlapping divs without pointer-events - javascript

I have a div with a onClick event, but it's not detecting the mouse because of an overlapping div. I can't put it below the 1st one, so changing the z-index isn't an option.
Is there any way to disable the mouse events on the 2nd div without the pointer-events? I need this to be cross-browser.
Requested sample. Right now all the event does is fire an alert:
<div class="buttonDiv" onClick="buttonAction()"></div>
<div class="filterDiv"></div>

You can try this:
HTML
<div class="buttonDiv" onClick="buttonAction(event)">
OUTER
<div class="filterDiv">INNER</div>
</div>
Javascript
var buttonAction = function(e) {
if(e.target.className == "buttonDiv") {
//code here
alert('got here');
}
}
Example: http://jsfiddle.net/aFRcd/1/
Basically on the click, you send along the click event and then you can see which div was actually clicked using event.target
You'll notice in the example that clicking on OUTER fires the alert whereas INNER does not.

The only solution I could find was having a Mouse Move event attached to the canvas and compare the coordinates of the button to the position and dimensions of the buttons. It's a pain, but at least it does the job

Related

keep mouse over active if hovering over another overlapping element

I've got a DOM structure like the one below. These to elements are overlaping. On hover, video start to play. Unfortunately, when I hover over .showsOnHover, mouseover and mouseout repeatedly fire one after another making .showsOnHover blink and video stutter.
What should I do to instruct browser to treat hovering over .showsOnHover as one continuous hover?
.html
<video (mouseover)="mouseover()" (mouseout)="mouseout()"></video>
<div [hidden]="!hovering" class="showsOnHover"></div>
.ts
mouseover(e){
this.hovering = true;
this.video.play();
}
mouseout(e){
this.hovering = false;
this.video.stop();
}
The issue is that when showsOnHover is shown, it covers up the video, which makes it mouseout, so it hides the div, then the hover event triggers again, and it shows the div, and it just loops over and over very rapidly.
You essentially will want to do one of the following:
Put the mouseover and mouseout events on both the video and the showsOnHover elements, perhaps do it on a containing parent div element. This way the mouseout event won't be triggered when it's shown; instead it will only trigger when you leave the larger containing element.
Add pointer-events: none; to your .showsOnHover class in the CSS. This makes that div transparent to mouse events. However, this could cause issues if you wanted to run any click events off that button.
Change mouseover to mouseenter as mentioned in Ram's answer
create a parent div and fire the same event on that,
<div class="parentDiv" (mouseenter)="mouseover()" (mouseleave)="mouseout()">
<video></video>
<div [hidden]="!hovering" class="showsOnHover"></div>
</div>
Use mouseenter instead of mouseover
mouseenter(e){
this.hovering = true;
this.video.play();
}
[.mouseover()] can cause many headaches due to event bubbling. For
instance, when the mouse pointer moves over the Inner element in this
example, a mouseover event will be sent to that, then trickle up to
Outer. This can trigger our bound mouseover handler at inopportune
times. See the discussion for .mouseenter() for a useful alternative.
Please see What is the difference between the mouseover and mouseenter events?
Use (mouseenter) and (mouseleave) instead of (mouseover) and (mouseout)

Right click acts like a left click on the event

I have this code:
document.getElementById("1").oncontextmenu = function() {
return false
}
It disables the little window that shows after a right click (only on the button/image).
On my code (https://jsfiddle.net/nnuyguat/) everything is working fine, except for when I do a right click on the image as it triggers the left click event and changes the image untill I move the mouse.
Another related problem is if I press left click without releasing and then right click (releasing the right button), it will also change the image.
I need to prevent the image changing with right clicks. It should work as the closing button of the browser (except it's another images and it doesn't close anything).
You could use event.button to check which button is pressed because event.button returns a number which indicates which mouse button was pressed.
Source
Edit:
if (event.button === 2){
// run your function
}
That should be correct, as I have never used this before.
The right click event is not triggering a left click. It is just activating your object. Your image says "click" but it is inaccurate. It should say "Active".
Second, a number is NOT a valid ID. So rename your div from id="1" to id="one" or similar.
Finally, try with this code, instead of yours:
document.getElementById("one").addEventListener('contextmenu', function(ev) {
ev.preventDefault();
alert('hello from right click');
return false;
}, false);
See https://jsfiddle.net/nnuyguat/3/
The issue with your image changing on right click is not related to your javascript, but to your css. The :active CSS pseudo-class matches when an element is being activated by the user. According to the specs this should only be when the element is activated with the primary mouse button, but it seems like most browsers do not implement the spec correctly. See this question for info.
A work around maybe to abandon the :active pseudo-class, and set up a function to change the content explicitly on left click.
Its because of the oncontextmenu event. Remove it and it will work

jQuery Click Event Triggering On Multiple Elements (I only want 1)

When my overlay comes up, everything works well, but I added some code to close out the overlay, but this code gets triggered even when I'm just clicking my arrows. The following is the code that's being triggered, which is fine when I'm not clicking the arrows to change the image. But when I click the arrows, the background which is the overlay is also being trigger, so the image is changing but the overlay is also hiding.
$('#overlay').click(function() {
$(this).fadeOut('slow');
});
How can I be able to use the arrows without it also clicking on the background overlay? If you open up the project, you will see what I'm saying.
To open the project:
https://htmlpreview.github.io/?https://github.com/rodriguesandrewb/photo_gallery_v1/blob/master/index.html
To open the repository:
https://github.com/rodriguesandrewb/photo_gallery_v1
You want to use event.stopPropagation(): https://api.jquery.com/event.stoppropagation/
This prevents the event from bubbling (being triggered by other elements)
Your outter most element is #overlay. It means that no matter where you click you'll be always clicking on your #overlay element. That is way your callback is being always triggered and closing your image.
To fix your problem and make your image close only when clicking on it you could use:
$('#changeImage').click(function() {
$(this).closest('#overlay').fadeOut('slow');
});
Ok, there's a ton of code to sort out, so I'm guessing your overlay is
<div id="overlay" style="display: block;"></div>
and your event.target is deep down inside this:
<div class="mainCenter">
<div class="container">
<div id="topFixed">
<input type="text" id="search" placeholder="Search">
</div>
<ul id="gallery">
.......
I'm not 100% sure where your event.target is, (the element you want to click and not everything else). But it's safe to assume that after you click your intended button, the event continues to bubble up the event chain. The event chain is basically your event.target's ancestors which includes#overlay` which is at the very top of the event chain.
To prevent event bubbling (btw bubbling is the default behavior but in instances such as your's it's not desired.) try placing stopPropagation() after or inside at the end of your event handler.
I wish I could be more specific as to where and how to apply this code as it pertains to your source, but you didn't provide the specific areas that concern your eventListeners, eventHandlers, etc...
The #overlay is used in this example but I suggest you use the event.target parent instead. The purpose of this code is to accept an event like 'click' on an element (i.e. button) or multiple elements (i.e. buttons) through their mutually shared parent. That's one place to click for potentially several different buttons. At first you'd think that's non-sense and you'd say, "Sure that button is clicked because the parent was clicked, but now everything the parent is chained to will trigger everything else."
That would be correct except we have stopPropagation(); at the very end of your eventHandler. That will stop propagation of the event bubbling back up the event chain, so there's no more rogue triggers lighting up everywhere. Rogue Triggers® sounds like a great band name. :P
For details and a much better explanation: http://www.kirupa.com/html5/handling_events_for_many_elements.htm
var overlay = document.querySelector("#overlay");
theParent.addEventListener("click", doSomething, false);
function doSomething(e) {
if (e.target !== e.currentTarget) {
var clickedItem = e.target.id;
alert("Hello " + clickedItem);
}
e.stopPropagation();
}

JavasScript changing DOM in mouse-event

I have 2 DIVs and in each DIV there's a Button which does something on click.
Now I've added a piece of code to bring the DIVs to front when they get a mousedown. Which works very well. The problem is, that they swallow the mousedown of the inner button... The inner button can only be clicked by double clicking it.
http://jsfiddle.net/nUtz6/
$('div').mousedown(function (event) {
$(this).parent().append($(this));
});
how could I solve this problem? I did it this way because I don't want to increment the z-index of the CSS property to some magic number everytime I click the div. I read that jquery also does the DOM manipulation trick.
The problem seems to occur because I change the DOM right before the click-Event of the button. If I don't do anything in the mousedown, everything works fine.
Just check that the DIV is actually the target of the event :
$('div').mousedown(function (event) {
if (event.target.tagName.toLowerCase() != 'button')
$(this).parent().append($(this));
});
FIDDLE

How can I bind a JQuery event to make it only fire once?

I have a help popup that I want to close when somewhere else is clicked. Here's what I have:
$('.help[data-info]').click(function(){
$('.info[a complicated selector]').toggle(400);
$('*:not(.info[the complicated selector]).one('click','',function(){
.info[the complicated selector].hide(400);
});
})
But one() isn't what I want before it fires for each element on the page. I only want it to fire once.
It looks like you are attaching event handlers to every element in your dom except the help popup? Hmm...
How about this:
Create a single "mask" div that overlays the entire screen, but is transparent (opacity: 0.0). Attach the click event handler only to that mask div. Then open up the info div on top of the overlay div. Clicking anywhere on the page, other than the info div, the event will be captured by the mask div before it gets to anything under it. In your event handler, hide() the info div, and remove the mask div altogether. While testing/experimenting with this, start with a partially opaque mask, not fully transparent).
Make use of a boolean variable and set it to true after first click, so it doesn't trigger the action again:
$('.help[data-info]').click(function() {
var clicked = false;
$('.info[a complicated selector]').toggle(400);
$('*:not(.info[the complicated selector]').one('click','',function() {
if (!clicked) {
.info[the complicated selector].hide(400);
clicked = true;
}
});
})
A couple of options:
You can use the blur event instead of binding a click event to everything but your popup.
Add a transparent, full-page div between the popup and the rest of the page. A click event on the transparent div could handle the hiding.
If you only want to fire once across all your elements, then you may have to manually unbind all the event handlers when any one is clicked or use a flag:
$('.help[data-info]').click(function(){
$('.info[a complicated selector]').toggle(400);
var sel = $('*:not(.info[the complicated selector]);
function hideInfo() {
.info[the complicated selector].hide(400);
sel.unbind('click', hideInfo);
}
sel.bind('click', hideInfo);
})

Categories

Resources