onclick event in a for loop certain amount of times - javascript

I thought that this onClick event in a For loop would help me but when I tried it, it still didn't work.
I am making a simple Battleship game, and while I'm trying to have the user click on only 4 squares to place on ship, the loop keeps going and doesn't stop after 4 tries. I have my onclick even handler in a for loop, but after 4 tries it doesn't stop. I've tried adding a count variable after the end, and even tried adding a break statement but can't get it to work.
Here's my code:
function placeShips() {
var playerTable = document.getElementById("mainPlayer");
var playerCells = playerTable.getElementsByTagName("td");
var count = 1;
alert("Please place the first ship. Click on 4 squares.");
while (count <= 4) {
for (i = 0; i < playerCells.length; i++) {
playerCells[i].onclick = placeBattleship;
}
count++;
}
}
The placeBattleship function contains the code to change the grid square to a background color of red to mark it. My problem is that once the user clicks 4 squares, you can keep going and click on more and more. I can't get the above for loop that calls the placeBattleship function to stop after the user clicks on 4 squares. I've tried putting it in a while loop, and even the solution in the above link, as well as moving the assignment of count, but can't get it to stop after x amount of times (in this case, 4).
Any ideas on what I'm doing wrong, or a better way to do it?

Wouldn't you consider to use jQuery?
Look your function much shorter:
function placeShips() {
$("td:lt(4)").click(placeBattleship);
}
You can testify on the code below:
<table>
<tr>
<td>1.1</td><td>2.1</td>
</tr>
<tr>
<td>1.2</td><td>2.2</td>
</tr>
<tr>
<td>1.3</td><td>2.3</td>
</tr>
</table>
<div id="console"></div>
<script>
$("td:lt(4)").each(function(){
$("#console").append("Content of "+ $(this).html() + "<br/>");
});
$("td:lt(4)").click(function(){
$("#console").append("Clicking "+ $(this).html() + "<br/>");
});
</script>
...or on my Plunker: https://plnkr.co/edit/yNZw6ZhkNfA9E0NdQg7V

So, now we have a solution that stop for 4th click on the squares:
function placeBattleship() {
var $shipDisplay = $("#shipDisplay");
var counter = $shipDisplay.data("counter");
if(counter++ < 4) {
$(this).css("background-color", "red");
$shipDisplay.data("counter", counter);
}
}
function placeShips() {
$("td").click(placeBattleship);
}
$(document).ready(function(){
placeShips();
});
I use a div with id shipDisplay to store a data-attribute for count the clicks.
Look at the plunker: http://plnkr.co/edit/PEba15PSLv2LK6qjY7AD?p=preview

You should separate priorities in your logic and removeEventListener when counter hits 4 , hopefully this helps you :
//defined outside the function
var counter = 0;
playerCells.addEventListener("click" , placeShips );
Then
function placeShips() {
if(counter <= 4){
//Move ship
placeBattleship();
//add to counter
counter++
}else{
//Remove click event if counter reaches 4 .
playerCells.removeEventListener("click" , doSomethingElse)
}
}

You question needs a bit clarification. To my current understanding, you need to move the checking of count to placeBattleship.
What you are doing is binding click to same tds 4 times, not limiting the number of event triggering to 4 times.
// pseudo code
var count = 4; // this is global
var currentCount = 0;
initFunc() {
// bind click events ONCE
}
startPlacing() {
// accept user click and place ship
// set currentCount to zero
}
placeShip() {
// the callback of user `click`
// check for currentCount == count then move on (no more placement)
// increase currentCount by 1
// place ship
}
Note that after an event is triggered, the listener will not be removed. Until you removeEventListener() from it, it will always be listening.

Related

Setting a limit on the number of times a note is created

I am currently working on a postIt for my website where pressing the plus button would create an editable post it/sticky notes. I am done with that part now but I am struggling with the next part which is limiting the number of sticky notes to just 4. I tried having a global variable that would serve as a counter so when the counter is 3, it should stop creating more sticky notes but unfortunately, it is not working.
Here is the link to my workable code:
Sticky note
And this is my futile attempt at limiting the number of sticky notes to 4.
$("#create").click(function(){
var count = 0;
if( count < 4){
$("#create").click(function() {
$(this).before("<textarea></textarea>");
});
count++;
}
}
Can anyone please give me pointers as to how to limit the notes to 4? I have been working on this forever now.
Just move var count = 0; outside the event listener and remove the inner event listener:
var count = 0; // outside the scope of the event listener function bellow so it won't get destroyed/recreated each time the function get called (ie when a clicks happen)
$("#create").click(function() {
if(count < 4) { // we haven't yet exceeded the limits
$(this).before("<textarea></textarea>"); // don't attach another click event listener on #create (we are already in one) so just create the note.
count++;
}
});
Everytime you click create, count the number of textarea elements then determine if you should create a new one:
$("#create").click(function() {
var count = $("textarea");
if (count.length < 4) {
$(this).before("<textarea></textarea>");
}
});
You can even add a class in the newly created textarea to ensure that you only count the ones created by this function.
HTML:
<textarea>This is not part of the group.</textarea>
<textarea class="sticky">This is a sticky note you can type and edit.</textarea>
<div id="create">+</div>
JS:
$("#create").click(function() {
var count = $("textarea.sticky");
if (count.length < 4) {
$(this).before("<textarea class='sticky'></textarea>");
}
});
The problem is that you are defining your count variable inside of your click event handler. As such, every time you click the element, the counter gets reset. You also shouldn't make use of a secondary click handler inside the main one.
To resolve this, bring the count variable outside of the click handler:
var count = 0;
$("#create").click(function() {
if (count < 3) {
$(this).before("<textarea></textarea>");
count++;
}
});
Note that the conditional should check that the count is less than 3, because it increases the count after creation. If it is set to check if the count is less than 4, five notes would be created.
In order to also hide the + after creating the fourth element, you would use:
if (count == 3) {
$(this).hide();
}
After increasing the count.
This can be seen working here.
Hope this helps! :)

