How to prevent BLUR event from firing multiple times? - javascript

I have certain text input fields where if users change a value and then blur away from that text field, the js will fire an ajax request to update that value in the db. The problem is that I wrote a test to get such an event to fire and I notice that the inner 'blur' event usually fires between two and five times after I tab out of the input field:
$('input[type=text]').on('input propertychange paste', function() {
$(this).on('blur', function () {
console.log('blur');
});
});
Even if I turn off the blur event handler right after catching it, it still fires two or three times. How do I get this to happen only once?

Just keep track of a hasFired boolean:
var hasFired = false;
$('input[type=text]').on('input propertychange paste', function() {
$(this).on('blur', function () {
if(!hasFired){
hasFired = true;
console.log('blur');
}
});
});
Actually, the real problem here is that you're binding the blur event multiple times. You can use a boolean like above to prevent that:
var isBound = false;
$('input[type=text]').on('input propertychange paste', function() {
if(!isBound){
isBound = true;
$(this).on('blur', function () {
console.log('blur');
});
}
});

Another solution would be is to create a class for those elements that already bound by that event.
$('input[type=text]').on('input propertychange paste', function() {
if(!$(this).hasClass("bound")) {
$(this).on('blur', function () {
$(this).addClass("bound");
console.log('blur');
});
}
});

Related

jquery onblur not firing

I am trying to get an onblur/onfocus combination working for a pair of text boxes which I am selecting via class in jquery. I am not getting any errors in debug, but the blur function never seems to be called. When debugging my breakpoint in the blur function is not hit.
$(document).ready(function () {
var row = $(this).closest('tr');
$('.editClass').click(function () {
var editBoxes = $(row).find('.editClass');
var focus = 0;
$(editBoxes).focus(function () { focus++ });
$(editBoxes).blur(function () {
focus--;
setTimeout(function () {
if (!focus) {
alert('LOST FOCUS'); // both lost focus
}
}, 50);
});
});
});
Pretty sure the problem here was that the editBoxes were dynamically added to the page. This was not apparent in my question. Since they were dyncamically added I need to use
$(document).on('blur', '.editBoxes', function (){
...
}
The last two lines of your code example should be this
});
});
This is needed for closing the ready and click function call.
Another possible problem is that you wrap the focus and blur listeners in a click handlers. Why did you do this?

prevent jQuery post request executed twice by double click

I've searched for equal questions, but found not a single one for my specific case.
I have an element
<span id="myButton">Click</span>
and a jQuery post-request bound to it
$(document).ready( function()
{
$(document).on( 'click', '#myButton', function(e)
{
$.post( "RESPONDING_WEBPAGE_HERE.php" ).done( function( result )
{
console.log( result );
});
});
});
Now, for every time you click the button, it makes a post-request. Makes sense. What I want is a good solution for only executing the post-request, if the result function (.done()) is executed.
For sure, I know to handle that with a variable like var isAjaxRequest = false; setting it to true, and back to false in the resulting function, but maybe there is a better (jQuery build-in) way of doing it.
Here is my solution by now. I would be really great if there are better ones.
var isAjaxRequest = false;
$(document).ready( function()
{
$(document).on( 'click', '#myButton', function(e)
{
if( !isAjaxRequest )
{
isAjaxRequest = true;
$.post( "RESPONDING_WEBPAGE_HERE.php" ).done( function( result )
{
isAjaxRequest = false;
console.log( result );
});
}
});
});
Thank you =)
I commonly set the button to disabled when it is clicked and then remove the disabled attribute on the callbacks for the POST request.
$(document).on('click', '#button', function () {
$('#button').attr('disabled', true);
$.post('something').done(function () {
$('#button').removeAttr('disabled');
}).fail(function () {
$('#button').removeAttr('disabled');
});
});
This will prevent the button from being clicked again once it has already been clicked.
As per the comments; If you want this behaviour on a span element or others which don't allow the disabled attribute, you could set a class when clicked.
$(document).on('click', 'span#button:not(.disabled)', function () {
$(this).addClass('disabled');
$.post('something').done(function () {
$(this).removeClass('disabled');
}).fail(function () {
$(this).removeClass('disabled');
});
});
The above code will make sure the element can only be clicked if it doesn't have the disabled class. This will also work for the button elements so there is no need to duplicate code for both methods.
I like to use .one() to attach the event handler and re-attach the event after the ajax call is complete. This will handle all cases even when your target doesn't support disabling:
//define handler function
var myButtonHandler = function(e) {
$.post("RESPONDING_WEBPAGE_HERE.php").done(function() {
attachButtonHandler("#mybutton"); //re-attach the click event after AJAX complete
});
}
//attach an event handler that's only good for one click
function attachButtonHandler(selector) {
$(document).one('click', selector, myButtonHandler);
}
//on doc ready, attach the event handler for the first time
$(function() {
attachButtonHandler("#mybutton");
});

