0

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>
Anoop H.N
  • 1,244
  • 1
  • 15
  • 31
mister
  • 37
  • 7

1 Answers1

1

Your issue is that pop removes the last element from the array while push adds the element to the end of the array.

What you probably want to do is use shift to remove the first element from the array and pop it back to the end if the answer is wrong.

Alternatively, you could pop the last element and use unshift to insert it back into the beginning if 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>
Ahmad Adibzad
  • 501
  • 2
  • 6
  • 14
Alexander Higgins
  • 6,765
  • 1
  • 23
  • 41
  • 1
    thank you, I couldn't see the forest for the trees. I was just adding elements right back where I took them off. Thank you also for the mock up. It simplified my code by 30 lines. – mister Jul 20 '17 at 23:03