jquery stopPropogation() not working as expected - javascript

here is my html :
<span class="checkbox checked replacement" tabindex="0">
<span class="check-knob"></span>
<input type="checkbox" name="data[InfoPagesClient][3][info_page_id]" value="25" checked="checked" class="">
</span>
<label for="InfoPagesClient3InfoPageId" class="label">asdasd</label>
now I want to show hide this pencil box on checkbox click event..
javascript :
$("p.checkbox-group span.checkbox").on('click', function(){
if($(this).hasClass('checked')) {
$(imgId).hide();
} else {
console.log('aaaaaaaaaaa');
$(imgId).show();
}
});
$("label.label").on('click', function(e) {
if ($(this).siblings('span.checkbox').hasClass('checked')) {
$(imgId).hide();
} else {
$(imgId).show();
}
e.stopImmediatePropagation();
});
clikcing on label it is going to span click event and prints console value... I tried using e.stopPropogation() and stopImmediatePropogation().. but ti is not working..
any idea ??

e.stopPropogation() or e.stopImmediatePropogation() will prevent the event from bubbling up, but will not stop the event immediately.
You can use e.preventDefault() along with e.stopPropogation(). e.preventDefault() will prevent the default event from occurring. You can check with the following change in your code.
$("p.checkbox-group span.checkbox").on('click', function(e){
e.preventDefault();
e.stopPropagation();
if($(this).hasClass('checked')) {
$(imgId).hide();
} else {
console.log('aaaaaaaaaaa');
$(imgId).show();
}
});
$("label.label").on('click', function(e) {
e.preventDefault();
e.stopPropagation();
if ($(this).siblings('span.checkbox').hasClass('checked')) {
$(imgId).hide();
} else {
$(imgId).show();
}
});

When you use label with for, browser will automatically click the associated control which triggers the "click" event. That is another event triggered later, in your case when you use e.stopImmediatePropagation();, it just stops the current "click" event and has no effect on the event of the associated control fired after that
To fix your issue, try removing for
Use this:
<label class="label">asdasd</label>
Instead of:
<label for="InfoPagesClient3InfoPageId" class="label">asdasd</label>

If you add the id attribute to your checkbox, then the label will work. Then you can simplify your code as follows:
$(function () {
$("p.checkbox-group input[type=checkbox]").on('change', function () {
if (this.checked) {
$(this).parent().addClass('checked').siblings('a.edit-content').hide();
} else {
$(this).parent().removeClass('checked').siblings('a.edit-content').show();
}
});
});
http://jsfiddle.net/gFXcm/2/

mmmh, isn't it a feature instead of a bug ? shouldn't the click on the label trigger the same action as the click on the "checkbox" ? That's precisely why the for attribute is used I guess.

Related

Checking if my input box has been click or is 'in focus' pure js

