I am trying to compare two values of different div classes using the data attribute. I have multiple div classes like these two, all with different data-vale:
<div class="card" data-value=38>
<img class ="front-face" src= "PNG/QH.png"/>
</div>
<div class="card" data-value=39>
<img class ="front-face" src= "PNG/KH.png"/>
</div>
Every div class will also receive a unique order using cards.style.order
In a JS function the user will select two cards (firstCard,secondCard) and the function should check if the value of firstCard is one greater than the value of the card with order 1 more than secondCard.
Here is the code I have been trying to use:
const cards = document.querySelectorAll('.card');
if(firstCard.dataset.value === cards[cards.indexOf(secondCard)-1].dataset.value)
cards is an array housing all of my div classes. One of the errors I received told my that indexOf is not a usable function here. I think this may be because the div classes are not actually part of an array and I need a different method to find the 'value of' something rather than the 'index of'.
For example, if a row of cards goes 2D,7S,9D,8H,3D, the user can click 3D for firstCard and 7S for secondCard. The function will verify that the value of 3D is one greater than 2D and will swap the positions of 3D and 7S.
I made my little snippet with auto-generating squares that can be moved as you suggested. You might check it out. If something is not okay, you might point it out, maybe I forgot something.
let cardsArray = [{
"value": 7,
"color": "red"
}, {
"value": 6,
"color": "yellow"
}, {
"value": 5,
"color": "green"
}, {
"value": 4,
"color": "red"
}, {
"value": 3,
"color": "yellow"
}, {
"value": 2,
"color": "green"
}, {
"value": 1,
"color": "green"
}]
// Function to automatically generate some squares
function drawSquares() {
let squaresParent = $("#squaresParent");
squaresParent.empty();
let lCALen = cardsArray.length;
for (let i = 0; i < lCALen; ++i) { //make it efficient for checking length
// Creating a text object for display purposes only
let newText = $('<p>').append(cardsArray[i].value);
// Creating a new card
let newCard = $('<div>').attr({
'data-value': cardsArray[i].value,
'style': 'background-color:' + cardsArray[i].color,
'index': i,
'class': 'card'
}).append(newText);
squaresParent.append(newCard);
}
}
drawSquares();
assignEvents();
let firstCard = null;
let secondCard = null;
function compareAndMove(fC, sC) {
//console.log("Switching...");
let firstCardIndex = fC.attr("index");
let secondCardIndex = sC.attr("index");
let beforeSecondCardIndex = 0;
if (secondCardIndex > 0)
beforeSecondCardIndex = secondCardIndex - 1;
let firstCard = cardsArray[firstCardIndex];
let secondCard = cardsArray[secondCardIndex];
let beforeSecond = cardsArray[beforeSecondCardIndex];
if (firstCard.value - 1 === beforeSecond.value) {
let temp = firstCard;
cardsArray[firstCardIndex] = secondCard;
cardsArray[secondCardIndex] = temp;
drawSquares();
assignEvents();
} else {
fC.removeClass("selected");
sC.removeClass("selected");
}
//console.log("Exiting...");
}
function assignEvents() {
$(".card").click(function() {
//console.log("Card clicked");
if (!firstCard) {
firstCard = $(this);
firstCard.addClass("selected");
return;
}
if (!secondCard) {
secondCard = $(this);
secondCard.addClass("selected");
}
compareAndMove(firstCard, secondCard);
firstCard = null;
secondCard = null;
});
}
.card {
width: 50px;
height: 50px;
border-radius: 10px;
border: 1px solid black;
display: inline-block;
text-align: center;
margin: 5px;
}
.selected {
border: 3px solid black;
}
body {
background-color: #ABCDEF;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<html>
<body>
<div id="squaresParent"></div>
</body>
</html>
I think you are looking for something like this..
var currentCard = $(".cards").first();
var currentCardInd = $(currentCard).attr("index");
$(".cards").on("click", function(event){
if(currentCard && parseInt(currentCardInd) < parseInt($(this).attr("index"))){
currentCard.attr("index", $(this).attr("index"));
$(this).attr("index", currentCardInd.toString());
$(this).swapWith(currentCard);
currentCard = $(".cards[index='"+$(this).attr("index")+"']").next();
currentCardInd = $(currentCard).attr("index");
}
});
jQuery.fn.swapWith = function(_with) {
return this.each(function() {
var copyWith = $(_with).clone(true);
var copyOrig = $(this).clone(true);
$(_with).replaceWith(copyOrig);
$(this).replaceWith(copyWith);
});
};
.cards{
padding:10px;
background-color:lightblue;
display:inline-block;
cursor:pointer;
border-radius:5px;
}
#card-7S{
background-color:lightgreen;
}
#card-9D{
background-color:lightyellow;
}
#card-8H{
background-color:lightgray;
}
#card-3D{
background-color:lightpink;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="main">
<div id="card-2d" class="cards" index="2">2D</div>
<div id="card-7S" class="cards" index="4">7S</div>
<div id="card-9D" class="cards" index="7">9D</div>
<div id="card-8H" class="cards" index="10">8H</div>
<div id="card-3D" class="cards" index="15">3D</div>
</div>
You can also check here..
https://jsfiddle.net/nimittshah/7z3y8mb5/
Array.from is the canonical way to get an array of elements
<div class="card" data-value="38">
<img class="front-face" src="PNG/QH.png"/>
</div>
<div class="card" data-value="39">
<img class="front-face" src="PNG/KH.png"/>
</div>
<script>
const [first, second] = Array.from(document.querySelectorAll('.card'))
if (first.dataset.value === second.dataset.value) {
/* do your thing... */
}
</script>
The problem with the code is that querySelectorAll() returns a NodeList which behave as an array but it is not really an array.
The same problem happens with getElementsByClassName() this one return an HTMLCollection which behave as an array but does not include all the prototypes functionalities since it is not really an array.
So you have several options to get the index, after getting the index you can get the element that is before it.
Use call or apply to trick the Array methods
`Array.prototype.indexOf.call(cards, second)`
Iterate manually
`let selectedIndex = 0;
for(let i =0; i < cards.length; i++){
if(cards[i] === second){
selectedIndex = i;
}
};
console.log(selectedIndex)`
Create an array using cards NodeList
const cards = document.querySelectorAll('.card');
const cardsArray = Array.from(cards)
if(firstCard.dataset.value ===
cardsArray[cardsArray.indexOf(secondCard)-1].dataset.value)
Use any library to select the element that returns an array, as jQuery
Related
I am making a multiple choice quiz game and want what the user clicked to change to either red or green depending on if that answer is correct or incorrect. I made a variable called selected which is what the user pressed- this does correctly update. I have also got all of the v-for items to change to the same colour depending on if the answer is correct or not, I only need help separating it so that only one of the v-for things change colour.
Here is my relative HTML:
<button type="button" class="btn" class="answer" v-for="option in options" #click="checkAnswer(option)" #click="selected = option" :style="{backgroundColor: colour}">
{{option}}<br/>
</button>
<button type="button" #click="getQ" #click="shuffle(options)" class="btn button next">Next</button>
Here is the relative JS:
let colour = Vue.ref('');
let selected = Vue.ref('');
let options = Vue.ref([correctAnswer, incorrectAnswerOne, incorrectAnswerTwo, incorrectAnswerThree]);
// Methods
let shuffle = function(options) {
let num = options.length, t, raInt;
//while there are remaining elements to shuffle
while (num) {
//choose random
raInt = Math.floor(Math.random() * num--);
//swap with current element
t = options[num];
options[num] = options[raInt];
options[raInt] = t;
}
return options;
};
let checkAnswer = function(clicked) {
console.log(clicked.value);
console.log(correctAnswer.value);
if (clicked.value == correctAnswer.value) { // checks if the button that was clicked is the same as the answers value
this.result = "Correct!"; //if it does, result changes to Correct!
this.colour = "green";
} else {
this.result = "Incorrect!"; //if the answer is incorrect, result changes to Incorrect!
this.colour = "red";
};
};
And here is some CSS:
.answer {
width: 100%;
background-color: #dbdbdb;
padding: 4% 2%;
margin: 1 0;
}
.answer:hover {
background-color: #c2c2c2
}
I haven’t really tried that much. I’m not sure what to try. In a different project I did style a different div based on what other div was selected, but I am not sure how to change just one part of a v-for, or if it is even possible.
Thanks in advance
You can set condition for showing color style:
const { ref, computed } = Vue
const app = Vue.createApp({
setup() {
let correctAnswer = 3
let incorrectAnswerOne = 1
let incorrectAnswerTwo = 2
let incorrectAnswerThree = 4
let colour = ref('');
let selected = ref('');
let options = ref([correctAnswer, incorrectAnswerOne, incorrectAnswerTwo, incorrectAnswerThree]);
let shuffled = ref([])
let shuffle = (array) => {
selected.value = null
let currentIndex = array.length, randomIndex;
while (currentIndex != 0) {
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex--;
[array[currentIndex], array[randomIndex]] = [
array[randomIndex], array[currentIndex]];
}
shuffled.value = array;
};
shuffle(options.value)
let checkAnswer = function(clicked) {
// 👇 set selected
selected.value = clicked
if (clicked == correctAnswer) {
this.result = "Correct!";
this.colour = "green";
} else {
this.result = "Incorrect!";
this.colour = "red";
};
};
return { colour, selected, options, shuffle, checkAnswer, shuffled }
},
})
app.mount('#demo')
.answer {
width: 100%;
background-color: #dbdbdb;
padding: .5em 2em;
margin: 1 0;
}
.answer:hover {
background-color: #c2c2c2
}
.btns {
display: flex;
}
<script src="https://unpkg.com/vue#3/dist/vue.global.prod.js"></script>
<div id="demo">
<div class="btns">
<div v-for="(option, i) in shuffled" :key="i" >
<!-- 👇 condition -->
<button class="answer" #click="checkAnswer(option)" :style="selected == option && {backgroundColor: colour}">
{{option}}<br/>
</button>
</div>
</div>
<button type="button" #click="getQ, shuffle(options)" class="btn button next">Next</button>
</div>
I browsed thru various similar questions, but I found nowhere real help on my problem. There are some Jquery examples, but none of them weren't applicable, since I want to do it by vanilla JavaScript only.
The Problem
I have rating widget which I want to build like every time I click on "p" element, eventListener adds class "good" on all p elements before and on the clicked one, and remove class good on all that are coming after the clicked one.
My Thoughts
I tried to select all the "p" elements and iterate over them by using a for loop to add class before and on clicked element, and to leave it unchanged or remove after, but somewhere I am doing it wrong, and it adds class only on clicked element not on all previous ones.
My Code
function rating () {
var paragraph = document.getElementsByTagName('p');
for (var i = 0; i < paragraph.length; i++) {
paragraph[i].addEventListener('click', function(e) {
e.target.className='good';
})
}
}
rating();
Result
Expected result is that every p element before the clicked one, including clicked one should be having class good after click and all the ones that are after the clicked one, should have no classes.
Actual Result: Only clicked element is having class good.
Using Array#forEach , Element#nextElementSibling and Element#previousElementSibling
General logic behind this is to loop through all the previous and next sibling elements. For each element, add or remove the class .good until there are no more siblings to handle.
const ps = document.querySelectorAll('p');
ps.forEach(p => {
p.addEventListener("click", function() {
let next = this.nextElementSibling;
let prev = this;
while(prev !== null){
prev.classList.add("good");
prev = prev.previousElementSibling;
}
while(next !== null){
next.classList.remove("good");
next = next.nextElementSibling;
}
})
})
p.good {
background-color: red;
}
p.good::after {
content: ".good"
}
p {
background-color: lightgrey;
}
<div id='rating'>
<p>*</p>
<p>*</p>
<p>*</p>
<p>*</p>
<p>*</p>
</div>
Alternative:
Using Array#slice to get the previous and next group of p's.
const ps = document.querySelectorAll('p');
ps.forEach((p,i,list) => {
p.addEventListener("click", function() {
const arr = [...list];
const previous = arr.slice(0,i+1);
const next = arr.slice(i+1);
previous.forEach(pre=>{
pre.classList.add("good");
})
next.forEach(nex=>{
nex.classList.remove("good");
});
})
})
p.good {
background-color: red;
}
p.good::after {
content: ".good"
}
p {
background-color: lightgrey;
}
<div id='rating'>
<p>*</p>
<p>*</p>
<p>*</p>
<p>*</p>
<p>*</p>
</div>
function setup() {
var paragraph = document.querySelectorAll("p");
for (p of paragraph) {
p.onclick = (event) => {
let index = Array.from(paragraph).indexOf(event.target);
[].forEach.call(paragraph, function(el) {
el.classList.remove("good");
});
for (let i = 0; i <= index; i++) {
paragraph[i].classList.add("good");
}
}
}
}
//Example case
document.body.innerHTML = `
<div id='rating'>
<p>*</p>
<p>*</p>
<p>*</p>
<p>*</p>
<p>*</p>
</div>`;
setup();
The key ingredient is to use Node.compareDocumentPosition() to find out if an element precedes or follows another element:
var paragraphs;
function handleParagraphClick(e) {
this.classList.add('good');
paragraphs.forEach((paragraph) => {
if (paragraph === this) {
return;
}
const bitmask = this.compareDocumentPosition(paragraph);
if (bitmask & Node.DOCUMENT_POSITION_FOLLOWING) {
paragraph.classList.remove('good');
}
if (bitmask & Node.DOCUMENT_POSITION_PRECEDING) {
paragraph.classList.add('good');
}
});
}
function setup() {
paragraphs = [...document.getElementsByTagName('p')];
paragraphs.forEach((paragraph) => {
paragraph.addEventListener('click', handleParagraphClick);
});
}
setup();
#rating { display: flex; }
p { font-size: 32px; cursor: default; }
p:hover { background-color: #f0f0f0; }
.good { color: orange; }
<div id='rating'>
<p>*</p>
<p>*</p>
<p>*</p>
<p>*</p>
<p>*</p>
</div>`
Sorry if this is a silly question, but I'm making something for a site and can't figure this one out.
How can I make this div appear on the first button click, cycle through the array, then disappear after the last item in the array?
var myArray = ["Hello", "Thank you", "Goodbye"];
var myIndex = 1;
var print = document.getElementById('print');
print.innerHTML = myArray[0]; //Print first value of array right away.
function nextElement() {
print.innerHTML = myArray[myIndex++ % myArray.length];
};
#notfound {
background: #2abfffff;
padding: 19px;
margin: 15px;
color: #fff;
}
<div id="notfound">
<p><span id="print"></span>.</p>
</div>
<a id="click" href="#" onclick="nextElement();">Click</a>
JSfiddle: http://jsfiddle.net/jBJ3B/382/
Because you don't want the div to appear before the first click, remove the line with //Print first value of array right away..
One option is to start with an index of -1, make the element visible when the index is 0, and hide the element when the index is higher or equal to the length of the array:
var arr = ["Hello", "Thank you", "Goodbye"];
var index = -1;
var print = document.getElementById('print');
function nextElement() {
index++;
if (index >= arr.length) {
print.style.visibility = 'hidden';
return;
}
if (index === 0) print.style.visibility = 'visible';
print.textContent = arr[index];
}
#notfound {
background: #2abfffff;
padding: 19px;
margin: 15px;
color: #fff;
}
.print {
visibility: hidden;
}
<div id="notfound">
<p><span id="print"></span>.</p>
</div>
<a id="click" href="#" onclick="nextElement();">Click</a>
If you need the element to re-appear on further clicks, then use modulo to set index to -1 at the end:
var arr = ["Hello", "Thank you", "Goodbye"];
var index = -1;
var print = document.getElementById('print');
function nextElement() {
index++;
if (index >= arr.length) {
print.style.visibility = 'hidden';
index = -1;
return;
}
if (index === 0) print.style.visibility = 'visible';
print.textContent = arr[index];
}
#notfound {
background: #2abfffff;
padding: 19px;
margin: 15px;
color: #fff;
}
.print {
visibility: hidden;
}
<div id="notfound">
<p><span id="print"></span>.</p>
</div>
<a id="click" href="#" onclick="nextElement();">Click</a>
You can check inside nextElement() if that element was the last one, and then just hide the div.
function nextElement() {
print.innerHTML = myArray[myIndex++%myArray.length];
if(myIndex>myArray.length){
document.getElementById("notfound").style.visibility = "hidden";
}
};
JSFiddle: http://jsfiddle.net/jBJ3B/384/
Is it what you trying to do:http://jsfiddle.net/yvbenitah/jBJ3B/393/.
If yes only add that line:
document.getElementById('notfound').style.display = 'none';
So I'm building a a turn based board game which needs to contain 2 player that can move across the map. I'm stuck at getting the position of the player(which is just a simple div element) inside of that 2D array. I've tried using indexOf, but even tho it's placed inside an onclick function, always returns 0.
The html code contains just of few div's with col classes:
And here is the JavaScript code (btw it contains some unnecessary stuff that I've just added for test purposes) :
let row = document.querySelector('.row');
let fields = document.getElementsByClassName('col-md-2')
let fieldsArr = Array.from(fields);
let header = document.getElementById("clicked");
let cols = header.getElementsByClassName("col-md-2");
let player = document.getElementById('player');
let player2 = document.getElementById('player2');
let blockedField = document.getElementsByClassName('blocked');
fieldsArr.sort(function() {
return 0.5 - Math.random();
}).forEach(function(el) {
row.appendChild(el);
});
// ADD AN EVENT LISTENER AND LISTEN FOR COLS ID
function replyClick(e) {
e = e || window.event;
e = e.target || e.srcElement;
if (e.nodeName === 'DIV') {
let changable = e.id;
//console.log(changable);
}
}
// CREATE A 2D ARRAY (MAP)
var map = [];
while (fieldsArr.length) map.push(fieldsArr.splice(0, 6));
// ON CLICK ADD A CLASS OF ACTIVE
for (var i = 0; i < cols.length; i++) {
cols[i].addEventListener("click", function() {
var current = document.getElementsByClassName("active");
current[0].className = current[0].className.replace(" active", "");
this.className += " active";
});
}
// MOVE PLAYER ONE ACROSS THE MAP
function movePlayer(multWidth, multHeight) {
$(".active").append(player);
if ((row).click > multWidth) {
alert(1)
}
}
// MOVE PLAYER 2 ACROSS THE MAP
function movePlayer2() {
$(".active").append(player2);
}
// MAKE GRAYED OUT FIELD UNAVALIABLE AND SHOW AN ALERT
$(blockedField).css("pointer-events", "none");
// APPEND PLAYER1(2) TO THE FIRST(LAST) FIELD ON THE MAP
map[0][0].appendChild(player);
map[5][5].appendChild(player2);
// GET PLAYERS CURRENT POSITION
$(row).click(function() {
let current = player.offsetTop;
});
const widthAllowed = 3 * 156;
const heightAllowed = 3 * 146;
// LIMIT PLAYER MOVES
let player1Moves = 3;
player2Moves = 3;
$(row).click(function() {
movePlayer();
let remainingMoves = player1Moves -= 1;
if (remainingMoves === 0) {
alert("You don't have any more moves. Player's 2 turn.");
$(player).css("pointer-events", "none");
$(row).click(movePlayer2);
}
})
for (var x = 0; x < map.length; x++) {
for (var y = 0; y < map[x].length; y++) {
console.log(x, y);
}
}
console.log(map);
console.log(map[2][5]);
console.log(map[5][0]);
You should take some beginner jquery/javascript course, since your question is very simple and you will find the whole programming thing way easier with a few basic concepts (like selectors, events and callbacks)
That said, here is a basic example of how to return the div element that contains the player element and how to use event attachment instead of inline events.
let row = $('.row');
row.on('click', replyClick);
function replyClick(e) {
var targetRow = $(e.target);
$('.row > div.active').removeClass('active');
targetRow.addClass('active');
var player = $('.row div.player');
alert(player.parent().attr('id'));
};
.player {
width: 20px;
height: 20px;
background: red;
}
.row > div {
padding: 10px;
width: 20px;
height: 20px;
border: 1px solid red;
}
.row > div.active {
background: blue;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="row">
<div id="col1" class="col-md-2">
<div class="player"></div>
</div>
<div id="col2" class="col-md-2 blocked"></div>
<div id="col3" class="col-md-2 active"></div>
<div id="col4" class="col-md-2"></div>
</div>
</div>
Can Push() and Pop() and Image Replacement Work within an Array?
8th Gr math teacher attempting to create a slide show of question images that pop() and push() through an image array based on student responses. If the student answers correctly the question is popped, but if they answer incorrectly it is added to the end of the queue. Additionally, since deleting elements in the DOM is bad, I am replacing the current image's src and id with that of the next element in queue. The array is then popped and pushed along, but whenever I enter in the incorrect answer twice the same image appears.
I have moved the global variable that holds the array, domEls, inside of the function retrieveAnsForImage to force it to randomize the images in the array. When I do this, the images change correctly so I believe it is the push() and pop() commands.
I included a snippet that doesn't work here, but works like a champ in Notepad ++. I just took a crash course in Javascript, HTML and CSS last month on Codecademy, I am very new to this. Thank you for reading.
//Jquery
$(document).ready(function() {
$(function() {
$('img.card').on('contextmenu', function(e) {
e.preventDefault();
//alert(this.id);
openPrompt(this.id);
});
});
});
//Provide and Shuffle array function
function shuffleImgs() {
var imgArr = [
"image1",
"image2",
"image3",
"image4",
"image5",
"image6",
"image7",
"image8",
"image9"
];
var currentIndex = imgArr.length, temporaryValue, randomIndex;
// While there remain elements to shuffle...
while (0 !== currentIndex) {
// Pick a remaining element...
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex -= 1;
// And swap it with the current element.
temporaryValue = imgArr[currentIndex];
imgArr[currentIndex] = imgArr[randomIndex];
imgArr[randomIndex] = temporaryValue;
}
alert("shuffle");
return imgArr;
}
function arrStack() {
var imgArr = shuffleImgs();
//Map over the array to create Dom elements
var domElements = imgArr.map(function (imgName, index) {
var cardDiv = document.createElement('div');
var cardImage = document.createElement('img');
//Add img id and class
cardImage.id = imgName;
cardImage.classList.add('card');
//Set img source
cardImage.src = `images/${imgName}.jpg`;
//Put it all together
cardDiv.appendChild(cardImage);
return cardDiv;
});
//this notation to call nested function for Global var stack
this.nDomElements = function () {
stackDomEl = domElements;
return stackDomEl;
}
//Display last element in array
//this notation to call the nested function from outside the function
this.nDisplayLastArr = function displayLastArr() {
var lastImgArr = domElements[domElements.length - 1];
//alert(lastImgArr);
//Append the elements to the DOM
var modal = document.querySelector('div.modal');
modal.appendChild(lastImgArr);
return lastImgArr; //Use brackets when your are returning more than one variable
}
}
//Function called from Jquery to open prompt to answer question
function openPrompt(imageId) {
var userAns = prompt("Please enter your answer below and click OK");
if (userAns == null || userAns == "") {
alert("User cancelled the prompt. Exit and please try again!");
}
else {
/*Vain hope that I can pass imageId from click event through the user prompt
to the answer checking function retrieveAnsForImage*/
retrieveAnsForImage(imageId, userAns); //out of scope?
}
}
//Global variable
func = new arrStack();
window.domEls = func.nDomElements();
//Compare user responses with the question image by use of the click image id
function retrieveAnsForImage(imageId, userAns) {
//Change these variables to the correct answer whenever this website is reused in other assignments
var ansImage1 = "1";
var ansImage2 = "2";
var ansImage3 = "3";
var ansImage4 = "4";
var ansImage5 = "5";
var ansImage6 = "6";
var ansImage7 = "7";
var ansImage8 = "8";
var ansImage9 = "9";
//Give students a second chance to retry a question
//var hintCounter = 0; //include a while statement above the if statements to allow students a retry
/*Compare user response with correct case answer and correct clicked image.
Students may enter the right answer for the wrong image hence the &&.
Images will always be refered to as image1, image2, etc.*/
if (userAns === ansImage1 && imageId === "image1") {
correctAns(imageId);
}
else if (userAns === ansImage2 && imageId === "image2") {
correctAns(imageId);
}
else if (userAns === ansImage3 && imageId === "image3") {
correctAns(imageId);
}
else if (userAns === ansImage4 && imageId === "image4") {
correctAns(imageId);
}
else if (userAns === ansImage5 && imageId === "image5") {
correctAns(imageId);
}
else if (userAns === ansImage6 && imageId === "image6") {
correctAns(imageId);
}
else if (userAns === ansImage7 && imageId === "image7") {
correctAns(imageId);
}
else if (userAns === ansImage8 && imageId === "image8") {
correctAns(imageId);
}
else if (userAns === ansImage9 && imageId === "image9") {
correctAns(imageId);
}
else {
window.alert("Incorrect Answer");
incorrectAns();
}
function correctAns(){
//Second to last element in array
var SecLastElArr = domEls[domEls.length - 2];
//Pull image id from second to last element in array
var nextImgId = SecLastElArr.querySelector("div > img").id;
//Pull image id from document
var imgId = document.querySelector("div > img").id;
//Student incorrect answer change im
document.getElementById(imgId).src = `images/${nextImgId}.jpg`;
document.getElementById(imgId).id = nextImgId;
domEls.pop();
//Think about when the array is completely gone
//while domEls.length !== 0;
}
function incorrectAns(){
//Last element in array
var LastElArr = domEls[domEls.length - 1];
//Second to last element in array
var SecLastElArr = domEls[domEls.length - 2];
//Pull image id from second to last element in array
var nextImgId = SecLastElArr.querySelector("div > img").id;
//Pull image id from document
var imgId = document.querySelector("div > img").id;
//Student incorrect answer change image src and id to next element in queue
document.getElementById(imgId).src = `images/${nextImgId}.jpg`;
document.getElementById(imgId).id = nextImgId;
//Remove last element in array
domEls.pop();
//move the last element to the first element in the array for another attempt
domEls.push(LastElArr);
alert(domEls.length);
}
}
function overlay() {
var el = document.getElementById("overlay");
el.style.visibility = (el.style.visibility == "visible") ? "hidden" : "visible";
}
#overlay {
visibility: hidden;
position: absolute;
left: 0px;
top: 0px;
width:100%;
height:100%;
text-align:center;
z-index: 1000;
background-color: rgba(0,191, 255, 0.8);
}
#overlay div {
width:70%;
margin: 10% auto;
background-color: #fff;
border:1px solid #000;
padding:15px;
text-align: center;
}
body {
height:100%;
margin:0;
padding:0;
}
#close-img {
float: right;
clear: right;
width: 30px;
height: 30px;
bottom: 0;
right: 0;
}
<!DOCTYPE html>
<html>
<head>
<title></title>
<span> "Left click to view any questions. Right click (two finger tap) to answer the question and claim the tile. Each player must claim 4 tiles to successfully complete the assignment."</span>
<link href="https://fonts.googleapis.com/css?family=Oswald:300,700|Varela+Round" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="Stack Rnd Temp.css">-->
<script type="text/javascript" src="Stack Rnd Temp.js"></script>
<script src="jquery-3.2.1.min.js"></script>
<script type="text/javascript" src="StackRndTempjq.js"></script>
</head>
<body>
<div class="title">
<h1></h1>
</div>
<div id="gameboard"> <!--Container for all nine divs-->
<a href='#' onclick='overlay()'>Click here to show the overlay</a>
</div>
<div class="modal" id="overlay">
<p> "Right click to answer the question"</p>
<script>
func = new arrStack();
func.nDisplayLastArr();
</script>
<img src="images/close.png" id="close-img" onclick="overlay()">
</div>
</body>
</html>
Your issue is that pop removes the last element from the array while push adds the element to end of the array.
What you probably want to do is use shift to remove the the first element from the array and pop it back to the end if the answer is wrong.
Alternately, you could pop the last element and use unshift to insert back into the beginning of you want to work in the other direction.
Here's a quick mockup without images.
var currentTest = null;
function getTest() {
$('#answer').html("").hide();
if (tests.length > 0) {
currentTest = tests.shift(); // remove the first question
$('#question').fadeIn(450).html(currentTest.q);
return currentTest;
} else {
$('#answer').html("Finished").fadeIn(500);
$('#btnCorrect').unbind();
$('#btnWrong').unbind();
}
}
var tests = [];
for (var i = 0; i < 5; i++) {
var question = "Question " + i;
var answer = "Answer " + i;
tests.push({
q: question,
a: answer
});
}
$('#btnCorrect').click(function() {
$('#question').hide();
$('#answer').fadeIn(450).html("Correct!");
window.setTimeout(getTest, 750);
});
$('#btnWrong').click(function() {
$('#question').hide();
tests.push(currentTest); // put the question back in the array
$('#answer').fadeIn(450).html("Incorrect!");
window.setTimeout(getTest, 750);
});
$(document).ready(function() {
getTest();
})
* {
font-family: arial;
}
#panel {
height: 50px;
}
#answer {
border: 1px solid #cccccc;
background: #dedede;
width: 400px;
}
#question {
border: 1px solid #999999;
background: #dedede;
width: 400px;
}
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
</head>
<body>
<div id="panel">
<div id="answer"></div>
<div id="question"></div>
</div>
<input id="btnCorrect" value="Mock Correct Answer" type="button">
<input id="btnWrong" value="Mock Wrong Answer" type="button">
</body>
</html>