Dont' allow to click button/icon more than once - javascript

I am creating a whack-a-mole style game where a sum is given and numbers animate from the bottom of the container to the top. The aim of the game is to click the correct answer to the sum and collect as many correct answers as possible.
My problem is that the user can click the numbers and other icons multiple times, causing it to crash. Is there a way to overcome this?
I have tried this jQuery one function
$(".character").one("click", function() {
});
But the icons re-appear so I need them to be clickable again.
I have also tried to set a time out but cannot seem to get it working. Can someone point e in the right direction.
setTimeout(function() {
$(".character").one("click", function() {
});
}, 3000);
Fiddle: http://jsfiddle.net/GvNB8/

Your main problem is that you are not interacting with the characters when re-showing them. In that case the only way to prevent the user from clicking is building in a method to prevent clicking twice in quick succession with a timeout.
That method would look something like this:
function clickThrottled(fn) {
var click = true;
return function () {
if(click) {
click = false;
fn.apply(this, arguments);
setTimeout(function () { click = true; }, 1000);
}
};
}
You then use the function like this:
$('.character').click(clickThrottled(function () {
// do your one time magic.
}));
What I am using here is JavaScript closures. The function you pass to the click event handler will only call the underlying function once, then ignore all calls for 1 second and then re-enable itself.
I'd still suggest you go with a normal method of just re-enabling the elements when they are redrawn onto the screen - but the above also works..

Why not just add an information indicating that this item has been clicked :
$(".character").click(function(){
if(!$(this).data("hasBeenClicked")) {
$(this).data("hasBeenClicked", true);
// the rest of your logic ...
}
});

Related

JavaScript Function, Click Button and Resizing (Reverses Button Function)

My code has a button that changes some CSS via adding and removing classes. I have the JS working fine to do this. The first click adds the class, clicking again removes it and so on around it goes, nothing unusual there.
However, I've also incorporated a function that removes the classes if the browser window is resized at all. My issue is, if I then go back to press the button again after resizing the window, it thinks it should be doing the second click (almost reversing the function) and removes the classes (even though they've already been removed by the resizing), whereas I need the button function to almost reset and have it think the button hasn't been clicked yet after the resizing, so the process can be started from the beginning.
I really hope this makes sense, because its been driving me around the bend, and nothing I've tried will make it work how I would like it to.
Thank you for any help!
Heres the code:
JS/jQuery
{
/* Button Function to add and remove classes. */
$("#nav-icon").click(function () {
var clicks = $(this).data("clicks");
if (!clicks) {
$(".logo-container").addClass("border-change-image");
$(".container-fluid").addClass("border-change-header");
} else {
$(".logo-container").removeClass("border-change-image");
$(".container-fluid").removeClass("border-change-header");
}
$(this).data("clicks", !clicks);
});
/* Window Resizing Function */
$(window).on("resize", function () {
var size = $(this).on("resize");
if (size) {
$(".logo-container").removeClass("border-change-image");
$(".container-fluid").removeClass("border-change-header");
} else {
}
});
}
Removed the variable storing the data and just "asked" if one of the div's had one of the classes then add or remove, based on that. Works like a charm.
JS
$("#nav-icon").click(function () {
if ($(".logo-container").hasClass("border-change-image")) {
$(".logo-container").removeClass("border-change-image");
$(".container-fluid").removeClass("border-change-header");
} else {
$(".logo-container").addClass("border-change-image");
$(".container-fluid").addClass("border-change-header");
}
});

jquery delay doesn't count as animation

I'm trying to do an animation after button click using promises. But no matter what I do, it will still let me keep clicking.
I'm showing some Bootstrap form validator classes and then removing them. Like this:
messageEffect : function(container) {
return container.fadeIn(100).delay(1000).fadeOut();
},
$.when(this.messageEffect($container)).done(function() {
$container.empty();
$icon.remove();
$group.removeClass('has-feedback has-' + alertType);
});
I'm calling this function called "showAlert()" after some stuff, if something fails, I show the error message below the input field.
Thing is, if I keep clicking and clicking, it will spam the message spans, until they disappear (of course) due to the animation.
I tried using the ('div-that-is-animating').is(':animated') but didn't work, I can still spam them.
I also tried doing an unbind of toggle and click before calling this "showAlert()" function, but didn't work either.
Is it because delay(1000) there isn't counting like an animation? Or what else I can try?
Thanks in advance.
See if this works (assuming your button id is myButton):
messageEffect : function(container) {
$('#myButton').attr('disabled', true);
return container.fadeIn(100).delay(1000).fadeOut();
},
$.when(this.messageEffect($container)).done(function() {
$('#myButton').attr('disabled', false);
$container.empty();
$icon.remove();
$group.removeClass('has-feedback has-' + alertType);
});

Onload fires no matter where I place it

