With javascript, how do you simply express a number of iterations? - javascript

For example, say I want a block of code to run after a certain event occurs a certain amount of times (let's suppose a button is pressed in the following example). Would I use something similar to an if statement such as the following:
if( //certain event occurs: document.getElementById('btn').clicked == true 5 times
) {
//block of code to run if button is clicked 5 times: output in p element
}
<button id="btn" type="button">click</button>
<p></p>
If there's a more practical way than an if statement, I'd like know, please, and thanks. However, if an if statement is the way to go (unless of course there's a more practical method), how would you have a block of code run after a certain event occurs per specified increment of times? Utilizing the html elemenets above:
var alpha = 0;
function addition() {
alpha = alpha + 1;
return alpha;
}
document.getElementById('btn').addEventListener('click', 'get_addition');
function get_addition() {
document.getElementsByTagName('P')[0].innerHTML = addition();
if( //document.getElementById('btn').clicked == true per 5 times
) {
//block of code to run per 5 button clicks outputted in p element;
//then return to outputting values in p element rendered by addition() until next 5th iteration;
}
}

You can use data attributes with modulus operator to keep track of the clicks.
function get_addition () {
this.dataset.clicked = this.dataset.clicked || 0
this.dataset.clicked++
if (this.dataset.clicked%5===0) {
this.classList.add("green");
} else {
this.classList.remove("green");
}
}
document.getElementById('btn').addEventListener('click', get_addition);
.green {
background-color: green;
}
<button id="btn">Click</button>

You have a global variable, alpha, which counts how many times the button was clicked. Seems like you can just test whether alpha is a multiple of 5 and execute your special code then (within your get_addition function, after incrementing alpha).
if (alpha % 5 == 0) {
alert("5 clicks");
} else {
// regular code
}

This answer is pretty much the same as #James', but I have provided a self-contained snippet. The idea is the same -- increment a global, and use modulus to check for multiples.
let count = 0;
let btn = document.getElementById("b");
btn.addEventListener("click", function() {
count++;
if (count % 3 == 0) {
alert("You see this once every three clicks");
}
});
<button id="b">Click me 3 times</button>

The best way is to track the number of clicks, increment each time. When you reach 5 you can execute your code & reset the counter.
var counter = 0;
document.getElementById('btn').addEventListener('click', function(){
counter ++;
if(counter == 5)
{
counter = 0;
//this code executed after 5 clicks
}
//this code executed every click
});

Related

Prevent actions before setTimeout() is over

Im curently making a memory game and if two card matches it blocks them but if not they should flip back. The problem is that you can click on other cards even if there are two cards already flipped and if you click more cards the game goes crazy and stops working
Any idea?
here's the code
https://codepen.io/stivennpe/pen/KRxvxR?editors=1010
restart ();
bindcards();
// to restart the game and shuffle the cards
function restart() {
$('.restart').on('click', function () {
cards = shuffle($('.card'));
$(".card").each(function() {
$( this ).removeClass( "open match show" );
});
$('.deck').html(cards);
bindcards();
});
}
//to open/show the card
function bindcards(){
$('.card').click(function () {
$(this).addClass('open show');
let openCards = $('.open');
let list = jQuery.makeArray(openCards);
if (list.length === 2 && list[0].innerHTML ===
list[1].innerHTML){
$(openCards).addClass('match');
}
if (list.length === 2) {
setTimeout(hola, 1000)
function hola() {$(openCards).removeClass('open show');
}
}
});
}
thanks
Seems like for a simple solution you could set a global variable, something like blockClicks
If blockClicks is true, do nothing when a user clicks. Reset its value to false after timeout
There is a race condition between applying the .open class to the div element, refreshing the page, querying that element, and the user speeding their way through your game. Instead of adding the .open class to the div, hoping the page refreshes quick enough, then immediately querying against with to find out how many open cards you have, keep a local variable count. Below is the slight modification to your code
function bindcards() {
let numOfOpenCards = 0;
$(".card").click(function(e) {
++numOfOpenCards;
if(numOfOpenCards > 2)
return;
$(this).addClass("open show");
let openCards = $(".open");
let list = jQuery.makeArray(openCards);
if (numOfOpenCards >= 2 && list && list.length >= 2 && list[0].innerHTML === list[1].innerHTML) {
$(openCards).addClass("match");
}
if (numOfOpenCards >= 2) {
setTimeout(hola, 1000);
function hola() {
numOfOpenCards = 0;
let openCards = $(".open");
let list = jQuery.makeArray(openCards);
if(list) {
for(let i = 0; i < list.length; ++i)
$(list[i]).removeClass("open show");
}
}
}
});
}
If two cards are already open, the most recent card check. The previous card check should still complete and refresh as needed.
https://codepen.io/anon/pen/NzPBrB?editors=1010
Additional edit
If you do not want to use numOfOpenCards, you can use the following. Find how many are already open. If there are more than 2 already, just quit. If there are less than already flipped, add the class then query the DOM again. Anywhere numOfCards is used you can replace with list.length;
let openCards = $(".open");
let list = jQuery.makeArray(openCards);
if(list && list.length > 2)
return;
$(this).addClass("open show");
openCards = $(".open");
list = jQuery.makeArray(openCards);
if (list.length >= 2) {
setTimeout(hola, 1000);
function hola() {
$(list).removeClass('open show');
}
}

javascript - check a function execution count and make it execute not more than once

I have used a plugin "isInViewport js" which lets you know when an element is in viewport and lets you do something when that happens.
So I have written a counting function which is a number counter function. This executes when an element earn is in viewport.
But this counting function starts executing every time the element comes into viewport. I want this function to execute not more than once.
This is the code I had written which runs fine but not as I expect:
$('.earn').on('inview', function (event, visible) {
console.log('inview');
if (visible == true) {
console.log('inview count');
counting();
} else {
$('#counter').text(0);
$('#counter2').text(0+"$");
}
});
The pusedocode for what I am looking for is:
if(count of function == 0){
executeFunction();
}
else{
}
Could someone please provide a solution for this through javascript or jquery?
If you just need counting to run once, you can do something like this in your inview handler.
if (visible == true) {
console.log('inview count');
if (!this.is_counted) { // 'this' should refer to your element.earn
counting();
this.is_counted = true;
}
}

If statement does not work when condition is met

Here is my code:
var count = 2;
var decrementAmount = 1;
function reduceVariable() {
count -= decrementAmount;
}
$("#button").click(function() {
reduceVariable();
});
if (count == 0) {
$("#avrageReactionTime").html("Hello");
};
When i click my button twice the div that has the id avrageReactionTime does not change to have the text hello. Why do i have this problem...
Right now you test once, instead of testing every time the counter changes.
You must put the if inside the event handler :
$("#button").click(function() {
reduceVariable();
if (count==0) {
$("#avrageReactionTime").html("Hello");
}
});
Note that properly indenting your code makes it obvious.

Pure JS "If stament depending the number of click"

I was searching for this problem but I didn't find a solution. I'm trying to create a code where when you click a button do one thing, and when you press the same button later do other thing. I tried to create and "if-else" statement but I can't (don't know) how to count the number of clicks.
The code is:
<button type="submit" id="btnshwmap" onClick="init()" >Show Map</button>
And the if-else :
function init() {
var click =0;
if (click === 0) {
do this
var click = 1;
} else {
do this
}
});//end click
Basically I'm trying to use this example Jquery if its the first time element is being clicked
But the answer are using Jquery I'm trying not use any library.
Thanks a lot!
The problem is that you keep on resetting click=0 every time you call the function.
I would suggest something like this:
function init() {
if( !init.click) {
// first, third, fifth etc.
init.click = 1;
]
else {
// second, fourth...
init.click = 0;
}
}
You just need to have the click counter outside the function, in the global area.
var click =0;
function init() {
if (click == 0) {
//do this once
click = 1;
} else {
//do this every other time
}
});//end click
You could try toggling the value set for the button with the click. Something like:
function init() {
var value = document.getElementById('btnshwmap').value;
if (value === 1) {
do this
document.getElementById('btnshwmap').value = 2;
} else {
do this
document.getElementById('btnshwmap').value = 1;
}
});//end click
Or keep a global variable to track the click status, rather than setting it every time you run the function.

