retain links functionality inside a div that has an onclick event - javascript

I have a div that has an onclick that hides the div.
If I have a link inside the div, the link does not work, because the onclick steals the click.
The desired result: if a click is made anywhere inside the div BUT the link, that the div gets hidden. If a click is made ON the link, then I want the link to open in a _blank window, and the div to remain visible.
Is there a way to deal with this with javascript?

document.getElementById('yourlinksid').onclick = function(e){
// ... pop your window ...
/* the following prevents the event from "bubbling up"
to the div's event handler */
if(!e.stopPropagation) {
e.cancelBubble = true;
return;
}
e.stopPropagation();
};
Verification:
http://jsfiddle.net/kSTNT/4/

DEMO
Inside the click handler for the link, you'll want to call event.stopPropagation, or set e.cancelBubble to true—whichever your browser prefers. This will prevent the event from bubbling to your div.
document.getElementById("thelink").onclick = function (e) {
window.open();
if (e.stopPropogation)
e.stopPropogation();
if (e.cancelBubble != null)
e.cancelBubble = true;
};

If you control the links, the easiest way is to add onclick="event.stopPropagation();" (or whatever the cross-browser version of that is) to each link, which stops the div from seeing the event without preventing the default effect of the link from taking place.
Alternatively, if the links only contain text, then you can check the tag name of the event's target in the div's click event to see whether it is a link, but if you have something more complex then you need to walk the dom tree from the event target to the div to verify that no link exists.

Related

Layered elements with oncontextmenu bindings

Repro: https://jsfiddle.net/ssabc/cL6qxn1r/13/
I have a background element and a foreground element (you can think of it as a dialog popup on top of a canvas). When the user right-clicks on the foreground I would like to prevent the context menu from appearing in the background.
I tried binding a handler for the foreground's context menu and returning false from it to no avail:
document.getElementById('above').oncontextmenu = function(e) {
e.preventDefault();
return false;
}
As you can see in the JSFiddle, the oncontextmenu-event triggers on both elements. Here's a screenshot showing event firing in the background no matter which element is right-clicked
Is there any way to prevent the background event from firing?
You just need to add
e.stopPropagation();
to your child element right click event handler. With the change, it would look like this:
document.getElementById('above').oncontextmenu = function(e) {
e.preventDefault();
e.stopPropagation(); // <=== add this
getResultP().innerHTML += '<li>Dialog oncontextmenu called</li>';
return false;
}
This prevents the event from bubbling up the DOM tree. Read more about it here.

JQuery detect click outside element and stop all other click events

I'm making a popup menu. The user clicks on it to show the menu, then if they click outside the popup menu I want to hide it.
I can find many solutions (most popular is here: How do I detect a click outside an element?) but they all seem to have the same issue.
They rely on handling clicks that bubble up to the window element.
Their Logic:
All clicks bubble up to window element. Handle those clicks - if menu is open, then close it. Also call preventDefault to stop any links being followed (let's just say that the user happens to click on a link when they are clicking outside the menu - we don't want to follow that link)
$(window).click(function(e) {
if (!e.isDefaultPrevented()) {
if($('.mainNav').hasClass('menuVisible')){
//stop any other actions happening (e.g. following a link)
e.preventDefault();
//Hide the menus
$('.mainNav').removeClass('menuVisible');
}
}
});
The issue
If the thing the user clicks on happens to have an onclick event itself then that code still gets fired. Elements lower down the tree get the click even first, so I cannot use preventDefault or stopPropagation to stop these events..
Any ideas how to fix it? My only idea is to put a transparent div across the whole screen on top of everything to catch the clicks first?
You need to use addEventListener() and the useCapture property. the useCapture property allows events from object higher in the DOM tree to be triggered first. You can then prevent your normal click behaviour from occurring:
var button = document.getElementById("myButton");
var response = document.getElementById("myResponse");
var windowClick = function (evt) {
response.innerHTML += "<p>The Window</p>";
evt.stopPropagation ();
}
var buttonClick = function (evt) {
response.innerHTML += "<p>The Button</p>";
evt.stopPropagation ();
}
button.addEventListener("click", buttonClick);
// If true, the window event fires first, if false, the button fires first.
var useCapture = true;
window.addEventListener("click", windowClick, useCapture);
<!DOCTYPE html>
<html lang="en">
<head>
</head>
<body>
<button id="myButton">Hello!</button>
<div id="myResponse">Who Clicked?</div>
</body>
</html>
Updated
I originally misunderstood that we were trying to stop inline onclick events from firing. I found a potential solution from another StackOverflow question, you can see it here.
Otherwise, take a look at this:
$('button[onclick]').each(function(){
$(this).data('onclick', this.onclick);
this.onclick = function(event) {
if($('.mainNav').hasClass('menuVisible')) {
return false;
};
$(this).data('onclick').call(this, event || window.event);
};
});
It overrides the elements click handler. I've updated your jsFiddle to show it in action.
you can add a class to the body when menu is opened, and attach an event listener to the click event of body which will hide the menu and remove the listener
when showing the menu
$('body').addClass('menu-open');
$('body.menu-open').one('click', function(e) {
e.preventDefault();
// code to hide your menu goes here
$('body').removeClass('menu-open');
});
Note the usage of .one for attaching the event handler. It automatically removes the event handler after it is executed once.
Ref https://api.jquery.com/one/