Right, I'm getting quite aggitated with this. I'm probably doing something wrong, but here's what I'm doing:
$(document).ready(function () {
$('#somebutton').click(function () {
openPage1();
});
$('#someotherbutton').click(function () {
openPage2();
});
});
var openPage1 = function () {
$('#iframe').attr('src', 'someurl');
$('#iframe').load(function () {
$('#button').click();
});
};
var openPage2 = function () {
$('#iframe').attr('src', 'anotherurl');
$('#iframe').load(function () {
$('#anotherbutton').click();
});
}
Whenever I click somebutton everything goes as expected. However when I click someotherbutton. The .load() from openPage1() is called first and I can't find a way to stop that. The .load() from openPage1() has a button with the same name, however on openPage2() I need to modify the contents before clicking the buttons.
I need to use .load() because I can't click the buttons before the document is ready.
Basically what I need is two seperate .load() instances on the same iframe, that don't fire off on each other.
Besides that, maybe my understanding of jQuery/JS is wrong, but shouldn't the .load() events only be listening after clicking the corresponding button?
Can someone help me out, this has been keeping me busy all afternoon.
Try using on, and once loaded, unbind
$("#iframe").on("load", function(){
$(this).off("load");
$('#button').click();
});
That way you remove the handler you put up before the second button is clicked?
By writing : $('#iframe').load(function (){ $('#button').click(); });, you are adding a listener on the load event, which will stay and be re-executed on each subsequent reload of the iframe.
Here is a jsfiddle to demonstrate this : click on the "reload" button, and see how many times the "loaded" message appears in your console.
in your case, if you click on #somebutton, then on #someotherbutton, after the second click, you will have two handlers bound on the load event, and both will be triggered.
If you click 5 times on #somebutton, you should end up calling 5 times $('#button').click().
If you want to execute it once, you can follow Fred's suggestion, or use jQuery .one() binder :
$('#iframe').one('load', function(){ $('#button').click() });
Here is the updated jsfiddle : 'loaded' should be displayed only once per click.
Maybe try and replace the lines in both functions like this:
$('#iframe').load(function() {
$('#anotherbutton').click();
};
$('#iframe').attr('src', 'anotherurl');
Otherwise it might be firing the event before the new event-handler has been set.
This isn't really an answer to your problem Now it is an answer, but I think utilizing functions as they were intended could be beneficial here, i.e.:
//Utilize a single function that takes arguments
var openPage = function (frame, src, eventEl) {
frame.attr('src', src); // If you pass frame as a jQuery object, you don't
frame.on("load", function(){ // need to do it again
$(this).off("load");
evEl.click(); //Same for your buttons
});
}
//Simplify other code
$(document).ready(function () {
$('#somebutton').click(function () {
openPage($("#iframe"),somehref,$("#buttonelement"));
});
$('#someotherbutton').click(function () {
openPage($("#iframe"),anotherhref,$("#someotherbuttonelement"));
});
});

Stop duplicate mouse over detection

I have a popup that is executed on mouseover with jquery.
Within that function I have a second delay before the popup displays using settimeout
Problem is if in that second they mouse over multiple times then multiple popups are triggered.
$('#div').mouseover(function() {setTimeout("popup()",1000);});
What I need to do is disable the detection and then re enable it in popup().
How might I do that?
You can use .hover() with a clearTimeout(), like this:
$('#div').hover(function() {
$.data(this, 'timer', setTimeout(popup, 1000));
}, function() {
clearTimeout($.data(this, 'timer'));
});
This clears the timeout you're setting if the mouse leaves, you'll have to stay on the element for a full second for the popup to trigger. We're just using $.data() on the element to store the timer ID (so we know what to clear). The other change is to not pass a string to setTimeout() but rather a reference directly to the function.
I guess something like this
(function(){
var popup_timer = 0;
$('#div').mouseover(function() {
clearTimeout(popup_timer);
popup_timer = setTimeout("popup()",1000);
});
});
EDIT updated code, clearTimeout added, wrapped

Queuing and stop propagating a click event to inside a div in Javascript

I'm trying to implement a "wait for 3 seconds to do this operation" <div>.
So, I have a <div> that has a bunch of elements in it that I want to be unclickable for say 3 seconds (a timer, or some other event), but somehow capture the events in a queue, and then fire them after the period (or some event of my choice) has elapsed/performed?
I'm thinking this is a problem kind of like putting up a modal dialog, and then not having anything beneath it clickable. Am I right in thinking this?
One possibility is to have the click handler for your DIV respond to clicks on its child elements as the event bubbles up. That handler would perform the queuing until the delay elapsed. Here's a rough example (using jQuery event handling for convenience):
(function() {
var isReady = false, queue = [];
setTimeout(function() {
isReady = true;
processQueue()
}, 3000);
$("#mainDiv").click(function(ev) {
if (isReady) {
//code to handle the click based on which child was clicked (ev.srcElement)
} else {
queue.push(ev.srcElement);
}
});
function processQueue() {
var i, elem;
for (i = 0; elem = queue[i]; i++) {
$(elem).click(); //re-trigger the click event
}
queue.length = 0;
}
})();
Give the div an onclick function, which starts off for the first 3 seconds as just holding an array of calls with their events...then after your 3000 millisecond timer is done, run a function that changes the div's onclick, allows things to be edited, and runs the array of events.
Another thing that Ive found to be helpful is the function.
setTimeout("alert('hello')",1250);
So something along the lines of surrounding all of the elements onclick method with a second method that will store that call for as long as you need.
<div onclick=registerClick("normallyDoThis()")></div>
Then you can setup a timer at the beggining of the time to change the Div and execute all the commands. Possibly with the eval command?
setTimeout("changeTheDiv()", 3000);
function changeTheDiv()
{
/*eval() all the items in a list of onclicks youve been storing up */
/*Then go through and parse out the register() from all the onclick methods*/
}
I hope this helps

Categories

Resources