skip to Main Content

I created a cardArray to hold card objecct. then loop through the cardArray to create images as cards. I am appending the grid div to hold the card images as children. then I have an event listener for the shuffle button. I cannot get the cards to load into the grid.

<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">    
<title>Shuffle Picture Cards</title>
<script>

//create cards
const cardArray =[
{name:'bass',
img:'images/bass.png'},
{name:'bass',
img:'images/bass.png'},
{name:'burger',
img:'images/burger.png'},
{name:'burger',
img:'images/burger.png'},
{name:'jamaica',
img:'images/jamaica.png'},
{name:'jamaica',
img:'images/jamaica.png'},
{name:'mbappe',
img:'images/mbappe.png'},
{name:'mbappe',
img:'images/mbappe.png'},
{name:'napali',
img:'images/napali.png'},
{name:"napali",
img:'images/napali.png'},
{name:'racecar',
img:'images/racecar.png'},
{name:'racecar',
img:'images/racecar.png'},
]

//shuffle card array
cardArray.sort(() => 0.5 - Math.random())

//shuffle from shfl-btn
const shuffle = document.getElementById('shfl-btn');

//eventListener for click on shuffle button
shuffle.addEventListener('click', createBoard);

//get grid
const grid = document.querySelector('.grid');

//create cards board
function createBoard() {
for(let i=0; i < cardArray.length; i++) {
    var card = document.createElement('img')
    card.setAttribute('src', 'images/astart.png')
    //card.setAttribute('data-id', i)
    //card.addEventListener('click', flipCard)
    grid.appendChild(card)
}
createBoard();
}


</script>
<style>
body{
    box-sizing: border-box;
    align-items: center;
}
img{
    height:100px;
    width:100px
}

button{
    padding:10px;
    width:80px;
    border:solid black 2px;
    border-radius:4px;
    cursor:pointer;        
    margin-top:20px;
}
    
        
.grid{
    height:300px;
    width:400px;
    border:solid blue 4px;
    display: flex;
    flex-wrap: wrap;
    flex-direction: row;
    margin:0 auto;
    border-radius: 10px;
}

.shfl-btn{
    align-items: center;
    margin:0 auto;
    width:400px;    
}
.shuffle{
    margin-left:160px;
    
}
</style>
</head>
<body>
<h1>Shuffle picture cards</h1>
<div class="grid" id="grid">     
</div>

<div class="shfl-btn"><button class="shuffle">shuffle</button></div>

</body>
</html>

I created a cardArray to hold card objecct. then loop through the cardArray to create images as cards. I am appending the grid div to hold the card images as children. then I have an event listener for the shuffle button. I cannot get the cards to load into the grid.

I am expecting the cards to load vua the createBoard function and to shuffle when shuffle button is clicked.

2

Answers


  1. First of all, your shuffle button’s event listener is isn’t working as I can see in this line:

    //shuffle from shfl-btn
    const shuffle = document.getElementById('shfl-btn');
    

    … you are trying to get the button element using the ID shfl-btn but I can see in the HTML code on this line:

    <div class="shfl-btn"><button class="shuffle">shuffle</button></div>
    

    … you have the shfl-btn as the class, so therefore adding id="shfl-btn", would fix it.


    //create cards board
    function createBoard() {
    for(let i=0; i < cardArray.length; i++) {
        var card = document.createElement('img')
        card.setAttribute('src', 'images/astart.png')
        //card.setAttribute('data-id', i)
        //card.addEventListener('click', flipCard)
        grid.appendChild(card)
    }
    createBoard(); // <--- Here
    }
    

    I see here in this function, you are calling createBoard() repeatedly, like an endless loop, so calling it only once outside the function would stop it from looping over and over again.


    And will also mention that adding these two lines inside the top of the createBoard() function would help get rid of the following problems:

    grid.innerHTML = ""; // Remove all the images from the grid before appending new ones.
    cardArray.sort(() => 0.5 - Math.random()); // Shuffle it each time createBoard function is called.
    

    Edit

    I see that the pictures aren’t loading… Well its because on this line in the for loop:

    card.setAttribute('src', 'images/astart.png');
    

    …you are setting each of the card’s src attribute to ‘images/astart.png’ which is not the same as the src values in the cardArray.

    So to get and set each the image links to each of src attributes, we use these line instead:

    card.setAttribute('src', cardArray[i]['img']);
    

    …which would get the value of ‘img‘ in each of cards in the cardArray.

    Login or Signup to reply.
  2. Here is another way of shuffling your cards.

    //create cards
    const cardArray = [{name:'bass',img:'https://picsum.photos/200'},{name:'bass',img:'https://picsum.photos/201'},{name:'burger',img:'https://picsum.photos/202'},{name:'burger',img:'https://picsum.photos/203'},{name:'jamaica',img:'https://picsum.photos/204'},{name:'jamaica',img:'https://picsum.photos/205'},{name:'mbappe',img:'https://picsum.photos/206'},{name:'mbappe',img:'https://picsum.photos/207'},{name:'napali',img:'https://picsum.photos/208'},{name:"napali",img:'https://picsum.photos/209'},{name:'racecar',img:'https://picsum.photos/210'},{name:'racecar',img:'https://picsum.photos/211'}];
    //shuffle from shfl-btn
    document.getElementById('shfl-btn').addEventListener('click', createBoard);
    const grid = document.querySelector('.grid');
    
    // Durstenfeld shuffle
    // https://medium.com/@anthonyfuentes/do-the-shuffle-the-durstenfeld-shuffle-7920c2ce0c45
    function shfl(a){
     for(let j,i=a.length;i>1;){
      j=Math.floor(Math.random()*i--);
      if (i!=j) [a[i],a[j]]=[a[j],a[i]]
     }
     return a
    }
    //create cards board
    function createBoard() {
      grid.innerHTML=shfl(cardArray).map(c=>`<img src="${c.img}" title="${c.name}">`).join("");
    }
    createBoard();
    body {
      box-sizing: border-box;
      align-items: center;
    }
    
    img {
      height: 100px;
      width: 100px
    }
    
    button {
      padding: 10px;
      width: 80px;
      border: solid black 2px;
      border-radius: 4px;
      cursor: pointer;
      margin-top: 20px;
    }
    
    .grid {
      height: 300px;
      width: 400px;
      border: solid blue 4px;
      display: flex;
      flex-wrap: wrap;
      flex-direction: row;
      margin: 0 auto;
      border-radius: 10px;
    }
    
    .shfl-btn {
      align-items: center;
      margin: 0 auto;
      width: 400px;
    }
    
    .shuffle {
      margin-left: 160px;
    }
    <h1>Shuffle picture cards</h1>
    <div class="grid" id="grid"></div>
    <div class="shfl-btn"><button class="shuffle" id="shfl-btn">shuffle</button></div>

    In my snippet I create the whole HTML of the grid in one go and apply it to the grid DOM element with a single .innerHTML assignment. This is very efficient as the jtml parsing will be done only once.

    I also used a different shuffling algorithm (Durstenfeld, a variation of the Fisher-Yates shuffle).

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search