<div class="container">
        <header class="">
            <div class="">
                <h1 id="title">Met Guess</h1>
            </div>
            <p id="about-the-game" class="">
            <!-- <span class="large">The game to test your knowlege of the Met Collection</span> -->
         <p style="background-color: red; padding: 10px;font-size: 120%">N.B. This is not the complete version of Met Guess, it is an example codepen to illustrate loading times and custom loading animation</p>
            </p>
      <p><a href="https://github.com/hariseldon27/met-museum-game" targer="_blank">Find the more or less finished game on GitHub here:
        https://github.com/hariseldon27/met-museum-game</a></p>
        </header>

        <div class="mx-auto"><!--container for the card-->
            <div id="card" class="">
                <div id="card-image-holder">
                    <img src="https://images.metmuseum.org/CRDImages/eg/original/DT563.jpg" id="main-image"> 
                </div><!--end card image holder-->
                <div id="gamepiece-holder" class="">
                        <ul id="game-pieces" class="">
                            <li class="game-option" id="objectID-1">Option 1</li>
                            <li class="game-option" id="objectID-2">Option 2</li>
                            <li class="game-option" id="objectID-3">Option 3</li>   
                        </ul><!--end of game choices-->
                </div>
                <div id="game-info-controls">
                    <div id="gamestats" class="">
                        Score: <span id="total-correct">0</span> correct /
                        <span id="total-questions">0</span> tries
                        <!-- <span class="" id="timeleft">Time Left: XX:XX</span> -->
                    </div>
                    <div class="gap-2 d-md-block" id="controls-holder">
                        <!-- <div id="score-skip" class=""> -->
                            <button id="skip" class="btn new-game-button btn-outline-dark">Next >></button>
                        <!-- </div> -->
                        <button role="button" id="new-game" type="button" class="btn new-game-button btn-outline-dark" data-bs-toggle="modal">
                            New Game!
                        </button>
                    </div>
                </div>
                <!-- <button role="button" type="button" class="btn btn" data-bs-toggle="modal" data-bs-target="#incorrectgit-popup">open wrong answ modal</button> -->
            </div>
            <!--end of card-->
        </div><!--end of card-->
        <div id="animated-loader" class="" style="">
            <svg id="mdot" data-name="m-dot" xmlns="http://www.w3.org/2000/svg" viewBox="-180 0 1200 1200">
                
                <path fill="white" stroke="none" d="M665.44,304.14v177.7q0,76.68,4.66,104.62t13.26,35.11q16.47,13.62,52.31,13.61l1.43,8.6h-192l1.43-8.6q35.1,0,51.59-12.89,13.6-10.75,15.76-70.22,1.44-23.66,1.44-70.23V178.75L414.66,636.62,207.57,249V480.41q0,71.65,6.81,103.54t21.86,41.56q15,9.68,50.15,9.67l1.44,8.6H111.56l1.43-8.6q26.51,0,39.77-3.94t22.57-21.14q9.3-17.19,11.82-45.85t2.51-83.84V304.86q0-55.17-2.51-83.84t-11.82-45.86Q166,158,152.76,154T113,150.09l-1.43-7.89h96L429,560,611.7,142.2H737.1l-1.43,7.89q-35.85,0-52.31,13.61Q665.44,178.75,665.44,304.14Z"   />
                <path fill="none" stroke="black" d="M665.44,304.14v177.7q0,76.68,4.66,104.62t13.26,35.11q16.47,13.62,52.31,13.61l1.43,8.6h-192l1.43-8.6q35.1,0,51.59-12.89,13.6-10.75,15.76-70.22,1.44-23.66,1.44-70.23V178.75L414.66,636.62,207.57,249V480.41q0,71.65,6.81,103.54t21.86,41.56q15,9.68,50.15,9.67l1.44,8.6H111.56l1.43-8.6q26.51,0,39.77-3.94t22.57-21.14q9.3-17.19,11.82-45.85t2.51-83.84V304.86q0-55.17-2.51-83.84t-11.82-45.86Q166,158,152.76,154T113,150.09l-1.43-7.89h96L429,560,611.7,142.2H737.1l-1.43,7.89q-35.85,0-52.31,13.61Q665.44,178.75,665.44,304.14Z"   />
                
                <circle r="45"  fill="red" >
                    <animateMotion dur="8s" repeatCount="indefinite" path="M665.44,304.14v177.7q0,76.68,4.66,104.62t13.26,35.11q16.47,13.62,52.31,13.61l1.43,8.6h-192l1.43-8.6q35.1,0,51.59-12.89,13.6-10.75,15.76-70.22,1.44-23.66,1.44-70.23V178.75L414.66,636.62,207.57,249V480.41q0,71.65,6.81,103.54t21.86,41.56q15,9.68,50.15,9.67l1.44,8.6H111.56l1.43-8.6q26.51,0,39.77-3.94t22.57-21.14q9.3-17.19,11.82-45.85t2.51-83.84V304.86q0-55.17-2.51-83.84t-11.82-45.86Q166,158,152.76,154T113,150.09l-1.43-7.89h96L429,560,611.7,142.2H737.1l-1.43,7.89q-35.85,0-52.31,13.61Q665.44,178.75,665.44,304.14Z"   />
                  </circle>
              </svg>
              <div class="loading" id="loading"></div>
          </div>
    </div> <!--end of our main body row-->

        
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>
html * {
  text-align: center;
}

