Prevent icon inside disabled button from triggering click? - javascript

Trying to figure out proper way to make a click event not fire on the icon of a disabled link. The problem is when you click the Icon, it triggers the click event. I need the selector to include child objects(I think) so that clicking them triggers the event whenever the link is enabled, but it needs to exclude the children when the parent is disabled.
Links get disabled attribute set dynamically AFTER page load. That's why I'm using .on
Demo here:(New link, forgot to set link to disabled)
http://jsfiddle.net/f5Ytj/9/
<div class="container">
<div class="hero-unit">
<h1>Bootstrap jsFiddle Skeleton</h1>
<p>Fork this fiddle to test your Bootstrap stuff.</p>
<p>
<a class="btn" disabled>
<i class="icon-file"></i>
Test
</a>
</p>
</div>
</diV>​
$('.btn').on('click', ':not([disabled])', function () { alert("test"); });​
Update:
I feel like I'm not using .on right, because it doesn't take the $('.btn') into account, only searching child events. So I find myself doing things like $('someParentElement').on or $('body').on, one being more difficult to maintain because it assumes the elements appear in a certain context(someone moves the link and now the javascript breaks) and the second method I think is inefficient.
Here is a second example that works properly in both enabled/disabled scenarios, but I feel like having to first select the parent element is really bad, because the event will break if someone rearranges the page layout:
http://jsfiddle.net/f5Ytj/32/

Don't use event delegation if you only want to listen for clicks on the .btn element itself:
$('.btn').on('click', function() {
if (!this.hasAttribute("disabled"))
alert("test");
});​
If you'd use event delegation, the button would need to be the matching element:
$(someParent).on('click', '.btn:not([disabled])', function(e) {
alert('test!!');
});​
Demo
Or use a true button, which can really be disabled:
<button class="btn" [disabled]><span class="file-icon" /> Test</button>
Demo, disabled.
Here, no click event will fire at all when disabled, because it's a proper form element instead of a simple anchor. Just use
$('.btn').on('click', function() {
if (!this.disabled) // check actually not needed
this.diabled = true;
var that = this;
// async action:
setTimeout(function() {
that.disabled = false;
}, 1000);
});​

