I am making an incremental game in javascript, so I am replacing some links in the page all the time, this links are showing a really weird behavior. I am attaching the click events with .on(, and some times the click event is fired and some times not, is very random.
Here is a clear example of the beheavior. I can imagine that is something related with the time interval, because if I set the interval in 1000 millis, the event always is fired. Of course that I can make some changed in the code in order to don't replace the link and only update it, but I want to know if this is fixable first.
HTML:
<div id="container"><a id="link" href="#">test</a></div>
JS:
$(document).ready(function(){
$("#container").on("click","#link",function(){
alert("clicked");
});
setInterval(function(){
var newA = $("#link").clone();
$("#link").remove();
$("#container").append(newA);
},100);});
Example in jsFiddle:
http://jsfiddle.net/MtR6b/1/
Thanks!!
Your setInterval code is very fast 100 ms that's why when then event is about to trigger element is replaced with new one so click event is not triggered.
Try clicking on the link many times you will see the alert.
DEMO with 1000ms=1s setInterval
Related
I'm having problems getting standard javascript timers to clear on mobile devices (Android and iOS, phone and tablet).
My page contains 2 buttons, a play/pause toggle and a stop button (both FontAwesome icons), the simple HTML for which is:
<span class="fa fa-pause control-button" id="pause-button"></span>
<span class="fa fa-stop control-button" id="stop-button"></span>
The interval is initiated with the following function:
var interval = function() {
$('.control-button').fadeIn(300);
//initiate the interval
infiniteInterval = window.setInterval(Tiles.infiniteTick, speed);
};
Where speed is defined in an earlier function (default is 300). infiniteTick is a very simple function which is working fine. I haven't explained it here as it would require an explanation of the whole program but I can provide code if required.
The play and pause toggles are as follows:
$('body').on('click touchstart', '#pause-button', function() {
if ($(this).hasClass('fa-pause')) {
window.clearInterval(infiniteInterval);
$(this).removeClass('fa-pause');
$(this).addClass('fa-play');
} else {
infiniteInterval = window.setInterval(Tiles.infiniteTick, speed);
$(this).removeClass('fa-play');
$(this).addClass('fa-pause');
}
});
Finally, the interval is terminated with this (some purely aesthetic extras removed for simplicity)
$('body').on('click touchstart', '#stop-button', function() {
window.clearInterval(infiniteInterval);
$('.control-button').fadeOut(300);
});
I initially thought from researching this that it was due to click events not being properly registered, but as you can see I have added touchstart to all the click events and that has made no difference. It's working absolutely fine on all desktop browsers.
Any help is greatly appreciated, and I'd be happy to answer any further questions.
Thanks,
Ben
I've managed to fix the problem, which it turns out was twofold.
Firstly, the click event was firing twice. This was fixed using this SO question: jquery mobile click event fires twice
Secondly, I wasn't properly clearing the intervals.
Edited with #MjrKusanagi's comments
A simple call to clearInterval() before every setInterval() call has fixed the problem, making sure that the interval was always reset before starting again.
Original sketchy workaround:
I've called
infiniteInterval = null;
after every clearInterval() call, as well as wrapping the setInterval() calls with
if (infiniteInterval === null)
Thanks to everyone who commented and hopefully this will help someone sometime :)
First, your click event is firing twice because of this sentence:
$('body').on('click touchstart', '#pause-button', function() { ...
It listens to two events click and touchstart, thus it will be triggered twice, once on click event and once on touchstart event. This is also why your code works well on pc because there's no touchstart event in pc browsers.
So every time you touch that button, things happened like this:
1st event triggered
interval set, handle id is 1 (for example)
infiniteInterval = 1
2nd event triggered
another interval set, handle id is 2
infiniteInterval = 2
And now there's two timing cycles running instead of one, and you only have track of the second one. When you invoke clearInterval, only the handle id = 2 interval is cleared, and 1 is still running.
So the solution is:
Fix the twice-triggered events problem, by only listen to click. (try fastclick or zepto or other lib to deal with the click latency on mobile devices)
As your own answer said, set infiniteInterval to null, and if it is not null do not ever start another interval. (I think it is more elegant than "always clear before setting" works, as infiniteInterval works as a flag of running interval)
Hope these could solve your problem.
I have a textarea with this event bind :
on focus :
display a link that will popup a larger version of text area.
on blur :
remove the link.
but "click" event on the link never triggered because it's already removed when onblur trigerred.
$("#text-area-new-message").focus(function(){
$("#text-area-new-message").after('<a id="enlarge-text-area" href="#">enlarge text area</a>');
$("#enlarge-text-area").click(function(){
alert('test');
});
});
$("#text-area-new-message").blur(function(){
$("#enlarge-text-area").remove();
});
here is the jsfiddle
how is the better way to do that?
When the user leaves the textbox, you could delay the removal of the link by, say, a few seconds:
$("#enlarge-text-area").delay(3000).remove();
Or more. Whatever seems an appropriate amount of time for a user to click the link if that was their intention. This could get even more 'clever', by, for instance, fading out slowly and stopping the animation and subsequent removal only if it captures the mouse (by way of hovering on the link.)
one approach is to use jquery on function to attach event handlers to all 'future'
'#enlarge-text-area' elements :
$('#myParentDiv').on('click', '#enlarge-text-area', function(){});
other approach is to hide rather than remove the link.
I know the usage of mouseenter and mouseleave. Below is my code sample:
$('div').mouseenter(function(e){
...
}).mouseleave( function(e){
...
//let say it will take 5 second.
});
But my question is, is it possible that two handlers are triggered at the same time if I move the mouse quickly? I mean mouseleave doesn't finish , meanwhile mouseenter is triggered because the mouse just moved in.
Updated
In my example, what I mean is if the mouse move in 3 seconds after mouseleave has been triggered, will it also trigger mouseenter? If it does, does it mean the same DOM element trigger mouseenter and leave at the same time? Thanks.
It is not possible to trigger both event at the same time. As javasript is not multi-threaded. If you want to put some delay between execution you can use setTimeout
no ....there is no possibbilities of calling both the function at same time.... and you can't be quick enough for that
I have some issues with my js code. I want to animate a simple click function so that a div, shows the div below but animates back after say 5 seconds. I think I got the right setup with fadeToggle and delay but I just don't get it how to set up "over-clicking" prevention. I mean when people mess with the click-object.
My first attempt was stop(true,true). Although it seems that it works as expected (aborting further function execution) it unfortunately shows the underlying div after 5 seconds although it should show the upper one (picture).
Here is the js and the fiddle:
$(function() {
$("#boxes li").on("click", function(){
$(this).find(".front,.back").stop(true, true).fadeToggle(800).delay(5000).fadeToggle(800);
});
});
but also a js fiddle link to see what I mean:
http://jsfiddle.net/sfiddle/bqbPL/
Regards,
PS: try first to click once to see what effect I want to accomplish and then click 2 times to see how after 5 seconds it will show the text div.
I have modified it a bit,
but still require some work on it, you may use some flag variable with click,
Please see the updated 'fiddle`, it handles the process but stores the next click that occurs after it fade back.
Update: to avoid double clicking
Creating a flag is, you will create a Boolean variable, that will be true/false. (or int variable with 0 or 1),
Like:
var flg=true;
Now, this variable called flag, flag is initiated with False/True value(as per requirement) then we will modify flag after the event occur(the event we want to watch out, here click of button) once event occurs we will change the flag.
In the second you will add flag to condition. if( condition == true && flag == true) {....} so, if flag is changed to false after event/click the event in if will not occur again.
I hope this will help..
today I discovered something that was quite confusing for me.
I just tried to hide s.th via jquery... first I tried to use this
$(".specificdiv li:nth-child(3)").click(function(){
$(".anotherdiv").hide();
})
....but it does not work.
After a time I tried it this way:
$(".specificdiv li:nth-child(3)").mousedown(function(){
$(".anotherdiv").hide();
})
Can anyone explain me why mousedown works instead of click?
Would be great to find out
EDIT
edited the anotherdiv.
Possible reasons:
The event mousedown executes before click, so first come first serve.
The element might have already a click event, which prevents this from happening, say that function executes first and it has a return false statement in it.
Now since you are using mousedown, which is not assigned for this element, it doesn't have any conflicts. This may be a reason, because you didn't post the full code. Feel free to correct. :)
On a smaller note, you have $(".anotherdiv").hide(); in the first code and $(".another").hide(); in the second code, missing the div in the class. Is that a problem?
Actually the mousedown event is triggered when you push down the button, even you don't let the button up.
The click is like the mouseup, when you let the button go up.
In your code you have: ".anotherdiv" and ".another" could it be your error?