JQuery acts as if it traverses DOM tree as Capturing - javascript

Digest:
Problem using jQuery and jQuery mobile with a radio button inside a tr tag.
A: click event handler of radio, B: click event handler of tr
When using radio button, B->A (tr.click then radio.click)
When using other elements, A (a.click then propagation stopped by
API)
Environment:
jQuery 1.11.3
jQuery Mobile 1.4.5
Running on Firefox 43.0
Details:
Hi,
I've encountered a problem while trying to handle click event in jQuery mobile when using a radio element inisde a table tag. The html code below shows how the DOM element looks like. You could see that the radio is inside the th tag and of course it is inside the table header tag. (#order_title)
<table class="w3-table w3-bordered w3-striped w3-border w3-hoverable" id="order_list" >
<tr class="order_title" order_id="1">
<th>a</th>
<th>b</th>
<th>
<fieldset data-role="controlgroup" data-type="horizontal">
<input name="sumshare_switch1" id="viewsum1" class="button_viewsum" type="radio" checked>
<label for="viewsum1"> summary </label>
<input name="sumshare_switch1" id="calshare1" class="button_calshare" type="radio">
<label for="calshare1"> calculate </label>
</fieldset>
</th>
</tr>
</table>
I've bounded two click events with the order_title as below:
$('.button_calshare').on( "click", function(e){
//do something(A)
e.stopImmediatePropagation();
});
$('.order_title').on("click", function(e){
//do something(B)
});
I anticipated that when the user click on the radio button with class "button_viewsum",
it should first trigger the event from $('.button_calshare'), then stopped by the stopImmediatePropagation function. Expected result is "something(A)" only.
However, when I tested on it, it turns out that result is "something(B) --> something(A)"
I searched for this problem, however, all I found is that in jQuery, event should bubble up as I expected.
My current solution is to use "a" tag to replace radio
<fieldset data-role="controlgroup" data-type="horizontal">
a
<a href="#" data-role="button" data-transition="fade" class="button_calshare" >b</a>
</fieldset>
and the event started to bubble instead of capture!
(Namely, only "Something(A)" happened, B is stopped by the stopPropagation function! )
Though my implementation problem is solved, I would really like to know why does the radio button doesn't work like I expected.
Thanks in advance!

Related

Click event triggering two times

I am trying to run some function when clicking on the label text but the click event fired two times.
HTML
<label class="label_one">
Label One
<input type="checkbox"/>
</label>
But its not happening if I change the html code like this.
<label for="test" class="label_two">
Label Two
<input type="checkbox"/>
</label>
My script is this:
$('.label_one').click(function(){
console.log('testing');
});
Can anyone explain me why this is happening like this.
My jsfiddle is here check it ones.
https://jsfiddle.net/sureshpattu/hvv6ucu8/3/
It is because of event bubbling.
In general all elements bubble the event to the root of the document whereas the label tag will bubble the event to its child nodes and thats how the input tag is getting ticked when you click the label dom.
So in your case you attached the event handler to label tag so
It calls when label tag gets clicked
event bubbles inside it and checkbox gets selected and checkbox bubbles the event to its parent node that is label tag again hence it is called twice.
To solve this, just attach the event handler to input/checkbox tag it should work fine.
I couldn't reproduce this in the version of chrome that I'm using.
But if you're facing this in some browser, it's likely because -
According to spec, labels containing inputs, and the ones connected to an input via for attribute trigger a click on the associated input when they are clicked.
So in your first case, there are 2 click events:
Actual click on <label>
Click triggered on <input> by the label
The one triggered on <input> will bubble up to <label> and trigger your handler.
In the second case, Since a for attribute is specified and there is no matching input with id of 'test', the additional click is not triggered even if the input is inside the label.
Click on checkbox do click on label. Try use .change event on input
$('.label_one input').change(function(){
var html = '<div class="log_sec_one">Log</div>';
$('.logs').append(html);
});
$('.label_two input').change(function(){
var html = '<div class="log_sec_two">Log</div>';
$('.logs').append(html);
});
DEMO
Move your input outside of your label, and use the for="" attribute.
<label class="label_one" for="checkbox_one">
Label One
</label>
<input type="checkbox" id="checkbox_one" />
<br/><br/>
<label for="checkbox_two" class="label_two">
Label Two
</label>
<input type="checkbox" id="checkbox_two"/>
<div class="logs"></div>
JSFiddle: https://jsfiddle.net/hvv6ucu8/2/
<label for="text" class="label_one">
Label One
<input type="checkbox"/>
</label>
<br/><br/>
<label for="text" class="label_two">
Label Two
<input type="checkbox" name="1"/>
</label>
you forgot to put for attribute in label (label_one). just change that. it will work

Is there a maximum number of elements I can bind a jquery event to?