IE7 issues with my jQuery [click and change functions]

I have the following snippets of code. Basically what I'm trying to do is in the 1st click function I loop through my cached JSON data and display any values that exist for that id. In the 2nd change function I capturing whenever one of the elements changes values (i.e. yes to no and vice versa).
These elements are all generated dynamically though the JSON data I'm receiving from a webservice. From my understanding that is why I have to use the .live functionality.
In Firefox everything works as expected (of course). However, in IE7 it does not. In IE7, if I select a radio button that displays an alert from the click function then it also adds to the array for the changed function. However, if the radio button does not do anything from the click function then the array is not added to for the change.
As I look at this code I'm thinking that I might be able to combine these 2 functions together however, right now I just want it to work in IE7.
$(document).ready(function () {
//This function is run whenever a 'radio button' is selected.
//It then goes into the CPItemMetaInfoList in the cached JSON data
//($.myglobals) and checks to see if there are currently any
//scripts to display.
$("input:radio").live("click", function () {
var index = parseInt(this.name.split(':')[0]);
for (i = 0; i <= $.myglobals.result.length - 1; i++) {
if ($.myglobals.result[i].CPItemMetaInfoList.length > 0) {
for (j = 0; j <= $.myglobals.result[i].CPItemMetaInfoList.length - 1; j++) {
if (index == $.myglobals.result[i].QuestionId) {
alert($.myglobals.result[i].CPItemMetaInfoList[j].KeyStringValue);
return;
}
}
}
}
});
});
$(document).ready(function () {
var blnCheck = false;
//Checks to see if values have changed.
//If a value has been changed then the isDirty array gets populated.
//This array is used when the questionSubmit button is clickeds
$('input').live('change', function () {
blnCheck = false;
for (i = 0; i <= isDirty.length - 1; i++) {
if (isDirty[i] == $(this).attr("name")) {
blnCheck = true;
break
}
}
if (blnCheck == false) {
isDirty[arrayCount] = $(this).attr("name");
arrayCount += 1;
alert($(this).attr("name"));
}
});
$('textarea').live('change', function () {
blnCheck = false;
for (i = 0; i <= isDirty.length - 1; i++) {
if (isDirty[i] == $(this).attr("id")) {
blnCheck = true;
break
}
}
if (blnCheck == false) {
isDirty[arrayCount] = $(this).attr("id");
arrayCount += 1;
//alert($(this).attr("name"));
}
});
});
UPDATE:
I had to move this chunk of code into the click function:
blnCheck = false;
for (i = 0; i <= isDirty.length - 1; i++) {
if (isDirty[i] == $(this).attr("name")) {
blnCheck = true;
break
}
}
if (blnCheck == false) {
isDirty[arrayCount] = $(this).attr("name");
arrayCount += 1;
alert($(this).attr("name"));
}
Like this:
$(document).ready(function () {
//This function is run whenever a 'radio button' is selected.
//It then goes into the CPItemMetaInfoList in the cached JSON data
//($.myglobals) and checks to see if there are currently any
//scripts to display.
$("input:radio").live("click", function () {
var index = parseInt(this.name.split(':')[0]);
for (i = 0; i <= $.myglobals.result.length - 1; i++) {
if ($.myglobals.result[i].CPItemMetaInfoList.length > 0) {
for (j = 0; j <= $.myglobals.result[i].CPItemMetaInfoList.length - 1; j++) {
if (index == $.myglobals.result[i].QuestionId) {
alert($.myglobals.result[i].CPItemMetaInfoList[j].KeyStringValue);
return;
}
}
}
}
blnCheck = false;
for (i = 0; i <= isDirty.length - 1; i++) {
if (isDirty[i] == $(this).attr("name")) {
blnCheck = true;
break
}
}
if (blnCheck == false) {
isDirty[arrayCount] = $(this).attr("name");
arrayCount += 1;
}
});
});
But...
I had to leave the change function the same. From my testing I found that the .click function worked for IE7 for the radio buttons and checkbox elements, but the .change functionality worked for the textboxes and textareas in IE7 and FF as well as the original functionality of the radio buttons and checkbox elements.
This one got real messy. Thanks to #Patricia for looking at it. Here suggestions did lead me to this solution. I'm going to leave the question unanswered as I wonder if there isn't a cleaner solution to this.
Fact: change event on radio buttons and checkboxes only get fired when the focus is lost (i.e. when the blur event is about to occur). To achieve the "expected" behaviour, you really want to hook on the click event instead.
You basically want to change
$('input').live('change', function() {
// Code.
});
to
$('input:radio').live('click', functionName);
$('input:not(:radio)').live('change', functionName);
function functionName() {
// Code.
}
(I'd however also take checkboxes into account using :checkbox selector for the case that you have any in your form, you'd like to treat them equally as radiobuttons)
I think this is because IE fires the change when focus is lost on checks and radios. so if the alert is popping up, focus is being lost and therefor the change event is firing.
EDIT:
try changing the $('input') selector to $('input:not(:radio)')
so the click will fire for your radios and the change for all your others.
Edit #2:
How bout putting the stuff that happens on change into a separate function. with the index as a parameter. then you can call that function from the change() and the click(). put the call to that function after your done with the click stuff.
You're declaring your blnCheck variable inside one of your document.ready() functions. You don't need two of these either, it could all be in one.
This means that the variable that you're declaring there won't be the one used when your change function is actually called, instead you're going to get some kind of implicit global. Don't know if this is part of it, but might be worth looking at. You should declare this at the top of your JS file instead.

Categories

Resources