Stopping Images being swapped on click - javascript

I am attempting to code a checkers game in JavaScript and I am having trouble with stopping images after one swap. In the current implementation (below) the images swap on click and then when you click on another part of the board (a table in this case) another 'piece' is placed. But then when you click again another is placed and another etc. I am trying to not have a piece be placed when you click again.
var imageSwaped = false;
function clickOnBlankSpace(object)
{
this.src="Directory/BlackPiece.png";
imageSwaped = true;
this.removeEventListener("click", clickOnBlankSpace);
return;
}
var BlackPieces = document.getElementsByClassName("BlackPiece");
var RedPieces = document.getElementsByClassName("RedPiece");
var BlankSpaces = document.getElementsByClassName("BlankSpace");
for(var j = 0; j<BlackPieces.length;j++)
{
var BlackPiece = BlackPieces[j];
BlackPiece.addEventListener("click", function()
{
this.src="Directory/BlackPieceH.png";
this.className ="BlackPieceH";
for(var j = 0; j<BlankSpaces.length;j++)
{
var BlankSpace = BlankSpaces[j];
if (!imageSwaped) BlankSpace.addEventListener("click", clickOnBlankSpace);
}
})
}

Related

createElement and loops [duplicate]

In JavaScript I am creating a grid (the type of grid you see in Photoshop) with HTML tables. The grid size is going to be variable, i.e., changeable by the user, so the size of each grid square must be calculated and divided by the number of pixels available to get an exact size grid.
I've done all this, but I have a problem adding in the necessary table elements to create the grid. My code is in full working order, except when I use the appendChild() function inside a for loop it only ever appends a single child, when it should be appending up to a couple of hundred.
My code:
grid.show = function(event)
{
var e = event;
if(grid.show_grid == false)
{
grid.show_grid = true;
parent.document.getElementById("grid_table").style.display = "block";
// Get grid (table) and create some elements.
grid.get_grid = parent.document.getElementById("grid_table");
grid.tr = parent.document.createElement("tr");
grid.td = parent.document.createElement("td");
// Clear the grid of all squares so we don't have to worry about subtracting anything.
grid.get_grid.innerHTML = "";
// Calculate the number of horizontal and vertical squares.
var horizontal = Math.ceil(grid.total_width / grid.size);
var vertical = Math.ceil(grid.total_height / grid.size);
// This was a nested loop, removed for demonstration.
// Attempting to add 10 "<tr><td></td></tr>" to the table.
for(var j = 0; j < 10; j++)
{
grid.tr.appendChild(grid.td);
}
//console.log(grid.tr);
// Add the elements to the table.
grid.get_grid.appendChild(grid.tr);
}
else
{
grid.show_grid = false;
parent.document.getElementById("grid_table").style.display = "none";
}
}
This only ever returns a single table row with single table data inside, like so:
<tr>
<td></td>
</tr>
I've already looked at this page and this page, and they sound promising but I just can't figure out how to make this work.
EDIT: Code now working, solution:
grid.show = function(event)
{
var e = event;
if(grid.show_grid == false)
{
grid.show_grid = true;
parent.document.getElementById("grid_table").style.display = "block";
grid.get_grid = parent.document.getElementById("grid_table");
grid.tr = null;
grid.td = null;
grid.get_grid.innerHTML = "";
var horizontal = Math.ceil(grid.total_width / grid.size);
var vertical = Math.ceil(grid.total_height / grid.size);
for(var i = 0; i < vertical; i++)
{
grid.tr = parent.document.createElement("tr");
for(var j = 0; j < horizontal; j++)
{
grid.td = parent.document.createElement("td");
grid.td.width = grid.size;
grid.td.height = grid.size;
grid.tr.appendChild(grid.td);
}
grid.get_grid.appendChild(grid.tr);
}
}
else
{
grid.show_grid = false;
parent.document.getElementById("grid_table").style.display = "none";
}
}
You are appending the same element over and over. You need to call document.createElement each time you wish to have a new element.
EDIT: If the element setup is really complicated and potentially includes children then you can also use Node.cloneNode
If you want to make one copy of the element, you will need to clone it. Use cloneNode()
So change
grid.tr.appendChild(grid.td);
to
grid.tr.appendChild(grid.td.cloneNode(true));
for(var j = 0; j < 10; j++)
{
grid.tr.appendChild(grid.td);
}
should be
for(var j = 0; j < 10; j++) {
var newTd = parent.document.createElement('td');
grid.tds.push(newTd); // if you need it, not sure why though
grid.tr.appendChild(newTd);
}