JavaScript Bind Event at Certain Time

I'm trying to implement the following functionality and am having some trouble. What I want is when a user clicks a certain image, a popup div will appear containing some information about that image. Then if the user were to click anywhere on the page outside of that popup div, it would simply hide and then remove the popup.
What I am trying to do is register an eventListener after the popUp div is added to the page. Tried with both jquery and without and am after the same issue. (I included both below but only one is active in the code at a time.)
createProfilePopUpEventListener: function(){
$('body').on('click', function(){
$('.profile_pop_up').fadeOut('fast').remove();
});
},
createProfilePopUpEventListener: function(){
var el = document.getElementsByTagName('body')[0];
el.addEventListener("click", $('.profile_pop_up').fadeOut('fast').remove();
},
showPopUp: function(e){
//creates popUp and adds it to the DOM
this.createProfilePopUpEventListener();
}
What seems to be happening is that the event is being triggered right away on the initial click to show the popup and thus it is never displayed. How can I create an eventListener that only starts listening for those clicks at a certain time?
I guess your problem is event propagation. Your image that is used as the trigger to open the popup bubbles your event up the whole DOM, eventually to the body. Thus the fadeout/remove event is triggered at the same time as your open event.
You will need to stop the propagation of that in such a fashion (using :
$('#popup_trigger').on('click', function(event){
event.stopPropagation();
$('.profile_pop_up').fadeIn();
});

How do I hide a div if the user clicks outside of the div?

I have a button which, when clicked, changes the visibility of a div as such:
<button type="button" id="editbutton" onclick="plus()" alt="Edit"></button>
function plus() {
var f = document.getElementById('edit');
if (f.style.visibility == 'hidden') {
f.style.visibility = 'visible';
}
else
f.style.visibility = 'hidden';
}
This works fine. But now I want to add the functionality so that if the user clicks anywhere outside of the div, the div will go back to being hidden.
Initially I tried my own methods, but was unsuccessful because whenever I click the button to make the div visible, it is made hidden again by the new code. I've looked into some of the jQuery examples others have posted, however none of the ones I have tried fix this problem. Any help would me much appreciated.
EDIT: To clarify, the issue is that because the div is initially made visible by the user clicking on a button, whenever I click the button, the div is made visible but is immediately hidden again because that counts as clicking on the body of the page.
You could call 'e.stopPropagation()' on the event from within your click event handler when a user clicks within your div - this will stop the event from 'bubbling' up the DOM.
And then if you attach an event handler to the BODY element listening for clicks, you can use that event handler to hide the DIV; knowing that a click on the DIV itself won't bubble the event up to the BODY handler.
In this way any click on another element, unless the handler also calls stopPropagation(), will get caught by your handler. So if there are other cases where you don't want the div to hide you can stop it happening by calling stopPropagation() as required.
E.g.:
$("#edit-button").click( function(e) {
$("#edit").toggle();
e.stopPropagation();
});
$('#edit').click(function(e) {
e.stopPropagation();
});
$("body").click( function(e) {
$("#edit").hide();
});
Set a click handler on the body element. In the event you can check event.target to see if it matches the div, if it does: do nothing, else: hide it.
document.body.onclick = function(event) {
if (event.target === f) {
// user clicked on the div, do nothing
} else {
f.style.visibility = "hidden";
}
};
This becomes a bit more complex if you have elements within the edit div (and the .target doesn't match), but I'm sure you can come up with a solution :) (it can be done).
you seem like you know what you're doing so I'll keep it short.
write a .click function in jquery.
you give your button an id (or the div it is in)
$('#buttonidordiv').click(function(){
$('#divtoshow').show() // put in a number to create a fade in seconds.
//your stuff here
}
and if someone clicks anywhere outside it... I think you should be able to use window. Else you can use another div (like your wrapper).
so
$('window').click(function(){
$('#samediv').hide() //same as above
//your stuff here
}
do realize, I suck with the )}; so you might have to add one of those somewhere ;)
best of luck!

How to disable expand/collapse on double click in XUL table

I have a XUL tree in my Firefox extension. When I double click on a row, the row collapses or expands. How can I disable this behavior (so that collapsing and expanding can only occur by clicking on the plus/minus signs)? I'd like to reserve double clicking for something else.
I've tried to disable the default action and event propagation like below, but this didn't work. The event handler was executed but did not prevent the collapsing.
tree.addEventListener("dblclick", onTreeDoubleClick, true);
onTreeDoubleClick = function(event) {
event.preventDefault();
event.stopPropagation();
}
The tree gets the event before you do. AFAIK the only way to get it earlier is to register a capturing event handler on the parent element of the tree:
tree.parentNode.addEventListener("dblclick", onTreeDoubleClick, true);
Of course, that assumes that the parent element doesn't contain element other than the <tree>, otherwise you catch the events on these elements as well - but you can always put the <tree> element into its own <box> element just for that.

Categories

Resources