.tiny {
  font-size: 50%;
}
.gigantic {

    font-size: 200%
}

html {
    position: relative;
    min-height: 100%;
}
body {
    margin: 0 0 40px;
}


/* media queries up top yo */

@media (max-width: 1000px){
    div#redheader {
        height:40px;
    }
    .tiny {
        font-size:45%;
    }
    .gigantic {
        font-size:120%
    }
    #cheekynote {
        font-size:70%
    }
    .footerleft{
        display: none;
    }
    #main-image,
    #correct-modal-object-image,
    #incorrect-modal-object-image {
        width: 20em;
    }
}
/* end large breakpoint */
@media (max-width: 768px){
    #met-header {
        display: none;
    }
    span#met-header-short {
        display: inline;
    }
    footer.footer span {
        display: none;
    }
    

} 
/* end medium breakpoint */

@media (max-width: 425px){
    div#redheader {
        height:30px;
    }
    .tiny {
        font-size:42%;
    }
    .gigantic {
        font-size:70%
    }
    #cheekynote {
        font-size:60%
    }
    img#welcome-image {
        width: 23vh;
    }
    #main-image,
    #correct-modal-object-image,
    #incorrect-modal-object-image {
        width: 15em;
    }
}
/* end small breakpoint */

/* main button stylez */
button#incorrect-modal-next-question-button,
button#correct-modal-next-question-button,
button#start-game-button,
button.next-button,
button.new-game-button {
    background: none;
    width: 12em;
    border: black solid 2px;
    padding: 7px;
    color: black;
}
button#incorrect-modal-next-question-button:hover,
button#correct-modal-next-question-button:hover,
button#start-game-button:hover,
button.next-button:hover,
button.new-game-button:hover,
li.game-option:hover {
    
    background-color: #e03;
    transition: 0.3s;
    border-style:inset;  
    border-color:transparent;
    color: white;
}
/* getting into the meat of it */

ul#game-pieces {
    display: inline-block;
    list-style: none;
    list-style-type: none;
    position:relative;
    float: none;
    text-align: center;
    padding: 0;
    margin: 0;
}
li.game-option {
    padding: 10px;
    position: relative;
    background: transparent;
    border: black solid 2px;
    border-radius: 4px;
    margin: 5px 5px 0px 5px;
    list-style: none;
}
li.game-option:hover {
  color: white;
}
#about-the-game {
  max-width: 40vh;
  position: relative;
  margin: auto;
}

#main-image {

    max-width: 40wh;
    max-height: 40vh;
    padding: 0 0 16 px 0;
}

#game-info-controls {
    position: relative;
    display: block;
}

#gamestats {
    background: none;
    border: black solid 2px;
    padding: 10px 15px 10px 15px ;
    color: black;
    margin: 5px;
    display: inline-block;
    border-radius: 40px;
    background: black;
    color: white;


}

.metred,
a.btn.metred {
  background: #e03;
  border-color: #e45;
}


a.btn.metred:hover {
    background: #e45;
    transition: 0.3s;
}