Images Change on Button Press Broken

I am trying to get a whole page of images to change when I click a single button. Here is my current code. My issue right now is I can change one image just fine but when I add the code to change the second image it stops the first image from changing and also will not let the second image change back to its original image.
Here is my JavaScript
//First image
var imageSources = ["origonal-image.jpg","2ndimage.jpg"]
var buttons = document.getElementsByClassName("change-image")[0];
var index = 0;
buttons.addEventListener('click', function() {
if (index === imageSources.length) {
index = 0;
}
document.getElementById("imagechangingid").src = imageSources[index];
index++;
});
//Second image
var imageSources1 = ["origonal-image.jpg","2ndimage.jpg"]
var buttons = document.getElementsByClassName("change-image")[0];
var index = 0;
buttons.addEventListener('click', function() {
if (index === imageSources1.length) {
index = 0;
}
document.getElementById("imagechangingid2").src = imageSources1[index];
index++;
});
This is because you are overriding your first event listener when you write below code twice. one implementation (I am guessing the second one) will override the other
buttons.addEventListener('click', function() {}
if the same button click should change both images - you should handle it in same event handler.
var imageSources = ["origonal-image.jpg","2ndimage.jpg"]
var buttons = document.getElementsByClassName("change-image")[0];
var imageSources1 = ["origonal-image.jpg","2ndimage.jpg"]
var buttons = document.getElementsByClassName("change-image")[0];
var index = 0;
var indexOne = 0;
buttons.addEventListener('click', function() {
if (index === imageSources1.length) {
index = 0;
}
document.getElementById("imagechangingid2").src = imageSources1[index];
index++;
if (indexOne === imageSources.length) {
indexOne = 0;
}
document.getElementById("imagechangingid").src = imageSources[indexOne];
indexOne++;
});

Hide/Show div p5.js

I am using the p5.js library, and I am working on a speech recognition - text to speech project. Kind of a chatbot.
Input is voice input which becomes a string.
I am outputting the result from a txt file, using a markov chain. Output is a string contained in a div.
My question is:
Is there a way to hide/show the div containing my input/output (.myMessage and .robotMessage) in intervals?
I want the whole screen first showing only the input when I am talking, then input disappears and only output showing, then when the computer voice finishes speaking my input is shown in the screen and so on...
Here some parts of the code, let me know if it is clear enough.
//bot
function setup() {
noCanvas();
//reads and checks into the text file
for (var j = 0; j < names.length; j++) {
var txt = names[j];
for (var i = 0; i <= txt.length - order; i++) {
var gram = txt.substring(i, i + order);
if (i == 0) {
beginnings.push(gram);
}
if (!ngrams[gram]) {
ngrams[gram] = [];
}
ngrams[gram].push(txt.charAt(i + order));
}
}
//voice recognition
let lang = 'en-US';
let speechRec = new p5.SpeechRec(lang, gotSpeech);
let continuous = true;
let interim = false;
speechRec.start(continuous, interim);
//text-to-speach
speech = new p5.Speech();
speech.onLoad = voiceReady;
function voiceReady() {
console.log('voice ready');
}
//input-ouput
function gotSpeech() {
if (speechRec.resultValue) {
var p = createP(speechRec.resultString);
p.class('myMessage');
}
markovIt();
chooseVoice();
speech.speak(answer);
}
}
and
function markovIt() {
var currentGram = random(beginnings);
var result = currentGram;
for (var i = 0; i < 100; i++) {
var possibilities = ngrams[currentGram];
if (!possibilities) {
break;
}
var next = random(possibilities);
result += next;
var len = result.length;
currentGram = result.substring(len - order, len);
}
var answer = result;
window.answer = answer;
var p2 = createP(answer);
p2.class('robotMessage');
}
how the HTML looks
<div class="container">
<div class="myMessage"></div>
<div class="robotMessage"></div>
</div>
Use select() to get a document element by its id, class, or tag name. e.g:
let my_div = select("myMessage");
Change the style of an element by style().
e.g hide:
my_div.style("display", "none");
e.g. show:
my_div.style("display", "block");
See also Toggle Hide and Show

for loop with array for background colors

This code takes the background color from an array of divs and colors another div with it. My problem is that I can put any value from 0-2 (0-2 being the array value of the original div) in task1[i].style.background but when I put i so that the loop gives me the value specific to the one moused over it brakes. I cannot use JQuery, JavaScript only.
EDIT: I expect task1[i].style.background to be equal to the background color of the specific div it hovered over from the loop running through the array.
var task1 = document.querySelectorAll('.t1_colors');
var task1background = document.querySelector('#task1');
var white = function() {
task1background.style.background = 'white';
}
for (var i = 0; i < task1.length; ++i) {
task1[i].addEventListener('mouseover', function () {
colorize();
});
}
//Something wrong with i
var colorize = function() {
task1background.style.background = task1[i].style.background;
}
for (var i = 0; i < task1.length; ++i) {
task1[i].addEventListener('mouseout', function() {
white();
});
}
What do you expect the value of i to be when you use it in colorize?
task1background.style.background = task1[i].style.background;
When colorize executes inside mouseover event listener, all loops have already terminated because i value reached task1.length.
You have to capture the current i value.
Change it to
for (var i = 0; i < task1.length; ++i) {
task1[i].addEventListener('mouseover', (function (index) {
return function() { colorize(index); };
})(i));
}
and
var colorize = function(index) {
task1background.style.background = task1[index].style.background;
}

How do I access DOM nodes from an array in javascript?

I am trying to build a drop-down menu that will show a row to the side of it when you hover over one of the cells with the mouse. I'm really new with using the DOM, and javascript as well.
The problem I'm running into is that the array I have created doesn't seem to access what I thought it should. Is it just my syntax, or do I need to approach this differently? Here is my code:
window.onload = function () {
var tableID = "strokerKitMenu";
var table = document.getElementById(tableID);
var tableRows = table.getElementsByTagName("tr");
var tableCell = [];
var counter = 0;
for (i = 0; i < tableRows.length; i++) {
tableCell[i] = new Array();
tableCell[i].push(tableRows[i].getElementsByTagName("td"));
}
for (i = 0; i < tableCell.length; i++) {
tableCell[0, i].style.display = "block"; //This doesn't compile
alert(tableCell[0, i].Text); //This comes back "undefined"
for (j = 1; j < tableCell[i].length; j++) //I haven't even tested this part yet
{
tableCell[i][j].onmouseover = function showCell() {
tableCell[i][j + 1].style.display = "block";
}
tableCell[i][j].onmouseout = function hideCell() {
this.style.display = "none";
}
} //end inner for loop
} //end outer for loop
}
tableCell[0, i].style.display="block"; //This doesn't compile
This syntax is invalid in JavaScript: you have specified two indices for tableCell but I guess you meant tableCell[0][i].style.display="block";
alert(tableCell[0, i].Text); //This comes back "undefined"
Once you fix the first error, you will want to change this to tableCell[0][i].textContent.
tableCell[i].push.apply(tableCell[i], tableRows[i].getElementsByTagName("td"));
You don't want to push the single array in. You want to push all the elements in. Otherwise you would have to access them as tableCell[i][0][j]

Categories

Resources