Disabling and enabling click event on image...jquery

what would be the best way to enable and then re-enable and image click with jquery?
I can diasble the click event easy enough
$(document).on("click", "#rightPager", function () {
if (condition) {
$(this).click(false);
}
});
how would I go about in 'enabling' the click event again based on a certain condition?.
I would want to enable the button again for example
$(document).on("click", "#leftPager", function () {
$("#rightPager").click(true);
});
In order to rebind you would need to use the original .on("click") event again.
Write a function to bind an event to your image:
function bindImage() {
$(img).on("click", function() {
// Your bind event goes here
});
}
Then write a conditional to unbind the event on the image if your condition returns true, then if its false, rebind the event to the image as normal.
if (condition) {
$(img).unbind();
} else {
bindImage();
}
Alternatively, you could complete this within a single function such as:
$(document).on("click", "#rightPager", function () {
if (condition) {
// terminate the function
return false;
} else {
// put your function here to run as normal
}
});
Try to use jQuery off method.
JSFiddle
$(document).off('click', '#rightPager');
Full code:
var condition = true;
$(document).on("click", "#rightPager", function () {
if(condition){
alert('Click was disabled');
$(document).off('click', '#rightPager');
}
});
you disable the default event by:
$(document).click(function(e) {
e.preventDefault();
condition ? doSomething() : doSomethingElse();
});​
so basically is not that you enable then disable, you prevent the default action, check for your condition and they execute appropriate function

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

Do not fire one event if already fired another

I have a code like this:
$('#foo').on('click', function(e) {
//do something
});
$('form input').on('change', function(e) {
//do some other things
));
First and second events do actually the same things with the same input field, but in different way. The problem is, that when I click the #foo element - form change element fires as well. I need form change to fire always when the content of input is changing, but not when #foo element is clicked.
That's the question )). How to do this?
Here is the code on jsfiddle: http://jsfiddle.net/QhXyj/1/
What happens is that onChange fires when the focus leaves the #input. In your case, this coincides with clicking on the button. Try pressing Tab, THEN clicking on the button.
To handle this particular case, one solution is to delay the call to the change event enough check if the button got clicked in the meantime. In practice 100 milisecond worked. Here's the code:
$().ready(function() {
var stopTheChangeBecauseTheButtonWasClicked = false;
$('#button').on('click', function(e) {
stopTheChangeBecauseTheButtonWasClicked = true;
$('#wtf').html("I don't need to change #input in this case");
});
$('#input').on('change', function(e) {
var self = this;
setTimeout(function doTheChange() {
if (!stopTheChangeBecauseTheButtonWasClicked) {
$(self).val($(self).val() + ' - changed!');
} else {
stopTheChangeBecauseTheButtonWasClicked = false;
}
}, 100);
});
});
And the fiddle - http://jsfiddle.net/dandv/QhXyj/11/
It's only natural that a change event on a blurred element fires before the clicked element is focused. If you don't want to use a timeout ("do something X ms after the input was changed unless in between a button was clicked", as proposed by Dan) - and timeouts are ugly - you only could go doing those actions twice. After the input is changed, save its state and do something. If then - somewhen later - the button is clicked, retrieve the saved state and do the something similar. I guess this is what you actually wanted for your UI behaviour, not all users are that fast. If one leaves the input (e.g. by pressing Tab), and then later activates the button "independently", do you really want to execute both actions?
var inputval = null, changedval = null;
$('form input').on('change', function(e) {
inputval = this.value;
// do some things with it and save them to
changedval = …
// you might use the value property of the input itself
));
$('#foo').on('click', function(e) {
// do something with inputval
});
$('form …').on('any other action') {
// you might want to invalidate the cache:
inputval = changedval;
// so that from now on a click operates with the new value
});
$(function() {
$('#button').on('click', function() {
//use text() not html() here
$('#wtf').text("I don't need to change #input in this case");
});
//fire on blur, that is when user types and presses tab
$('#input').on('blur', function() {
alert("clicked"); //this doesn't fire when you click button
$(this).val($(this).val()+' - changed!');
});
});​
Here's the Fiddle
$('form input').on('change', function(e) {
// don't do the thing if the input is #foo
if ( $(this).attrib('id') == 'foo' ) return;
//do some other things
));
UPDATE
How about this:
$().ready(function() {
$('#button').on('click', function(e) {
$('#wtf').html("I don't need to change #input in this case");
});
$('#input').on('change', function(e) {
// determine id #input is in focus
if ( ! $(this).is(":focus") ) return;
$(this).val($(this).val()+' - changed!');
});
});

Categories

Resources