#redheader {
  height: 70px;
  background: #e03;
  z-index: 3000;
  color: white;
  text-align: left;
  font-size: x-large;
  margin-bottom: 25px;
}

#redheader p {
  text-align: left;
  padding: 0 15px 0;
}

#gamestats {
  margin: 0.5vh;
}

#title,
#met-header,
#met-header-short,
#welcome-card h4 {
  font-family: "Gilda Display", serif;
}
#met-header-short {
  display: none;
}

#indemnification {
  color: #444;
}

#card {

    padding: 18px 0 5px 0;
}


footer.footer {
    size: 2em;
    background: black;
    display: inline-block;
    left: 0;
    bottom: 0;
    width: 100%;
    height: 40px;
    position: absolute;
    bottom: 0;
    color: white;
    font-size: .8em
}
footer span{
    padding: 8px
}
span.footerleft {
    float: left;
}
span.footerright {
    float: right;
}



/* modal windows */
#welcome-image {
  width: 40vh;
}
#modal-object-image {

    width: 30vh;


}
#welcome-popup {
  background: #666;
}

#incorrectModalObjectDetails *, 
#correctModalObjectDetails * {
  text-align: left;
}
#correct-popup h6, 
#incorrect-popup h6 {
  background: #999;
}



#animated-loader{
    z-index: 997;
    position: fixed;
    z-index: 996;
    height: 20em;
    width: 20em;
    overflow: show;
    margin: auto;
    top: 0;
    left: 0;
    bottom: 0;
    right: 0;
    transition: 0.3s;
    display: none;
}
#loading {
    position: fixed;
    z-index: 996;
    height: 20em;
    width: 20em;
    overflow: show;
    margin: auto;
    top: 0;
    left: 0;
    bottom: 0;
    right: 0;
  }
  
  /* Transparent Overlay */
  #loading:after {
    content: '';
    display: block;
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background-color: rgba(0, 0, 0, 0.363);
  }

  
window.addEventListener("DOMContentLoaded", (event) => {
  console.log("DOM fully loaded and parsed");
  init();
});
//document selectors
const mainImage = document.getElementById("main-image");
const option1 = document.getElementById("objectID-1");
const option2 = document.getElementById("objectID-2");
const option3 = document.getElementById("objectID-3");
const nextButton = document.getElementById("skip");

const scoreEl = document.getElementById("scorekeeper");
const timeLeftEl = document.getElementById("timeleft");
const welcomePopupEl = document.getElementById("modal-holder");

const totalCorrectScore = document.getElementById("total-correct");
const totalQuestionsScore = document.getElementById("total-questions");

const newGameButton = document.getElementById("new-game");


//event listeners
option1.addEventListener("click", winLogic);
option2.addEventListener("click", winLogic);
option3.addEventListener("click", winLogic);

newGameButton.addEventListener("click", function (e) {
  e.preventDefault();
  reset();
  totalQuestionsScore.textContent = 0;
  totalCorrectScore.textContent = 0;
  correctAnswers = 0;
  totalQuestions = 0;
});
nextButton.addEventListener("click", function (e) {
  e.preventDefault();
  reset();
  totalQuestions++;
  totalQuestionsScore.textContent = totalQuestions;
});


let correctAnswers = 0;
let totalQuestions = 0;

function init() {
  goSearch();
}

const baseSearchParam =
  "https://collectionapi.metmuseum.org/public/collection/v1/search?medium=Paintings&q=cat&department=13";

//returned value is no lower than (and may possibly equal) min, and is less than (and not equal) max.
function randomNum(min, max) {
  return Math.floor(Math.random() * (max - min) + min);
}

function goSearch(searchTerm) {
  fetch(baseSearchParam)
    .then((res) => res.json())
    .then((data) => searchResults(data));
}

//this is the object that will store our game options
//first the objectID is filled from picking three random numbers from our search-set
//then the artist value should be filled in by a second fetch call to each of the relevant objects
const gameOptions = {
  option1: {
    objectID: 01,
    artist: "a",
    title: "title",
    year: 0000,
    image: "url",
  },
  option2: {
    objectID: 02,
    artist: "b",
    title: "title",
    year: 0000,
    image: "url",
  },
  option3: {
    objectID: 03,
    artist: "c",
    title: "title",
    year: 0000,
    image: "url",
  },
  option4: {
    objectID: 04,
    artist: "d",
    title: "title",
    year: 0000,
    image: "url",
  },
  option5: {
    objectID: 05,
    artist: "e",
    title: "title",
    year: 0000,
    image: "url",
  },
};

