jQuery - only calling .click() on the foreground element? - javascript

http://jsfiddle.net/waitinforatrain/8AqgU/
The example in that link shows a nested ordered list. If you open up your Chrome/Firebug console, you can see that clicking a child element causes a .click() event on its parents as well.
Is there a way to just detect the .click() on the visible foreground element that was clicked?

You just need to stop the propogation of the click:
$('#toc li').click(function(e) {
console.log ($(this).attr('id'));
e.stopPropagation();
});
Check out this page for more info

Related

Hide context menu on outside click

I have a context menu that appears when you right click inside the <div>, and it only goes away if the user click left click inside the <div> again.
How do i hide it when a user click anywhere on the page?
my fiddle
change these two functions to the following:
_onPageClick: function(e) {
e.stopPropagation()
if (this.refs.contextMenu.getDOMNode() !== e.target){
this.contextMenu.setState({contextMenuLocation: ''});
}
},
componentDidMount: function(){
this.contextMenu = this.refs.contextMenu;
document.addEventListener('click', this._onPageClick)
},
all we have to do is to move _onPageClick from the wrapper div to a listener on the document. the above code will close the menu if the user clicks anywhere that is not inside the context menu. if you want it to close if the user clicks the context menu as well, then change _onPageClick to:
_onPageClick: function(e) {
e.stopPropagation()
this.contextMenu.setState({contextMenuLocation: ''});
}
(also, the wrapper div should no longer have the onClick handler)
http://jsfiddle.net/yikevinqu/eeu9unhm/1/
Check out Ben Alman's clickoutside jQuery plugin. Even if you are not using jQuery, you can review his mechanism for catching these click events as they bubble up.
http://benalman.com/projects/jquery-outside-events-plugin/
All click events get bubbled up through the DOM, so if you click an inner element, if you don't event.stopPropagation(), it will bubble up to the parent element. So just catch the click on the parent element (can even be document to hide your context menu).
Check out my fiddle for a pure JS example: http://jsfiddle.net/jsc8zLaj/
There's actually an existing React mixin on npm you can use for this:
https://github.com/Pomax/react-onclickoutside
Since mixins have fallen out of favour now, you may want to implement it as a wrapper component instead, but this is an excellent starting point.

jQuery .not() issues