Simon game mechanism (Javascript) -- Sequence input

Essentially I have the following:
1) Game will randomly pre-choose 20 random sequence
2) Game will turn off click event listener
3) Game will display the light sequence for each level(starting level 1)
4) Game will turn on click event listener so that user can input via .buttons
5) Game will evaluate user's input
I am having trouble on the 5th step...
How do evaluate user's input while the game is still running? I thought about using while loop but it seems that doesn't work quite nicely...
Board.prototype.getUserInput = function(){
board.userInput = []; //reset the user input
$(".button").click(function(){
var currentLevel = board.sequence.slice(0,board.index);
var color = $(this).attr('id');
board.userInput.push(color)
board.evaluateInput(currentLevel);
})
}
heres my codepen: http://codepen.io/neotriz/pen/RRxOJb
This is an old implementation i had done of the game.
http://codepen.io/antoniskamamis/pen/pJAxq?editors=0010#0
Basically since you have predefined the order all you have to do is increase a counter with each click on a color and check if the color clicked is the one in the nth position of your predefined colors
pseudocode for the solution
var predefinedColors = ['red', 'yellow',...]
var turn = 0;
buttons.addEventListener("click", ev => {
if(ev.target.classList.contain(predefinedColors[turn]){
//right guess
turn++
} else {
// wrong guess reset game
}
})

Looping inside jQuery function only issue

I'm having some trouble with jQuery in Meteor - I'm just trying to learn so I hope someone could help.
So when #addButton is clicked it will append the div to the .formField and each div created on click will have an unique class, eg formField[1], formField[2] etc
The trouble is when the button is clicked instead of just changing the name of the div only, the div is also added 50 times. I know how dumb it sounds as its a loop, but how would I loop only the div's class on click so each have a different name?
My code is below:
Template.form.events({
'click #addButton': function(event) {
var i;
for (i = 0; i < 50; i++) {
$(".formField").append('<div class="formField['+i+']">.....</div>');
}
return false;
If I understand what you are doing here you don't need a loop. You just need a variable to increment every time the button is clicked. Take your append out of the loop and instead on click increment your variable by one then call an append. No loop necessary.
var i = 0;
Template.form.events({
'click #addButton': function(event) {
i += 1;
$(".formField").append('<div class="formField['+i+']">.....</div>');
}
});
return false;
Do it like this, (i.e. by creating a closure), click run to verify
var uuid = 0;
$('#addButton').on('click', function (event) {
uuid = uuid + 1;
$(".formField").append('<div class="formField[' + uuid + ']">Form' + uuid + '</div>');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="formField"></div>
<input type="button" value="Add New" id="addButton"></input>

Event on second and third click

I'm currently in the process of making a website for my band, and one idea I had was that on a specific page, you would see a picture of each band member, and when you hover over it with your mouse the picture would change and you would hear that band member saying something, then when you click on them, they say something else and you'll be redirected to their page.
This alone isn't a problem, but for one member, I want it to take three clicks before you actually get redirected to his page; I also want him to say something different at each click.
So what I'm basically looking for is a way to create different events on the first, second and third click (preferably using javascript).
I hope you guys can help me out, thanks in advance!
Just use variable to count clicks:
var count = 0
$(".test").click(function() {
count++;
if(count == 1) {
$(".test").text("first");
}else if(count == 2){
$(".test").text("second");
}else if(count == 3){
$(".test").text("third");
count = 0;
}
})
http://jsfiddle.net/x83bf1gq/4/
An option could be to create an onclick handler that keeps saying things until all texts in an array of texts are said. Once all the texts have been said, you can just redirect or whatever action you need to be done. Example:
var johnTexts = [
'hello',
'how are you doing',
'come on'
];
var jamesTexts = [
'ready',
'go'
];
var sayTexts = function (texts) {
var i = 0;
return function () {
if (i < texts.length) {
alert(texts[i++]);
} else {
alert('do your redirect or whatever you need');
}
};
}
document.getElementById('john').onclick = sayTexts(johnTexts);
document.getElementById('james').onclick = sayTexts(jamesTexts);
See demo
Simply set an event listener that makes different actions based on a global counter of clicks.
Check this fragment of code:
//set counter
var counter = 0;
var component = document.getElementByID("ID-of-component");
component.addEventListener('mouseover', function(){
//do something
});
component.addEventListener('click', function() {
switch(++counter) {
case 1: /* do something */ break;
case 2: /* do something */ break;
case 3: /* do something */ break;
}
counter = 0; //reset counter
});
Obviously, you have to write this code for each component of your band.

Javascript next button array

I am unrehearsed in javascript and was hoping for some help with a next button that links to an id based on the array. Here is the array
var baseline_next=new Array();
baseline_next[0]="#one";
baseline_next[1]="#two";
baseline_next[2]="#three";
baseline_next[3]="#four";
baseline_next[4]="#five";
baseline_next[5]="#six";
baseline_next[6]="#six2";
baseline_next[7]="#seven";
baseline_next[8]="#eight";
baseline_next[9]="#nine";
baseline_next[10]="#ten";
baseline_next[11]="#eleven";
baseline_next[13]="#thirteen";
baseline_next[14]="#fourteen";
baseline_next[15]="#fifteen";
baseline_next[16]="#sixteen";
baseline_next[17]="#seventeen";
baseline_next[18]="#eighteen";
baseline_next[19]="#nineteen";
baseline_next[20]="#twenty";
baseline_next[21]="#twentyone";
baseline_next[22]="#twentytwo";
baseline_next[22]="#twentythree";
Basically what I need is, when the next button is clicked first ("0" ~ #one) I need the next buttons id to become two, and when clicked again it needs to become #three. I have no idea how to link an array to a button. The reason I need this to happen is because I am using ajax to .load div contents, so the next button doesn't actually submit, it just becomes a new next button. I dont know if it matters, but here is a part of what the button would cause to happen on click.
$('#one').click(function(){
$("#area").hide("slide", { direction: "left" }, 500);
$("#area").load("test_it.jsp #area");
$("#area").show("slide", { direction: "right" }, 500);
$("#two").show();
});
$('#two').click(function(){
if((document.form1.baseline_01[0].checked || document.form1.baseline_01[1].checked| document.form1.baseline_01[2].checked)
&& (document.form1.baseline_02[0].checked || document.form1.baseline_02[1].checked)
&& (document.form1.baseline_03_native.checked || document.form1.baseline_03_asian.checked|| document.form1.baseline_03_black.checked|| document.form1.baseline_03_pacific.checked|| document.form1.baseline_03_white.checked|| document.form1.baseline_03_other.checked)){
if(document.form1.baseline_03_other.checked && document.form1.baseline_03_other_text.value==""){
alert("Please fill in what other race you concider yourself to be.");
return false;
}else{
$("#area").hide("slide", { direction: "left" }, 500);
$("#area").load("test_it.jsp #area2");
$("#area").show("slide", { direction: "right" }, 500);
$("#three").show();
return true;
}
}else{
alert("Please select an answer for each question.");
return false;
}
});
I must apologize in advanced if my question is hard to follow, I just started coding this year.
I think that you should consider reworking your code a bit to not have this list of IDs and use a single class on all of the elements. It would help to see how your HTML is set up to get the next element based on class as well.
Since you already have this array of doom, though, I guess we'll have to use it. Ideally, you have the same class on each element. Let's say, .number.
$(".number").on('click', function () {
var nextID = baseline_next.indexOf(this.id) + 1;
});
If you can't use .number, then you can do the same thing except with a list of every ID that needs to be bound .. ouch. In the above function, nextID should be the index of the ID that comes after the clicked element.
By the way, IDs can be numbers, and you could even use data-id that contains the number. That would be easier too.
OK I really need to ask why are you doing this, are you sure that creating more than 20 ID's called like that is the better way to do want you want?
Anyways, first of all, you can create the array in a shorthand way:
var baseline_next= ["#one", "#two", "#four", "#five", "#six", "#six2" ..., "#twentythree";
(btw "#six2"? really?)
then do something like this:
var counter = 0; // start for the first one
$("#button").on('click', function () {
var id = counter++;
baseline[id]; // and I don't know what you want to do with this, but here it is!
});
Ancient question. (7 years wowzers). Here is some logic that I used for determining the next item in an array using indexOf. This will also start from the beginning once you reach the end of your array.
let options = [true,false,null];
let current = options.indexOf(this.get('order'));
let next = (current+1 > options.length-1 ? 0 : current+1);
this.set('order', options[next]);
It can be simplified as follows:
let baseline_next = ["#one", "#two", "#three"];
Don't use a var as it behaves unpredictably.
Add a variable count to change the index of the array.
let count = 0;
let baseline_next = ["#one", "#two", "#three"];
$(baseline_next[count]).click(function() {
count++;
});
Or
let count = 0;
let baseline_next = ["#one", "#two", "#three"];
$("#one").click(function() {
$(baseline_next[count]).click();
count++;
});

Categories