I need to know if my input box is clicked so I can fire a script to do something, except none of the routes I'm attempting seem to do anything.
basic input box
<input type="text" id="search-stuff" placeholder="search"/>
Javascript
var inputBox = document.getElementById("search-stuff");
if (inputBox) {
inputBox.addEventListener('keyup',function () {
startSearch();
})
inputBox.addEventListener('onfocus',function() {
console.log('we clicked');
searchBoxClicked();
})
}
function searchBoxClicked() { console.log('we clicked it'); }
I need to know if the user clicks so I can clear some classes on previous elements before the user types something.
You nearly got it right. A few minor mistakes:
to listen to the focus event. onfocus isn't an event.
the keyup event is for listening when a keyboard button is released (following a keydown event). If you want to listen to a mouse click, use the click event.
var inputBox = document.getElementById("search-stuff");
if (inputBox) {
inputBox.addEventListener('click', function() {
startSearch();
});
inputBox.addEventListener('focus', function() {
searchBoxClicked();
});
}
function searchBoxClicked() {
console.log('focus');
}
function startSearch() {
console.log('click');
}
<input type="text" id="search-stuff" placeholder="search" />
Attach the event listener to your input instead of the form. Instead of getElementById you could iterate the children to find it or use a selector.
When using event listeners the event is click or focus not onclick or onfocus.
document.getElementById('search-stuff').addEventListener('focus',function() {
console.log('clicked it');
};
or
document.querySelector('#formName > input[type=text]').addEventListener('focus',function() {
console.log('clicked it');
});
document.querySelector('#formName > input[type=text]')
.addEventListener('focus',function() {
console.log('clicked on ' + this.name);
});
<form id="formName">
<input name="username" type="text" value="press here">
</form>

Event handling issue with label and input inside it [duplicate]

window.onload = function(){
var wow = document.getElementById("wow");
wow.onclick = function(){
alert("hi");
}
}
<label id="wow"><input type="checkbox" name="checkbox" value="value">Text</label>
This is my code, when I clicked on "Text" it will alert hi twice but when I clicked on the box, the onclick element will only trigger once, why?
When you click on the label, it triggers the click handler, and you get an alert.
But clicking on a label also automatically sends a click event to the associated input element, so this is treated as a click on the checkbox. Then event bubbling causes that click event to be triggered on the containing element, which is the label, so your handler is run again.
If you change your HTML to this, you won't get the double alert:
<input id="wowcb" type="checkbox" name="checkbox" value="value">
<label id="wow" for="wowcb">Text</label>
The label is now associated with the checkbox using the for attribute instead of wrapping around it.
DEMO
If your intention is to respond only to clicks on the label and not on the checkbox, you can look at the event.target property. It references the element that called the listener so that if the click wasn't on that element, don't to the action:
window.onload = function(){
var el = document.getElementById('wow');
el.addEventListener('click', function(event) {
if (this === event.target) {
/* click was on label */
alert('click was on label');
} else {
/* click was on checkbox */
event.stopPropagation();
return false;
}
}, false);
}
If, on the other hand, you want to only respond to clicks on the checkbox (where a click on the label also produces a click on the checkbox), then do the reverse. Do nothing for clicks on the label and let ones from the checkbox through:
window.onload = function(){
var el = document.getElementById('foolabel');
el.addEventListener('click', function(event) {
if (this === event.target) {
/* click was on label */
event.stopPropagation();
return false;
} else {
/*
** click is from checkbox, initiated by click on label
** or checkbox
*/
alert('click from checkbox');
}
}, false);
}
This version seems to have the most natural behaviour. However, changing the markup so that the label no longer wraps the checkbox will mean the listener is not called.
Event bubble.
The checkbox is the child node of the label. You click the checkbox. Event bubble to the label. Then alert pop up twice.
To prevent alert pop up twice when you click the checkbox. You can change you onclick function into this:
wow.onclick = function(e){
alert('hi');
stopBubble(e);
}
function stopBubble(e)
{
if (e && e.stopPropagation)
e.stopPropagation()
else
window.event.cancelBubble=true
}
Hope this can work for you.
The Label tag will be associated with the input tag inside it. So when you click the label, it will also trigger a click event for the input, then bubble to the label itself.
See this:
document.getElementById("winput").addEventListener('click', function(event){
alert('input click');
//stop bubble
event.stopPropagation();
}, false);
http://jsfiddle.net/96vPP/
Rammed headfirst into this gotcha again and decided to prove what it did to myself, hopefully helping me remember. To help future people to whom the above might not be clear enough, here the example I made.
https://jsfiddle.net/ashes/0bcauenm/
$(".someBigContainer").on("click", "input[type=checkbox]", ()=> {
$output.val("Clicked: checkbox\n" + $output.val());
});
edit: added the link with a snipped of the code.
This is probably the simplest answer. Just add a span around your text and stop event propagation.
window.onload = function(){
var wow = document.getElementById("wow");
wow.onclick = function(){
alert("hi");
}
}
<label id="wow">
<input type="checkbox" name="checkbox" value="value">
<span onclick="event.stopPropagation()">Text</span>
</label>
Or without inline-javaScript
window.onload = function(){
var wow = document.getElementById("wow");
wow.onclick = function(){
alert("hi");
}
var span = document.getElementsByTagName("span")[0];
span.onclick = function(event){
event.stopPropagation();
}
}
<label id="wow">
<input type="checkbox" name="checkbox" value="value">
<span>Text</span>
</label>
For those using React and Material UI - I've encountered this issue on one of my forms. event.preventDefault() is stopping the event from bubbling as described by the accepted answer.
<Button
onClick={(event) => {
event.preventDefault()
this.handleCardClick(planName)
}}
>
<FormControl component="fieldset">
<RadioGroup
row
value={selectedPlan}
>
<FormControlLabel
control={<Radio color="secondary" />}
label={label}
/>
</RadioGroup>
</FormControl>
</Button>
Use change to listen for events instead of click

jquery focusout == submit

How could I tell if the focusout event occured due to an enter press = form submit or just because of clicking away? The event data which goes to the console is of type "focusout" and has no relevant information
$(".clientrow[clientid="+clientid+"] td."+fieldname+"").bind("focusout", function(event){
console.log(event);
setTimeout(function() {
if (!event.delegateTarget.contains(document.activeElement)) {
$(".clientrow[clientid="+clientid+"] td."+fieldname+"").html(
$(".clientrow[clientid="+clientid+"] td."+fieldname+" input[type=text]").val()
);
}
}, 0);
});
Edit: As Oriol pointed in the comments, this will not work in Mozilla. If you are looking only for webkit browsers, you can try this approach. But as a generic solution, try binding an event on submit button and consecutively set a flag which identifies the element. Based on the element, you can detect whether it's an actual blur or not.
You can look out for relatedTarget property in the event.
Demo: http://jsfiddle.net/GCu2D/782/
JS:
$(document).ready(function () {
$("input").on("blur", function (e) {
console.log(e);
if (e.relatedTarget) {
console.log("Because of button");
} else {
console.log("Just a blur")
}
});
});
HTML:
<form>
<input type="text" />
<button type="button">Submit</button>
</form>
You'll have to replace the focusout with blur event. When the blur is due to a click on a button, the relatedTarget property will have button as value but in other cases it will be null.

Jquery - Differentiate between 'click' and 'focus' on same input when using both

I'm trying to trigger an event on an input if the input is clicked or if the input comes in to focus.
The issue i'm having is preventing the event from firing twice on the click as, obviously, clicking on the input also puts it in focus. I've put a very loose version of this on jfiddle to show you what I mean, code as below:
HTML:
<body>
<input type="textbox" name="tb1" class="input1"></input>
<label> box 1 </label>
<input type="textbox" name="tb2" class="input2"></input>
<label> box 2 </label>
</body>
JQuery
$(function () {
$('.input2').click(function() {
alert("click");
});
$('.input2').focus(function() {
alert("focus");
});
});
JSFiddle: http://jsfiddle.net/XALSn/2/
You'll see that when you tab to input2 you get one alert, but if you click you get two. Ideally for my scenario, it needs to be one alert and ignore the other. it also doesn't seem to actually focus.
Thanks in advance for any advice.
How about setting a flag on focus so we can fire on focus and ignore clicks but then listen for clicks on the focussed element too? Make sense? Take a look at the demo jsFiddle - If you focus or click on the unfocussed .index2 it triggers the focus event and ignores the click. Whilst in focus, clicking on it will trigger the click.
I have no idea why you would want this (I cant imagine anyone wanting to click on a focussed element for any reason (because the carat is already active in the field) but here you go:
$(function () {
$('.input2').on("click focus blur", function(e) {
e.stopPropagation();
if(e.type=="click"){
if($(this).data("justfocussed")){
$(this).data("justfocussed",false);
} else {
//I have been clicked on whilst in focus
console.log("click");
}
} else if(e.type=="focus"){
//I have been focussed on (either by clicking on whilst blurred or by tabbing to)
console.log("focus");
$(this).data("justfocussed",true);
} else {
//I no longer have focus
console.log("blur");
$(this).data("justfocussed",false);
}
});
});
http://jsfiddle.net/XALSn/12/
This probably won't be the best answer, but this is a way of doing it. I would suggest adding tab indexes to your inputs and firing the focus event when you blur from another input.
I've added that to this fiddle:
http://jsfiddle.net/XALSn/9/
$(function () {
$('.input2').click(function(e) {
alert("click");
e.preventDefault();
});
});
$('input').blur(function(){
$('input').focus(function() {
alert("focus");
});
});
You can use one thing I am using very often in JS
var doSomething = true;
$(function () {
$('.input2').click(function(e) {
if (doSomething) {
// do something :)
}
doSomething = false;
});
$('.input2').focus(function() {
if (doSomething) {
// do something :)
}
doSomething = false;
});
});
But You have to change value of doSomething on mouseout or foucs over etc. :)
$(function () {
var hasFocus = false;
$("body")
.off()
.on({
click : function()
{
if(!hasFocus)
{
hasFocus = true;
alert("click");
}
},
focus : function()
{
if(!hasFocus)
{
hasFocus = true;
alert("focus");
}
}
},".input2");
});
try setting a flag hasFocus and act accordingly
http://jsfiddle.net/AEVTQ/2/
just add e.preventDefault() on the click event
$(function () {
$('.input2').click(function(e) {
console.log("click");
e.preventDefault();
e.stopPropagation();
});
$('.input2').focus(function() {
console.log("focus");
});
});
If I understand your question right, the e.prevnetDefault() will prevent the browser from automatically focusing on click. Then you can do something different with the click than would with the focus

How do you propagate a click to child elements if the parent element has preventDefault?

UPDATE:
this doesn't work in the latest version of firefox (15.0.1):
http://jsfiddle.net/DerNalia/NdrNV/5/
clicking the checkbox navigates to google... but it shouldn't :(
it appears that adding e.stopPropagation() doesn't help / doesn't work.
playarea: http://jsfiddle.net/DerNalia/NdrNV/1/
What I'm trying to do:
When I click the checkbox that is next to (but actually is a child element of) the anchor, it should change states, and also change the state of the "other" checkbox.
But because the anchor has e.preventDefault() invoked, the checkbox never gets checked.
Here is my markup
Link Name <input class="home" type="checkbox"/>
<br />
Sync'd checkbox: <input class="other" type="checkbox" />​
Here is some the troubled jquery
$(function() {
$("input.home").click(function() {
$("input.other").click();
});
$("a").click(function(e) {
e.preventDefault();
// prevent default so we can do some ajaxy things instead of follow the href
});
})​
So, how do I change the jQuery click action on the anchor tag such that clicks propagate to child elements (but I can still do ajaxy things without the browser following the href of the anchor tag)?
Is there a way to do this without changing the markup? (the way it is now makes semantic sense for my web application)
It doesn't work because event.preventDefault would cancel the event.
Using e.preventDefault on click on the checkbox which is wrapped inside <a> would not let you change the checkbox state.
A workaround I could think of is to set the checkbox state in a different context so that the e.preventDefault code is ineffective.
DEMO: http://jsfiddle.net/NdrNV/10/
$(function() {
$("input.home").click(function() {
$("input.other").click();
});
$("a").click(function(e) {
e.preventDefault();
var setCheckbox = function() {
var checkbox = $(e.target)[0];
checkbox.checked = checkbox.checked?false:true;
}
if ($(e.target).is(':checkbox')) {
setTimeout(setCheckbox, 0);
}
});
})
Note: This is a workaround.
You can put condition e.target.tagName like this,
if(e.target.tagName == 'A')
e.preventDefault();
Live Demo
$(function() {
$("input.home").click(function() {
$("input.other").click();
});
$("a").click(function(e) {
if(e.target.tagName == 'A')
e.preventDefault();
// prevent default so we can do some ajaxy things instead of follow the href
});
})​
$(function() {
$("input.home").click(function() {
if($(this).attr('checked') == 'checked')
$(this).removeAttr('checked');
else
$(this).attr('checked', 'checked');
$("input.other").click();
});
$("a").click(function(e) {
e.preventDefault();
// prevent default so we can do some ajaxy things instead of follow the href
var target = e.target; // object that triggers the event
$(target).children().trigger('click');
});
});

Categories

Resources