I'm building a simple 1 page app that allows someone to curate a list of json feeds. I'm running into an issue with trying to bind a mouseenter/mouseleave event to all the inputs on the page with a given class. Simply, put the first works and the second does not.
I have to following jquery:
$(".feed").on("mouseenter", ".publish", function(){
console.log("feed")
}); //this is for test purposes
$(".feed").on("mouseenter", ".keys-input", function(){
console.log($(this));
$(this).siblings(".delete").fadeIn(75);
});
$(".feed").on("mouseleave", ".keys-input", function(){
$(this).siblings(".delete").fadeOut(75);
});
and the following html:
<div class="feed"><!-- sorry for the confusion -->
<div class="feed-header">
<h2>pga-2013.json</h2>
<button class="publish button-white-bg button-save">Publish</button>
</div>
<div class="kvRow collapsed">
<span class="delete icon">x</span>
<input type="text" class="keys-input" value="free" disabled=""/>
<input type="text" class="values-input" value="0" disabled=""/>
</div>
</div>
The reason I ask if there is a max number of elements you can bind to is because the ".feed" event triggers and there are only 11 of them on the dom whereas the ".keys-input" event does not and there are 7266 of them on the dom. Either that or I'm blind and doing something dumb...
here's a fiddle with fewer elements but the same code that works http://jsfiddle.net/khLPc/
this is the issue: Event on a disabled input the inputs are disabled so they won't fire events which is bananas to me...
The event is not triggered on the disabled element.
Enable the input and it will work.
Check here, I've enabled one of the input fields:
http://jsfiddle.net/balintbako/khLPc/1
Apparently I have to include some code too:
<input type="text" class="keys-input" value="free"/>

jQuery Mobile click event.preventDefault does not seem to prevent change

I am trying to prevent a radio button from changing when a use clicks, it works when using standard jQuery but when you include jQuery Mobile it does not seem to work, is there something else I have to do in jQuery Mobile?
<fieldset data-role="controlgroup" data-type="horizontal">
<input type="radio" name="trade-direction" id="buy" value="B" checked="checked" />
<label for="buy">Buy</label>
<input type="radio" name="trade-direction" id="hold" value="H" />
<label for="hold">Hold</label>
<input type="radio" name="trade-direction" id="sell" value="S" />
<label for="sell">Sell</label>
</fieldset>
$('[name="trade-direction"]:radio').click(function(event) {
if(!confirm("Do You Want To Change?")) {
event.preventDefault();
}
});
below is a link to the code in jsFiddle.
http://jsfiddle.net/mikeu/xJaaa/
The problem is that with jQuery.Mobile, the element that is effected by the UI change is not the input element. In fact, the radio element isn't actually clicked at all. The Element that is clicked is <div class="ui-radio">. If you want to bind to the radio input itself, you need to use the change event, but in this case it won't work for you, because the function gets called after the change has already taken place.
What you need is something like this:
// Probably a good idea to give your fieldset an ID or class
$('fieldset').delegate('.ui-radio','click',function(event){
if(!confirm("Do You Want To Change?")) {
event.stopImmediatePropagation();
event.preventDefault();
}
})
The event.stopImmediatePropagation() prevents the the .ui-radio from triggering the click event to the input, and the event.preventDefault prevents the default action. The stopImmediatePropagation may not be necessary, but it gives an added guarantee that may be helpful across different browsers.

jQuery stopPropagation not effective

I'm just completely stumped, I looked over a lot of the similar questions but I can't figure out why this click event keeps propagating.
Here is the code:
$("#view-radio").buttonset().bind('click', function(e) {
redraw(Testimonials);
e.stopPropagation();
});
Here is the radio buttons
<div id="view-radio" class="i-obj buttonset">
<input type="radio" id="gridradio" name="view-radio" checked="checked" value="grid" />
<label for="gridradio"> <img src="http://SwolePersonalTraining.com/beta/wp-content/themes/striking/images/gridview.jpg" class="icon">Grid View</label>
<input type="radio" id="listradio" name="view-radio" value="list" />
<label for="listradio"><img src="http://SwolePersonalTraining.com/beta/wp-content/themes/striking/images/listview.jpg" class="icon">List View</label>
</div>
You can find the page in action here: http://swolepersonaltraining.com/beta/?page_id=380
Here is the complete code: http://swolepersonaltraining.com/beta/wp-content/themes/striking/js/custom/custom_testimonial.js?ver=3.1.3
Any ideas?
I can't swear it because it's difficult to test in your live site, but I think that what's happening is that you bound the click event of the view-radio div instead of each of the two radio buttons inside it.
I'd try something like:
$("#view-radio").buttonset(). // Turn radio buttons of the div in a buttonset
find('input').bind('click', // Bind the click event of each of the two radios
....
EDIT:
Yes! It works!
http://jsfiddle.net/marcosfromero/TDsrj/
And stopPropagation isn't needed (read other answers to know why).

IE6 forces two clicks to trigger Javascript event

I have a web form that has 2 radio buttons, depending on which one is clicked it displays a hidden element
This works fine in all browsers except for IE6, which, after I click on the radio button, I have to click again (anywhere on the window) and then the element is displayed...has anyone had behavior like this before?
I tried to not use jQuery and do straight getElementById() but I get the same behavior...
Javascript
function showHidden(divid) {
$('#'+divid).css( {'display':'inline'} );
}
HTML
<input type=radio name=borp value=1 onChange='showHidden("brandchecks")' > Brand
<input type=radio name=borp value=2 onChange='showHidden("productchecks")' > Product
<div id='brandchecks' style='display:none;'>
Blah
</div>
<div id='productchecks' style='display:none;'>
Blah
</div>
I thought I remember something about IE firing the onChange event after the focus was lost. This behavior would match what you have seen (ie clicking somewhere else to active your code)
Try to change the onChange in onClick for better results.
Note: To be able to click on the text accompanying the radio buttons you could use the <label> tag, this results in a more user-friendly page.

Categories

Resources