//this is the object that will store our game options
//first the objectID is filled from picking three random numbers from our search-set
//then the artist value should be filled in by a second fetch call to each of the relevant objects

//build function that loops over gameOptions to check for blank strings
function checkMissingStringsInObject() {
  //console.log(gameOptions);
  for (const option in gameOptions) {
    if (gameOptions[option].artist === "") {
      gameOptions[option] = gameOptions.option4;
    } else if (gameOptions[option].artist === "Unidentified artist") {
      gameOptions[option] = gameOptions.option5;
    }
  }
  //console.log(gameOptions);
}

async function searchResults(data) {
  showSpinner()
  //this fills in our game pieces with randomly chosen objects
  for (let option in gameOptions) {
    gameOptions[option].objectID = data.objectIDs[randomNum(1, 800)];
    let objectToFind = gameOptions[option].objectID;
    //use our three objectIDs to then search for each object and gather data
    await fetch(
      `https://collectionapi.metmuseum.org/public/collection/v1/objects/${objectToFind}`
    )
      .then((resp) => resp.json())
      //next we set the artist name in our local object based on the info from the api
      .then((data) => {
        
        // this points to the gameOptions object, and for each option.artist in the object
        //it will set that param to data.artistDisplayName as it comes from the api
        gameOptions[option].artist = data.artistDisplayName;
        gameOptions[option].image = data.primaryImageSmall;
        gameOptions[option].title = data.title;
        gameOptions[option].year = data.objectEndDate;
      });
  }
  //run logic to check for empty strings
  checkMissingStringsInObject();
  initialLoad();
}
function randomizeWinnerOptions() {
  const randNum = Math.floor(Math.random() * (6 - 1) + 1);
  // console.log(randNum);
  for (let option in gameOptions) {
    if (option === `option${randNum}`) {
      gameOptions["correct"] = gameOptions[option];
    }
  }
}
// initialLoad populates DOM
async function initialLoad() {
  //set the id of each of the board pieces to match the input objectid
  option1.setAttribute("data-id", gameOptions.option1.objectID);
  option2.setAttribute("data-id", gameOptions.option2.objectID);
  option3.setAttribute("data-id", gameOptions.option3.objectID);
  //set the text on the game pieces
  option1.textContent = gameOptions.option1.artist;
  option2.textContent = gameOptions.option2.artist;
  option3.textContent = gameOptions.option3.artist;
  //below randomly chooses from the three existing options to choose a winner and make a new obj
  randomizeWinnerOptions();
  //the below attribute won't work if we don't fire randomizeWinnerOptions first
  mainImage.setAttribute("data-id", gameOptions.correct.objectID);
  mainImage.src = gameOptions.correct.image;
  hideSpinner()
}

// winner logic- add to event listeners on option buttons
function winLogic() {
  //see if data-id matches mainImage.dat-id
  if (this.getAttribute("data-id") === mainImage.getAttribute("data-id")) {
    console.log("correct!");
    correctAnswers++;
    totalQuestions++;
    totalCorrectScore.textContent = correctAnswers;
    totalQuestionsScore.textContent = totalQuestions;
    // openModalWindow()
    reset();
  } else {
    console.log("wrong!");

    totalQuestions++;
    totalQuestionsScore.textContent = totalQuestions;
    // openModalWindow()
    reset();
  }
}
//reset the game board (currently just clears, will need to fire goSearch again)
const reset = () => {
  option1.setAttribute("data-id", "");
  option2.setAttribute("data-id", "");
  option3.setAttribute("data-id", "");
  mainImage.setAttribute("data-id", "");
  goSearch();
};



// animated popup 
const loadingEl = document.getElementById('animated-loader')


function showSpinner() {
    
        loadingEl.style.display = "block";
        console.log("showspinner")
   
}

function hideSpinner() {
  loadingEl.style.display = "none";
  console.log("hidespinner")
}

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.