I'n new to javaScript and jQuery. How is this possible to call the click event of parent element when you click its child?
I have this structure in my code:
<ul id="pc5">
<li>book
</li>
</ul>
I want something like this:
$("a").click(ul.click);
Any help would be appreciated.
EDIT: in my ul click function I need ul id attribute. something like this:
ul.click(function(e){alert(e.target.id);
so when link is clicked, event.target isn't ul element.
If your child element is located inside your parent element you could also just add this CSS property.
.child {
pointer-events: none
}
This way the click directly triggers the parent's click event listener.
This feature's support is quite good.
You dont need to trigger element click events when child elements are clicked, the click event bubbles up the dom tree if you dont stop propagation.
Here you can see it working: jsfiddle just click on the blue span, the click event will bubble up to the ul :)
Updated question
If you want the id of the ul, simply to:
$('ul li a').click(function() {
var id = $(this).closest('ul').attr('id');
});
Which would be even easier like so:
$('ul').click(function() {
var id = $(this).attr('id');
alert(id);
});
Working fiddle
This should work if you click on an since it bubbles up
You should read about event propagation in jQuery. In few words: when user clicks on a then event will be propagated up in DOM tree.
I had html like this:
<a href="?chk=1">
<input id="CHK_1" name="CHK[1]" type="checkbox">
<span>CHK 1</span>
</a>
where checkbox was supposed to be checked/unchecked only from server side.
For reason i don't know, 'click' was not bubbling from checkbox to link,
so i used js code like this:
$(document).on('click', '[id^="CHK_"]', function (e){
window.open($(this).parent().attr('href'), '_self');
e.preventDefault();
});
Related
I have a situation where I have attached an onclick event to an anchor tag, but it has a span tag inside as a child; hence when I do something like this:
HTML:
<a href="#" class="toggle js-toggle" data-target-cat="3">
<span class="icon-angle-down"></span>
</a>
JS:
$('.js-toggle').on('click', function(e) {
e.preventDefault();
var cat_id = $(e.target).data('target-cat');
});
It doesn't work as e represents the span element; sure I can just put the attribute on the span again, but I am paranoid that sometimes the anchor may trigger it rather than the span and I don't want to duplicate the attribute on both elements.
So I decided to do this:
$('.js-toggle').on('click', function(e) {
e.preventDefault();
var cat_id = $(e.target).data('target-cat');
if (typeof cat_id === "undefined") {
// Seems the click was triggered by a child of the anchor tag; grab it from the parent
cat_id = $(e.target).parent().data('target-cat');
}
});
This works, however I'm not overly comfortable doing it this way as what happens if the children elements change inside the anchor.
Is there a more consistent way of doing this or should I perhaps put the onclick event on the span tag instead?
Bonus Question: Why does e.preventDefault(); work if e represents the span tag and not the anchor?
You're using event.target which references the element the event was initiated for. But what you want is to access the element you registered the event handler on - see event.currentTarget.
For your "bonus question" you need to understand that the default action can be prevented on any element at anytime during the capture or bubble phase. That said, because you registered the event handler on the <a>, that's where you're preventing the default, not on the the <span> as you assumed.
Try $(this) instead of $(e.target):
$('.js-toggle').on('click', function(e) {
e.preventDefault();
var cat_id = $(this).data('target-cat');
});
To answer your bonus question:
e.preventDefault() works because the event is on the anchor tag and not on the span element. As you can see here, you're calling the on click event on $('.js-toggle') which stands for the anchor tag.
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)
I'm using CSS sliding doors and when I try to attach an event handler to it, it doesn't seem to get triggered because of the span within the anchor.
I have the same CSS as the above link, with a class called 'button':
<span>Submit</span>
When I click on the far right side, it works, which is outside the span. But when I click on the span, it doesn't
I'm attaching an event handler like this:
$('.button').live('click', function(e){
alert('click');
});
Any suggestions for this?
Thank you!
Just put the event listener on the span instead.
$('.button span').on('click', function(e){
alert('click');
});
Check out this fiddle. It works.
It maybe in the CSS.
Also, I changed "live" since it's deprecated.
$('.button').on('click', function() {alert('click')});
I have some HTML like this:
<a class="button">
<span>
<span>
<span class="buttonspan">Content</span>
</span>
</span>
</a>
I already have some events on the parent Anchor object. Now I am trying to add a click event on to the child span element and at the same time to disable click events on the parent Anchor object. I am using jQuery to achieve this, but I could not figure out. My jQuery code is like this:
$('a.button').click(function(event){
return false;
});
$('.buttonspan').live('click', function(event){
event.preventDefault();
event.stopImmediatePropagation();
// some function
});
If I execute the code above, it prevents the child element click event as well. But if I do not the first part, the parent click event will be triggered as well. Is there a way to disable the parent event without disabling the newly added child click event?
You could set the click event on the parent button and use the event target to determine what was clicked and perform the necessary actions.
$('a.button').click(function(e) {
var $target = $(e.target);
if ($target.is('.buttonspan')) {
// do actions for the .buttonspan click
} else {
// do actions for a click anywhere else inside a.button
e.preventDefault();
}
});
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.