The premise of what I'm trying to do is use jQuery to start a CSS transition to open and close a search box.
User clicks magnifying glass icon, box opens, user clicks anywhere on the page but the search form, box closes.
To close, using this:
$('body *').not('#header-search, #header-field, #header-submit').click(function () {
And different variations of the answer found here: jQuery - Select everything except a single elements and its children? without success.
Clicking on the input#header-field always closes the box.
Pen Here:
http://codepen.io/anon/pen/RNbmwr
Thanks for reading.
Your code is very aggressive (it gets applied to all elements, so inner element to those in the .not() will trigger it).
It is better to delegate the closing of the box to the body (since click events bubble up), and manually cancel any event that occurs under the forbidden list.
$('body').on('click', function(){
// code for closing box here
});
$('#header-search, #header-field, #header-submit').on('click', function(){
return false; // stop bubbling of event
});
And since in your example the #header-field and #header-submit are descendants of header-search you only need to cancel the bubbling on that
$('#header-search').on('click', function(){
return false; // stop bubbling of event
});
Demo at http://codepen.io/gpetrioli/pen/XJrwXO
Try the jQuery toggle() function:
<script>
$( "button" ).click(function() {
$( "p" ).toggle( "slow" );
});
</script>
Substitute the id for your magnifying glass for "button" and change the paragraph -- $("p") -- the search controls you want to show/hide. Toggle changes the visibility of the indicated id or class. If it is initially hidden, mouse click will make it visible; if initially visible, mouse click will hide it.
Finally, change the speed of the transition if you don't want it to move "slow"
A more complete explanation of toggle() is available at http://api.jquery.com/toggle/
There are many elements on the page. Some of them may contain or be contained by the elements you name. So they will still trigger the event.
Instead, bind a single event handler:
$("body").click(function(evt) {
and check if you clicked on one of the elements:
if( $(evt.target).parents("#header-search").length > 0) {
cancelling the handler if so:
return true;
}
Perform the actual event otherwise:
doSomething();
});

Attach Click Event to HTML after Menu Click

I've got a dropdown menu on a site I'm working on that has different classes added to it when it is activated. It's built into a WordPress theme so I'm having to build a workaround on it for iPad landscape mode. The site navigation displays the same as desktop when on landscape so I need to create some touch events to mimic the behavior.
The first thing I'm having to do is to deactivate the link on the first click and then reactivate it if it's clicked again. This works fine.
if ('ontouchstart' in document.documentElement) {
$('#masthead nav ul > li:has(.sub-menu) a').click(function(e){
e.preventDefault();
$('li.clicked_link').on('click', function(){
var this_link = $(this).find('> a').attr('href');
document.location.href=this_link;
});
$(this).parent().addClass('clicked_link');
});
}
The problem is that when you click on the li.sub-menu it adds a class of sub-hover onto it which activates a dropdown menu. It's a CSS/jQuery dropdown menu so it's based on the presence of that sub-hover class. It works fine when I first click but I then want to remove that class when you click outside of it. It deactivates it if I click another link in the dropdown but I'd like to bind a click event to the html or body elements so if you click anywhere outside of it, it will remove the sub-hover class, thus removing the dropdown.
I tried to do this:
if ('ontouchstart' in document.documentElement) {
$('#masthead nav ul > li:has(.sub-menu) a').click(function(e){
e.preventDefault();
$('li.clicked_link').on('click', function(){
var this_link = $(this).find('> a').attr('href');
document.location.href=this_link;
});
$(this).parent().addClass('clicked_link');
$('html').on('click',function(){
$('#masthead nav ul > li:has(.sub-menu)').removeClass('sub-hover').removeClass('clicked_link');
});
});
}
It doesn't work though because it seems to fire the first click function and then immediately fire the html click function. I tried to use bind as well but the same thing happened. I also tried it outside of the initial click function but, as you can guess, it fires the two click events simultaneously which doesn't work.
How do I get it to bind but not fire the click event only after the initial click event takes place?
This is not a direct fix for the problem, but something that might help you fix the problem (Too long for a comment).
You are binding click handlers inside another click handler without unbinding the previous ones, So everytime you click a matching <li> new click handlers are being added to <html> and other matching elements. I strongly believe you're not doing it on purpose and isn't aware of it.
Leaving that, You're trying to bind a click for .clicked_link using
$('li.clicked_link').on('click', function(){
This code looks for matching elements currently present in DOM, and probably finds no matching elements since you're actually adding the class clicked_link after it.
You actually need to delegate this handler to check for matching elements in future.
The events are bubbled up till the root element, in other words: you if you click an anchor, starting from the anchor, all the parents till html will receive a click event, which you can prevent using e.stopPropagation();.
Ideally you're code should look something like this:
if ('ontouchstart' in document.documentElement) {
$('#masthead nav ul > li:has(.sub-menu) a').click(function(e){
e.preventDefault();
$(this).parent().addClass('clicked_link');
});
$(document).on('click','li.clicked_link', function(){
var this_link = $(this).find('> a').attr('href');
document.location.href=this_link;
});
$('html').on('click',function(){
$('#masthead nav ul > li:has(.sub-menu)').removeClass('sub-hover').removeClass('clicked_link');
});
}
(Can't go any further with the currently available info. Minimal code such as respective html structure or a demo would be helpful)

Finding all js events associated with a HTML element using Chrome

Is there a easy way to find all js events that are associated with a specific HTML element using Chrome?
Example:
HTML element
Cancel
Script:
<script type="text/javascript">
$(function () {
$(".cancel_link").click(function () {
//do something
});
$(".refresh_page").click(function () {
//do something
});
});
</script>
Find the html element in the Elements panel of the dev tools. Then click the Event Listeners tab in the right panel. In the top right hand corner of that Event Listeners panel there's a filter icon. When you click on it you can choose "All Nodes" (default) or "Selected Node Only".
Press F12 to open Developer Tools
Click the Elements tab
Select the element you with to analyze
On the right hand side click the Event Listeners tab
From that tab you can view all of the handlers bound to the element for each event.
Since you seem to use jquery, here is a previously posted solution:
// Bind up a couple of event handlers
​$("#foo").on({
click: function(){ alert("Hello") },
mouseout: function(){ alert("World") }
});​​​
// Lookup events for this particular Element
​$._data( $("#foo")[0], "events" );
you can find out more here: Can I find events bound on an element with jQuery?

Is it possible to have jQuery.click trigger on the top element only?

I'm trying to make a site where the user can click on any element to edit it's CSS. I use the following to add the click function to all <li>, <div> and <ul>.
$('li,div,ul').click(function () {
alert(this.id);
});
The problem is if I click on a <li> element, then I get the alert for that and any element underneath it. (all the containers).
Is it possible to have only the top element trigger when clicked?
You want to stop event propagation, you do this in jQuery by calling the stopPropagation method on the event object.
$('li,div,ul').click(function (e) {
e.stopPropagation();
alert(this.id);
});
I believe you'd want to use stopPropagation(); inside the click function.
It sounds to me like you're looking for .stopPropagation(). Calling stopPropagation will prevent the event from "bubbling" up to parent containers.

Categories