disable click event handler for a duration of time - javascript

I've already looked at similar questions but the answers provided involve buttons and not div elements. When I click the div element with id click, the click event handler is disabled by unbind() and sets a timer for 2 seconds. After 2 seconds, the click event handler should be enabled again by bind(). The problem is that the click event handler doesn't seem to get "rebound". I am appending text to another div element to check if the click event handler is active.
Here is my JSFiddle.

Another approach to the whole problem is not to bother with unbinding and rebinding and just use a "disabled" flag:
$(document).ready(function(){
var clickDisabled = false;
$('#click').click(function(){
if (clickDisabled)
return;
// do your real click processing here
clickDisabled = true;
setTimeout(function(){clickDisabled = false;}, 2000);
});
});

Try this:
$(document).ready(function(){
$('#click').click(function(){
$('#click').unbind('click');
$('#status').append("unbound ");
setTimeout(
function(){
$('#click').bind('click',function(){
});
$('#status').append("bound ");
},
2000
);
});
});
You misspelled setTimeout and your "bound" message was being appended only on click.

I answer your question but just don't kill yourself :)) Just kidding... Your code is fine just a typo: setTimeOut should be setTimeout (the O should be o)

When you are rebinding the function the second time you are binding just a subset of all your code - all it does it output bound to the status, but it doesn't contain any of the code for doing a timeout a second time.
Also, you will like the .one() function.
I've fixed up your code here: https://jsfiddle.net/eQUne/6/
function bindClick() {
$('#click').one('click', function() {
$('#status').append("bound ");
setTimeout(bindClick, 2000);
});
}
$(document).ready(function(){
bindClick();
});