.on('click', ':not([disabled])'
^ This means that, since the icon is a child of the button ".btn", and it is not disabled, the function will execute.
Either disable the icon, also, or apply the event listener only to the <a> tag that is your button, or use e.stopPropagation();
I would suggest using e.stopPropagation();, this should prevent the icon from responding to the click.
That doesn't seem to work for me ^
Disabling the icon, however, does.

I would prefer to add the event using delegation here as you are trying to base the event based on the attributes of the element.
You can add a check condition to see if you want to run the code or not.
$('.container').on('click', '.btn', function() {
if( $(this).attr('disabled') !== 'disabled'){
alert('test!!');
}
});​
Check Fiddle

You're not using the selector properly.
$('.btn').not('[disabled]').on('click', function () {
alert("test");
});​
See it live here.
Edit:
$('.container').on('click', '.btn:not([disabled])', function () {
alert("test");
});​

I think what you need is:
e.stopPropagation();
See: http://api.jquery.com/event.stopPropagation/

Basically something like the following should work
$('.icon-file').on('click', function(event){event.stopPropagation();});
You may want to add some logic to only stop bubbling the event when the button ist disabled.
Update:
not sure, but this selector should work:
$('.btn:disabled .icon-file')

Related

Disable HTML Link after it has been Clicked

I am trying to disable a link that submits my form after it has been clicked. This is needed to stop duplicate requests from the same user. Here is my code, but unfortunately it is not working.
<a id="submit-form-link" onclick="document.forms[0].submit()" class="next">Next <span>Step</span></a>
<script type="text/javascript">
$('#submit-form-link').click(function(){
$('submit-form-link', this).attr('style', 'pointer-events: none;');
});
</script>
I feel like I am close but it just is not working.
You're going about this wrong. Get rid of the inline onclick event handler and use this inside a document ready call:
$('#submit-form-link').one('click', function(){
$('form').submit();
});
This binds the click event to your link, but unbinds it after the first click.
You can see this in the console in this jsFiddle example. The first time you click the link it attempts to submit the form, but doesn't try on subsequent clicks.
Try this:
...
$('submit-form-link').off().click(function() { return false; });
...
<a id="submit-form-link" onclick="document.forms[0].submit()" class="next">Next <span>Step</span></a>
<script type="text/javascript">
$('#submit-form-link').click(function(){
if (!$(this).hasClass('disabled')) {
$('submit-form-link', this).attr('class', 'next disabled');
return true;
}
return false;
});
</script>
Here, you can create a class disabled and style it as you want. Just add this class after clicking the button so you will know that it is disabled. Then you return false to stop the event if the button was already clicked.
bind the click event again in the first click event callback function
$('#submit-form-link').click(function(){
$('submit-form-link', this).attr('style', 'pointer-events: none;');
$(this).click(function(e){e.preventDefault})
});
You have to remove the onclick attribute.
$('#submit-form-link').click(function(){
$(this).removeAttr('onclick');
});
Also, $('submit-form-link', this) is totally wrong. You are selecting nodes of type submit-form-link that are children of this. First of all you'd need #submit-form-link and second this is already a reference to the link node you just clicked.

Change Div Class on click takes multiple clicks before it works

I used the methods in this question:
change div class onclick on another div, and change back on body click
So here's my jQuery function:
jQuery('.checkbox_wrapper').on('click', function(e){
jQuery(this).parent()
.toggleClass('not_selected')
.toggleClass('selected');
});
However it doesn't seem to be working properly. It takes multiple clicks before the class changes.
See my jsfiddle:
http://jsfiddle.net/7A3vw/
I cut it down to the bare essentials thinking it might be conflicting javascript, but even with the single function it takes multiple clicks before the class actually changes. Because the production environment has 1 click toggle a hidden checkbox, multiple clicks is not reasonable.
Could someone help me figure out what's causing this issue?
The click function fires twice, once for the image, and once for the input, as both will bubble to the parent element, and firing twice reverts the classes again (proof).
Just target the image instead, as that is what you're really trying to click, not the parent :
jQuery('.deck_card img').on('click', function (e) {
jQuery(this).closest('div').parent().toggleClass('not_selected selected')
});
FIDDLE
i guest you need the checkbox checked together with the toggling of your div.
$(document).ready(function(e) {
$('.checkbox_wrapper').on('click', function(e){
var checked = $(this).find('input[type="checkbox"]').is(":checked");
if(checked){
jQuery(this).parent().addClass('selected').removeClass('not_selected');
}else{
jQuery(this).parent().addClass('not_selected').removeClass('selected');
}
});
});
Your code is triggering click event twice. So use .preventDefault()
This makes the default action of the event will not be triggered.
$('.checkbox_wrapper').on('click', function(e){
$(this).parent()
.toggleClass('not_selected')
.toggleClass('selected');
e.preventDefault(); // prevent the default action to be
}); // triggered for next time
Check this JSFiddle
try this
jQuery(document).on("click",'.checkbox_wrapper', function(e){
jQuery(this).parent()
.toggleClass('not_selected')
.toggleClass('selected');
});
Multiple Clicks are getting triggered because you are using class selector. You need to use not to exclude extra elements :
jQuery("div.checkbox_wrapper :not('div.checkboxdiv')").on('click', function(e){
jQuery(this).parent()
.toggleClass('not_selected selected')
});
Here is a FIDDLE.

Excluding an element from jQuery selection

I'm trying to get a .click() event to work on a div.content except if clicked on something with a specific class, say, .noclick. Example html:
<div class="content">
<a href="#" class="noclick">
</div>
Doing this doesn't work because the <a> tag is not technically in the selection:
$('.content').not('.noclick').click(function(){/*blah*/});
How can I get the click function to work if I click anywhere on .content except something with class .noclick?
You'd have to exclude them from within the callback:
$('.content').click(function(e) {
if ($(e.target).hasClass('noclick')) return;
});
Or stop the event from leaving those elements:
$('.noclick').click(function(e) {
e.stopPropagation();
});
I would go with the second one. You can just drop it and your current code (minus the .not()) will work.
$('.content').click(function(event) {
// ...
}).find('.noclick').click(function(event) {
event.stopPropagation();
});
$('.content').click(function(e){
if(!$(e.target).is('.noclick')){
// Handle click event
}
});
$('.content').
on('click', '.noclick', function(){return false;}).
click(function(){alert("click")})
cancels clicks on '.noclick', yet fires clicks elsewhere
http://jsfiddle.net/FshCn/

jQuery .on('click') firing multiple times when used with :not() selector

Good morning,
I have a set of boxes on a page that are presented as a list, and within these boxes there might be some links that can be clicked. I want the links within the boxes to work as normal (i.e. bubble up and either perform the default action or then be handled by event handlers further up the DOM), but if the box is clicked anywhere else then it should be caught by a particular event handler attached to the "list" containing all the boxes.
Simple html representation
<div class="boxlist">
<div class="box" data-boxid="1">
Some text, and possibly a link and another link, and perhaps even a third link.
</div>
<div class="box" data-boxid="2">
Some more text, this time without a link.
</div>
</div>
The javascript that I thought should work.
$(function () {
$('.boxlist').on('click', '.box :not(a)', function (e) {
var boxid= $(this).closest('.box').data('boxid');
console.log('open: ' + boxid);
});
});
My expectation was that the above javascript should handle all clicks that did not originate from tags. However, for some reason when the box is clicked (either the box itself, or an tag, doesn't matter), it fires this event X times, where X is the total number of tags within the list of boxes.
So I have two questions:
1. What am I doing wrong with the :not() selector.
2. Is there a better way to handle this scenario?
Thank you for helping!
linkUsing jQuery :not selector actually is very slow ex:http://jsperf.com/not-vs-notdasdsad/4 and it's way better to just use event delegation. So in this case you want to keep track of every click on the .boxlist but check the node type to see if its an anchor or not. This is an example.
$(function () {
$('.boxlist').on('click', function(ev){
if(ev.target.tagName != "A"){
// handle box click code
console.log('box click');
return false;
}
// Otherwise allow event to bubble through.
});
});
and here is a jsfiddle example
http://jsfiddle.net/drXmA/
Also their are a few reasons your code doesn't work
.box :not(a)
should be
.box:not(a)
and the reason this also does not work is because .box is not an anchor tag it has children elements that are anchor tags it will never find an anchor tag named .box if their is one the callback would not execute. Changing the .box to an anchor tag will make it so the code doesn't execute because .box is an anchor and it is only running when .box:not(a)
I guess you want something like this:
$('.boxlist').on('click', '.box:not(a)', function (e) {
var boxid = $(this).closest('.box').data('boxid');
console.log('open: ' + boxid);
}).on('click', '.box a', function (e) {
e.preventDefault().stopPropagation();
});
DEMO FIDDLE
I think better to stop the default behavior and stop the event bubbling to its parent. .on() chain to the .box items excluding <a> from it and stop the default behavior and event bubble with e.preventDefault().stopPropagation();

change div class onclick on another div, and change back on body click

Let me define the problem a little bit more:
i have
<div class="contact">
<div id="form"></div>
<div id="icon"></div>
</div>
i want onclick on #icon, to change the class of .contact to .contactexpand( or just append it).
Then i want that the on body click to change the class back, but of course that shouldnt happen when clicking on the new class .contactexpand, and if possible that clicking on icon again changes the class back again.
I tried numerous examples and combinations but just couldn't get the right result and behavior.
Check this: Working example
Let's go step by step
I want onclick on #icon, to change the class of .contact to .contactexpand( or just append it). […] and if possible that clicking on icon again changes the class back again.
You want to use the toggleClass() method to achieve this. Simply:
$('#icon').on('click', function(e){
$(this).parent()
.toggleClass('contact')
.toggleClass('contactexpand');
});
Then i want that the on body click to change the class back
You will have to make sure that body removes contactexpand class and adds contact. At this point I would just give the container element an id (or class if you prefer), just to make things simpler. Then what you do is pretty simple:
$('body').on('click', function(e){
$('#thisdiv')
.removeClass('contactexpand')
.addClass('contact');
});
but of course that shouldnt happen when clicking on the new class .contactexpand.
This is the step that the other answers missed, I think. Since everywhere you click, you also click on the body element, you will always trigger the click event on the body, hence removing the contactexpand class and adding the contact one.
Enter event.stopPropagation(). This method will make sure that the events doesn't bubble up the DOM, and will not trigger the body click.
$('#thisdiv').on('click', function(e){
e.stopPropagation();
});
Working example
You can add a class to parent element like the following code.
$(".contact #icon").click(function(){
var element = $(this).parent(".contact");
element.removeClass("contact").addClass("contactexpand");
});
I like to the jQuerys toggleClass function like so:
$('#icon').click(function(){
$('#contactbox').toggleClass('contact');
$('#contactbox').toggleClass('contactexpand');
});
Or you could use addClass('className') and removerClass('className') if you would like to apend it rather than toggle it :)
Here is an example: http://jsfiddle.net/aUUkL/
You can also add an onclick event to the body of the page and use hasClass('className') to see whether or not to toggle the class when the body is clicked. You could use something like this (Although I havent tested this bit!):
$('body').click(function(){
if( $('#contactbox').hasClass('contactexpand') ){
$('#contactbox').addClass('contact');
$('#contactbox').removeClass('contactexpand');
}
});
You can do this
$('body').on('click', function(event) {
if ($(event.target).attr('id') == 'icon') {
$(event.target).parent().toggleClass('contactexpand');
} else {
$('.contact').removeClass('contactexpand');
}
});
Check out this jsfiddle
var $contact = $('.contact');
$contact.find('#icon').click(function(e, hide) {
e.stopPropagation();
$contact[hide ? 'removeClass' : 'toggleClass']('contactexpand');
});
$(document).on('click', function(e) {
if (e.srcElement === $contact[0]) return;
$contact.find('#icon').trigger('click', true);
});
http://jsfiddle.net/kZkuH/2/

Categories

Resources