If I got what you were asking correctly, this should work:
<div id="click" >time out</div>
<div id="status"></div>
$(document).ready(function() {
$('#click').click(unbindme);
$('#status').html('bound');
function unbindme()
{
$('#click').unbind('click');
$('#status').html('unbound');
setTimeout(function(){
alert('here');
$('#status').html('bound');
$('#click').click(unbindme);
}, 2000);
}
}
Check it out here: https://jsfiddle.net/eQUne/

Related

jQuery callback function accumulating

I wrote some code for a custom confirm box that calls a function when confirm button (yes-button) is pressed and passes another function as a parameter and I bind it to 2 different button clicks with different functions as a parameter. For example:
$('#button1').click(function() {
callFunction(function() { alert("test"); });
});
$('#button2').click(function() {
callFunction(function() { alert("test2"); });
});
function callFunction(callback) {
//code to display custom confirm box
console.log(callback);
$('.confirm-box .yes-button').click(function() {
callback();
});
}
Everything happens as expected, confirm box appears and on confirm button click I get a callback function executed and it alerts "test" (or "test2" depending on which button called the confirm box). The problem arises when I click button1 that sends a function that alerts "test", then instead of confirming I cancel that (nothing happens as expected), and then click button2 that passes alert("test2") as a callback function. Now once I press the yes-button instead of alerting just "test2", I get both "test2" and "test" alerts even though that console.log I wrote logs just the function that alerts "test2" at the time of that button2 click. It seems like these callback functions get stacked somewhere, but I don't understand where and why.
The .click() function can add more than one handler to an element, and I think that's what's happening here. Try this:
// ...
$('.confirm-box .yes-button').unbind('click').click(function() {
callback();
});
This removes any previous click handler before applying the new one.
When you execute the code:
$('.confirm-box .yes-button').click(function() {
callback();
});
you are binding an event handler to the .yes-button element. If you run that code twice, it will have two events bound to it. And so on.
One solution is to use .one instead, so that the event handler will be removed after the first time it is fired:
$('.confirm-box .yes-button').one("click", function() {
callback();
});
This of course has issues if there are two confirm boxes open simultaneously or if there are two .yes-button elements, but for a simple use case it works fine.
What is happening is that each time a button is clicked the callFunction method is executing. It runs through that code block and applies an event listener to the $('.confirm-box .yes-button') button. So clicking your button N times will apply the click listener N times as well. One solution is to store the function in a variable.
Not sure what the end goal is, but this is one solution.
Another solution would be to remove buttons event listeners each time.
var functionToCallOnYes = function() {};
$('#button1').click(function() {
functionToCallOnYes = function() {
alert("test");
};
});
$('#button2').click(function() {
functionToCallOnYes = function() {
alert("test2");
};
});
$('.confirm-box .yes-button').click(function() {
console.log(functionToCallOnYes);
functionToCallOnYes();
});
You can do it by setting an identity by classes,
var button = $('.confirm-box .yes-button');
$('#button1').click(function() {
button.removeClass("b").addClass("a");
});
$('#button2').click(function() {
button.removeClass("a").addClass("b");
});
button.click(function() {
if($(this).hasClass("a")){
callBackForButton1();
} else {
callBackForButton2();
}
});
It is a bad practice to stack up the event handler for a single element.
Yes, extra callbacks are getting stacked up. In $('button1').click(f), the function f will be called with no parameters every time button1 is clicked. In this case, f is callFunction-- a function that itself attaches a new handler to any .confirm-box .yes-button element each time it's invoked. So on the Nth click, you should have N-1 alerts.
To make things like this easier, you can refer to functions by name in JavaScript. So if you had function test() { console.log("test"); };, you could write $(".confirm-box").click(test) just once and every click on a .confirm-box from then on would print test to the console.
Usually if you have callbacks whose sole purpose is to call a callback, you can just remove that callback.

setTimeout not working only for the first time of the event causing it

In code below, i want to set var hasFocus=False; after 500ms on blur of mentioned <textarea> and <input>. This code immediately turns hasFocus=False without waiting for 500ms for the first time. Afterwards, it works as expected.
I'm unable to understand why it is not running as expected for the first time only!
$(function(){
var hasFocus=false;
$("textarea[name='question1'], input[name^=q1_option]").blur(function(event){
setTimeout(function(){
hasFocus=false;
},500);
}).focus(function(){
hasFocus=true;
});
$(document).on('click',function(e){
console.log("focus :" +hasFocus);
if(hasFocus)
{
alert("Working!!"); //Now this does not come up for the first time!
}
})
});
That's because your console.log executes before the timed out blur event is triggered and thus console shows the previous value. Move the console.log("focus :" +hasFocus); inside your blur and focus functions to see that everything works properly.
Demo - Fiddle
Well after a lot of headbanging, i came up with this. Its not my exact code but a demo and it worked exactly the way i wanted:
$(function(){
var hasFocus=false;
$("textarea[name='question1'], input[name^=q1_option]").blur(function(event){
setTimeout(function(){
hasFocus=false;
},500);
}).focus(function(){
setTimeout(function(){ //just initiated focus event after blur event
hasFocus=true; //just initiated focus event after blur event
},510); //just initiated focus event after blur event
});
$(document).on('click',function(e){
console.log("focus :" +hasFocus);
if(hasFocus)
{
alert("Working!!"); //Now this does not come up for the first time!
}
})
});
setTimeout(function(){
hasFocus=false;
},500, function() {hasFocus=true;});
Just add this: function() {hasFocus=true;} to the end of setTimeout function. Or create a function that sets hasFocus variable to true and call this function when the setTimeout function is completed.
You can read more about setTimeout function there: http://www.sitepoint.com/jquery-settimeout-function-examples/
EDIT: Oh, and if this method wouldn't work, then the Nikolay is right! :)

How to get JQuery.trigger('click'); to initiate a mouse click

I'm having a hard time understand how to simulate a mouse click using JQuery. Can someone please inform me as to what i'm doing wrong.
HTML:
<a id="bar" href="http://stackoverflow.com" target="_blank">Don't click me!</a>
<span id="foo">Click me!</span>
jQuery:
jQuery('#foo').on('click', function(){
jQuery('#bar').trigger('click');
});
Demo: FIDDLE
when I click on button #foo I want to simulate a click on #bar however when I attempt this, nothing happens. I also tried jQuery(document).ready(function(){...}) but without success.
You need to use jQuery('#bar')[0].click(); to simulate a mouse click on the actual DOM element (not the jQuery object), instead of using the .trigger() jQuery method.
Note: DOM Level 2 .click() doesn't work on some elements in Safari. You will need to use a workaround.
http://api.jquery.com/click/
You just need to put a small timeout event before doing .click()
like this :
setTimeout(function(){ $('#btn').click()}, 100);
This is JQuery behavior. I'm not sure why it works this way, it only triggers the onClick function on the link.
Try:
jQuery(document).ready(function() {
jQuery('#foo').on('click', function() {
jQuery('#bar')[0].click();
});
});
See my demo: http://jsfiddle.net/8AVau/1/
jQuery(document).ready(function(){
jQuery('#foo').on('click', function(){
jQuery('#bar').simulateClick('click');
});
});
jQuery.fn.simulateClick = function() {
return this.each(function() {
if('createEvent' in document) {
var doc = this.ownerDocument,
evt = doc.createEvent('MouseEvents');
evt.initMouseEvent('click', true, true, doc.defaultView, 1, 0, 0, 0, 0, false, false, false, false, 0, null);
this.dispatchEvent(evt);
} else {
this.click(); // IE Boss!
}
});
}
May be useful:
The code that calls the Trigger should go after the event is called.
For example, I have some code that I want to be executed when #expense_tickets value is changed, and also, when page is reload
$(function() {
$("#expense_tickets").change(function() {
// code that I want to be executed when #expense_tickets value is changed, and also, when page is reload
});
// now we trigger the change event
$("#expense_tickets").trigger("change");
})
jQuery's .trigger('click'); will only cause an event to trigger on this event, it will not trigger the default browser action as well.
You can simulate the same functionality with the following JavaScript:
jQuery('#foo').on('click', function(){
var bar = jQuery('#bar');
var href = bar.attr('href');
if(bar.attr("target") === "_blank")
{
window.open(href);
}else{
window.location = href;
}
});
Try this that works for me:
$('#bar').mousedown();
Technically not an answer to this, but a good use of the accepted answer (https://stackoverflow.com/a/20928975/82028) to create next and prev buttons for the tabs on jQuery ACF fields:
$('.next').click(function () {
$('#primary li.active').next().find('.acf-tab-button')[0].click();
});
$('.prev').click(function () {
$('#primary li.active').prev().find('.acf-tab-button')[0].click();
});
I have tried top two answers, it doesn't worked for me until I removed "display:none" from my file input elements.
Then I reverted back to .trigger() it also worked at safari for windows.
So conclusion, Don't use display:none; to hide your file input , you may use opacity:0 instead.
Just use this:
$(function() {
$('#watchButton').trigger('click');
});
You can't simulate a click event with javascript.
jQuery .trigger() function only fires an event named "click" on the element, which you can capture with .on() jQuery method.

jQuery .click() only working once

I am trying to make some text that changes when you click it, but changes back if you click it again.
It works fine, once. But if i try it a second time, nothing happens.
My HTML:
<div id="text">
<p>TEXT1</p>
</div>
JavaScript/jQuery:
$(document).ready(function(){
$("#text").click(function(){
$(this).html("<p>TEXT2</p>").click(function(){
$(this).html("<p>TEXT1</p>");
});
return false;
});
});
Example:
http://mrkireko.github.io/jQueryExample/
I'd suggest instead:
$('#text p').click(function(){
$(this).text(function(i,t){
return $.trim(t) === 'text1' ? 'text2' : 'text1';
});
});
JS Fiddle demo.
References:
click().
jQuery.trim().
text().
It's because after the first click, you now have two handlers assigned,
The first one still puts the TEXT2 in place, but the second one changes it back.
One correct solution is to use the handler version of .toggle():
$(document).ready(function(){
$("#text").toggle(function(){
$(this).html("<p>TEXT2</p>");
return false;
}, function(){
$(this).html("<p>TEXT1</p>");
return false;
});
});
As #KevinB noted, this version of .toggle() is deprecated. To do your own toggle, you can do this:
$(document).ready(function() {
$("#text").click(function(i){
return function() {
$(this).html(++i % 2 ? "<p>TEXT2</p>" : "<p>TEXT1</p>");
return false;
};
}(0));
});
DEMO: http://jsfiddle.net/NkGZj/
You are binding multiple click handlers to the same element, and they are all executing every time you click. Since the handler to change the text to TEXT1 executes last, that's what you end up with.
See the console.log() output here:
http://jsfiddle.net/tcMx5/
Binding event handlers in event handlers is almost never the right thing to do. Instead, have one handler that checks the current state and toggles the value.
Several answers here, some will work well. Here is another option, using class:
<div id="text" class="state1">
<p>TEXT1</p>
</div>
$(document).ready(function(){
$("#text").click(function(){
var $this = $(this);
if ($this.hasClass('state1')) {
$this.html('<p>TEXT2</p>');
}
else {
$this.html('<p>TEXT1</p>');
}
$this.toggleClass('state1');
});
});
I would lean more towards this solution because it is not dependent on what is actually contained within the element. Unless, of course, you know that it will never change and you can reliably target the string.
You can do something like this:
$( "#text" ).toggle(function() {
this.html("<p>text 2</p>");
}, function() {
this.html("<p>text 1</p>");
});

How to check if there is already a click/event associated to an element

lets say I have
function trigger(){
$('a.pep').each(function(){
$('a.pep').click(function(){
console.log($(this).val());
});
});
}
function push(){
$('body').append('<a class="pep">hey mate i have no trigger yet</a>');
trigger(); //now i do but the others have duplicated trigger
}
$(document).ready(function(){
$('a.push').click(function(){
push();
});
});
So it seems that the click event is being applied twice/+ because the console.log is lauched more than once by click
How can i prevent this?
The problem is that you call $('a.pep').click() lots of times. (In fact, you bind as many click handlers as there are matching elements to each element. And then you do it again every time one of them is clicked.)
You should lever the DOM event bubbling model to handle this. jQuery helps you with the on method:
$(document.body).on('click', 'a.pep', function() {
console.log('element clicked');
$(document.body).append('<a class="pep">Click handlers handled automatically</a>');
});
See a working jsFiddle.
Note that I have removed the val call, because a elements can't have a value... Note also that the on method is introduced in jQuery 1.7; before that, use delegate:
$(document.body).delegate('a.pep', 'click', function() {
Small change to your trigger function is all you need. Just unbind the click event before binding to ensure that it is never added more than once. Also, you don't need to use each when binding events, it will add the event to each item automatically.
function trigger(){
$('a.pep').unbind('click').click(function() {
console.log($(this).val());
});
}
You can check using data('events') on any element if the required event is attached or not. For example to check if click event is attached or not try this.
if(!$('a.pep').data('events').click){
$('a.pep').click(function(){
console.log($(this).val());
});
}
you should use jQuery live here because you add DOM elements dynamicly and you want them to have the same click behaviour
function push(){
$('body').append('<a class="pep">hey mate i have no trigger yet</a>');
}
$(document).ready(function(){
$('a.push').click(function(){
push();
});
$('a.pep').live('click', function(){
console.log($(this).val());
});
});
Try:
if($('a.pep').data('events').click) {
//do something
}
i think if you use live() event you dont need to make function
$('a.pep').live('click', function(){
console.log($(this).val());
});

Categories