HTML preprocessors can make writing HTML more powerful or convenient. For instance, Markdown is designed to be easier to write and read for text documents and you could write a loop in Pug.
In CodePen, whatever you write in the HTML editor is what goes within the <body>
tags in a basic HTML5 template. So you don't have access to higher-up elements like the <html>
tag. If you want to add classes there that can affect the whole document, this is the place to do it.
In CodePen, whatever you write in the HTML editor is what goes within the <body>
tags in a basic HTML5 template. If you need things in the <head>
of the document, put that code here.
The resource you are linking to is using the 'http' protocol, which may not work when the browser is using https.
CSS preprocessors help make authoring CSS easier. All of them offer things like variables and mixins to provide convenient abstractions.
It's a common practice to apply CSS to a page that styles elements such that they are consistent across all browsers. We offer two of the most popular choices: normalize.css and a reset. Or, choose Neither and nothing will be applied.
To get the best cross-browser support, it is a common practice to apply vendor prefixes to CSS properties and values that require them to work. For instance -webkit-
or -moz-
.
We offer two popular choices: Autoprefixer (which processes your CSS server-side) and -prefix-free (which applies prefixes via a script, client-side).
Any URLs added here will be added as <link>
s in order, and before the CSS in the editor. You can use the CSS from another Pen by using its URL and the proper URL extension.
You can apply CSS to your Pen from any stylesheet on the web. Just put a URL to it here and we'll apply it, in the order you have them, before the CSS in the Pen itself.
You can also link to another Pen here (use the .css
URL Extension) and we'll pull the CSS from that Pen and include it. If it's using a matching preprocessor, use the appropriate URL Extension and we'll combine the code before preprocessing, so you can use the linked Pen as a true dependency.
JavaScript preprocessors can help make authoring JavaScript easier and more convenient.
Babel includes JSX processing.
Any URL's added here will be added as <script>
s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.
You can apply a script from anywhere on the web to your Pen. Just put a URL to it here and we'll add it, in the order you have them, before the JavaScript in the Pen itself.
If the script you link to has the file extension of a preprocessor, we'll attempt to process it before applying.
You can also link to another Pen here, and we'll pull the JavaScript from that Pen and include it. If it's using a matching preprocessor, we'll combine the code before preprocessing, so you can use the linked Pen as a true dependency.
Search for and use JavaScript packages from npm here. By selecting a package, an import
statement will be added to the top of the JavaScript editor for this package.
Using packages here is powered by esm.sh, which makes packages from npm not only available on a CDN, but prepares them for native JavaScript ESM usage.
All packages are different, so refer to their docs for how they work.
If you're using React / ReactDOM, make sure to turn on Babel for the JSX processing.
If active, Pens will autosave every 30 seconds after being saved once.
If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.
If enabled, your code will be formatted when you actively save your Pen. Note: your code becomes un-folded during formatting.
Visit your global Editor Settings.
<!-- Images used were originally pulled form various creators at https://www.pexels.com/ -->
<!-- These images were uploaded at different dimensions to twitter, and then sourced from the following Twitter thread: https://twitter.com/coovercode/status/1515376340224167941 -->
<!-- Used as an underlay for the Nothing Selected Notice; prevents the rest of the application from functioing until the user closes the notice -->
<div id="Shadow-Panel" class="shadow-panel hidden"></div>
<header>
<div class="header-content-wrap">
<h1>Quizapalooza</h1>
<h2>Online Quiz Web Application</h2>
</div>
</header>
<main>
<article>
<h2 class="quiz-title hidden">eCommerce Quiz</h2>
<section id="Start-Menu" class="menu hidden active-panel">
<div class="menu-content-wrap">
<h3 id="Menu-h3">eCommerce Quiz</h3>
<p>You are about to take a three question quiz on eCommerce. You will have two minutes to complete the quiz. Excellence is mandatory; wrong answers will restart your quiz, however, your timer will continue to count down. You may retake the quiz as many times as you like. Press "Start" to begin.</p>
</div>
</section>
<section id="Failed-Menu-Answer" class="fail-notice hidden">
<div class="menu-content-wrap">
<h3 id="Menu-h3">Test Failed: Wrong Answer</h3>
<p>I'm sorry, but sadly you have selected a wrong answer and failed the test. As a reminder, excellence is mandatory, and so you will have to restart to continue the test. Press the Quit Button to return to the Main Menu or press Retry to further test your excellence.</p>
</div>
</section>
<section id="Failed-Menu-Time" class="fail-notice hidden">
<div class="menu-content-wrap">
<h3 id="Menu-h3">Test Failed: Timed Out</h3>
<p>I'm sorry, but sadly you have run out of time and failed the test. As a reminder, excellence is mandatory, and so you will have to restart to retake the test. Press the Quit Button to return to the Main Menu or press Retry once again test your excellence.</p>
</div>
</section>
<section id="Nothing-Selected-Notice" class="error-notice hidden">
<div class="menu-content-wrap">
<h3 id="Menu-h3">Nothing Was Selected</h3>
<p>With the goal of excellence in mind, you must select an answer to continue.</p>
<input id="Close-Button" type="submit" value="Close" name="Close">
</div>
</section>
<section id="Quitting-Pug" class="quitting-pug hidden">
<div class="menu-content-wrap hidden">
<p id="It-Me-Paragraph">hello. it me.</p>
<img id="Quitting-Pug-Small" class="puppies-small hidden quitting-pug-small" src="https://pbs.twimg.com/media/FQe5bU3WQAgBmBc?format=jpg&name=small" alt="A sad-looking pug puppy with black fur; its eyes watering as they look up towards the camera with a frowning face.">
<img id="Quitting-Pug-Medium" class="puppies-small hidden quitting-pug-medium" src="https://pbs.twimg.com/media/FQe_HZfXMAYQRty?format=jpg&name=small" alt="A sad-looking pug puppy with black fur; its eyes watering as they look up towards the camera with a frowning face.">
<p class="small-paragraph">i was wondering if after all these puppy years, you'd like to retry. dat way i not need say hello from da other side...</p>
</div>
</section>
<section id="Question-One" class="question hidden">
<h3>Question 1 of 3</h3>
<form action="">
<h4>Which of the following is not a real eCommerce platform?</h4>
<div class="radio-button-wrapper">
<input class="wrong-answer answer" type="radio" id="Shopify" name="real-eCommerce-platform" value="Shopify">
<label for="Shopify">Shopify</label><br>
</div>
<div class="radio-button-wrapper">
<input class="wrong-answer answer" type="radio" id="WooCommerce" name="real-eCommerce-platform" value="WooCommerce">
<label for="WooCommerce">WooCommerce</label><br>
</div>
<div class="radio-button-wrapper">
<input class="correct-answer answer" type="radio" id="ShopCommerce" name="real-eCommerce-platform" value="ShopCommerce">
<label for="ShopCommerce">ShopCommerce</label><br>
</div>
<div class="radio-button-wrapper">
<input class="wrong-answer answer" type="radio" id="BigCommerce" name="real-eCommerce-platform" value="BigCommerce">
<label for="BigCommerce">BigCommerce</label><br>
</div>
</form>
</section>
<section id="Question-Two" class="question hidden">
<h3>Question 2 of 3</h3>
<form action="">
<h4>If Shopify is so good, why are Shopify developers necessary?</h4>
<div class="radio-button-wrapper">
<input class="wrong-answer answer" type="radio" id="To_Save" name="why-shopify-devs" value="To_Save">
<label for="To_Save">To save time on things like store setups and migrations</label><br>
</div>
<div class="radio-button-wrapper">
<input class="wrong-answer answer" type="radio" id="To_Extend" name="why-shopify-devs" value="To_Extend">
<label for="To_Extend">To extend the limited design options and functionalities of themes with custom code</label><br>
</div>
<div class="radio-button-wrapper">
<input class="wrong-answer answer" type="radio" id="To_Provide" name="why-shopify-devs" value="To_Provide">
<label for="To_Provide">To provide support with a deep understanding of how the platform works and what its limitations are</label><br>
</div>
<div class="radio-button-wrapper">
<input class="correct-answer answer" type="radio" id="All_Above" name="why-shopify-devs" value="All_Above">
<label for="All_Above">All the above</label><br>
</div>
</form>
</section>
<section id="Question-Three" class="question hidden">
<h3>Question 3 of 3</h3>
<form action="">
<h4>Which of the following is true about Shopify developers?</h4>
<div class="radio-button-wrapper">
<input class="wrong-answer answer" type="radio" id="Paid_Well" name="true-shopify-devs" value="Paid_Well">
<label for="Paid_Well">They are paid extremely well</label><br>
</div>
<div class="radio-button-wrapper">
<input class="wrong-answer answer" type="radio" id="High_Demand" name="true-shopify-devs" value="High_Demand">
<label for="High_Demand">There is a high demand for them</label><br>
</div>
<div class="radio-button-wrapper">
<input class="wrong-answer answer" type="radio" id="Need_Know" name="true-shopify-devs" value="Need_Know">
<label for="Need_Know">They need to know web development, the platform itself, and the liquid template language</label><br>
</div>
<div class="radio-button-wrapper">
<input class="correct-answer answer" type="radio" id="All_Above_2" name="true-shopify-devs" value="All_Above_2">
<label for="All_Above_2">All the above</label><br>
</div>
</form>
</section>
<section id="You-Won" class="winner-panel hidden">
<h3 id="Menu-h3">Congratulations!</h3>
<p>You have achieved excellence! Now, please enjoy this image of cute puppies in celebration of your success!</p>
<!-- SMALL PUPPY IMAGES FOR SMALLER SCREEN SIZES -->
<img id="Shih-Tzu-Small" class="hidden puppies-small-img" src="https://pbs.twimg.com/media/FQez3GHXMAcQdlf?format=jpg&name=small" alt="Three Shih-Tzu puppies sitting cuddled together on a wooden board in a rustic house with a blue ball.">
<img id="Labradoodle-Small" class="hidden puppies-small-img" src="https://pbs.twimg.com/media/FQe0hHsX0AE7-9J?format=jpg&name=small" alt="Eleven blonde Labradoodle puppies are standing side-by-side in the bed of an old Chevrolet Truck, their front paws resting on the tailgate.">
<img id="Plott-Hound-Small" class="hidden puppies-small-img" src="https://pbs.twimg.com/media/FQe12jyXIAAOyTg?format=jpg&name=small" alt="On a lawn are three Plott Hound puppies sitting in a whisker basket, their heads resting over the edge of the basket.">
<img id="Siberian-Husky-Small" class="hidden puppies-small-img" src="https://pbs.twimg.com/media/FQe21UIXwAgPhSU?format=jpg&name=small" alt="Two Siberian Husky puppies are sitting outside against a stone-plaster brick wall; they have their mouths open and their eyes bright with excitement as they playfully bite at each other.">
<!-- MEDIUM PUPPY IMAGES FOR MEDIUM SCREEN SIZES -->
<img id="Shih-Tzu-Medium" class="hidden puppies-medium-img" src="https://pbs.twimg.com/media/FQe8_gPXEAUKjj1?format=jpg&name=small" alt="Three Shih-Tzu puppies sitting cuddled together on a wooden board in a rustic house with a blue ball.">
<img id="Labradoodle-Medium" class="hidden puppies-medium-img" src="https://pbs.twimg.com/media/FQe9jXNXwAgTmcc?format=jpg&name=small" alt="Eleven blonde Labradoodle puppies are standing side-by-side in the bed of an old Chevrolet Truck, their front paws resting on the tailgate.">
<img id="Plott-Hound-Medium" class="hidden puppies-medium-img" src="https://pbs.twimg.com/media/FQe9_G3WYAQ_W0f?format=jpg&name=small" alt="On a lawn are three Plott Hound puppies sitting in a whisker basket, their heads resting over the edge of the basket.">
<img id="Siberian-Husky-Medium" class="hidden puppies-medium-img" src="https://pbs.twimg.com/media/FQe-TukXIAANrEf?format=jpg&name=small" alt="Two Siberian Husky puppies are sitting outside against a stone-plaster brick wall; they have their mouths open and their eyes bright with excitement as they playfully bite at each other.">
<p class="small-paragraph">(Please play again for the opportunity to increase your daily dose of serotonin.)</p>
</section>
</article>
</main>
<footer>
<div id="Start-Button-Wrap" class="footer-content-wrap hidden active-panel">
<input id="Start-Button" type="submit" value="Start" name="Start">
</div>
<div id="Retry-Button-Wrap" class="footer-content-wrap hidden">
<input id="Retry-Button" type="submit" value="Retry" name="Main-Menu">
<input id="Quit-Button" type="submit" value="Quit" name="Quit-Button">
</div>
<div id="Quiz-Button-Wrap" class="footer-content-wrap hidden">
<input id="Next-Button" type="submit" value="Next ❯" name="Next">
<div class="container-timer">
<p id="Timer-Title">time left:</p>
<p id="timer">
<span id="timer-mins">02</span>
<span id="timer-colon"> : </span>
<span id="timer-secs">00</span>
</p>
</div>
</div>
<!-- FOR DEBUGGING -->
<!-- <div id="Add-All-Button-Wrap" class="footer-content-wrap hidden active-panel">
<input id="Add-All-Button" type="submit" value="Add All" name="Add-All">
</div> -->
</footer>
/* This CSS was created using SCSS/SASS */
/* Github source for project creation: https://github.com/nrcoover/quizapalooza-web-app */
@import url("https://fonts.googleapis.com/css2?family=Lato:ital,wght@0,100;0,300;0,400;0,700;0,900;1,100;1,300;1,400;1,700;1,900&display=swap");
*, *::before, *::after {
box-sizing: border-box;
border-style: none;
list-style: none;
margin: 0;
padding: 0;
text-decoration: none;
}
html, body {
font-family: "Lato", sans-serif;
font-size: 14px;
min-width: 100%;
width: 100%;
}
footer {
background-color: #3700B3;
bottom: 0;
box-shadow: -2px -2px 5px rgba(18, 18, 18, 0.3);
width: 100%;
}
#Start-Button-Wrap {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
#Quiz-Button-Wrap, #Retry-Button-Wrap {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
}
#Start-Button, #Next-Button, #Retry-Button, #Quit-Button, .container-timer {
font-size: 1.5rem;
line-height: 1.5rem;
margin: 0 0;
padding: 0 0;
background-color: #018786;
box-shadow: 0 0 5px rgba(18, 18, 18, 0.3);
border-radius: 5px;
color: #FFFFFF;
font-weight: 700;
height: 3.5rem;
text-align: center;
text-decoration: none;
width: 8rem;
}
#Timer-Title {
font-size: 0.8rem;
line-height: 0.8rem;
}
.container-timer {
margin: 0 0;
padding: 0 0;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background-color: #FFFFFF;
color: black;
height: 3.5rem;
}
.footer-content-wrap {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
height: auto;
margin: 0 auto;
max-width: 40rem;
padding: 2rem 2rem 3rem;
width: 100%;
}
header {
background-color: #6200EE;
box-shadow: 2px 2px 5px rgba(18, 18, 18, 0.3);
color: #FFFFFF;
width: 100%;
}
.header-content-wrap {
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: center;
height: auto;
padding: 2rem 0;
width: 100%;
}
body {
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: center;
font-size: 18px;
min-height: 100vh;
min-width: 330px;
}
main {
height: auto;
max-width: 40rem;
padding: 2rem;
width: 100%;
}
article {
position: relative;
}
h1, h2, h3, h4, p, label {
font-family: "Lato", sans-serif;
}
h1 {
font-size: 3.4rem;
line-height: 3.6rem;
margin-bottom: 0.35em;
}
h2 {
font-size: 1.6rem;
line-height: 1.8rem;
font-weight: 500;
margin-bottom: 0.4em;
}
h3 {
font-size: 1.2rem;
line-height: 1.4rem;
margin-bottom: 1rem;
}
h4 {
font-size: 1.4rem;
line-height: 1.6rem;
margin-bottom: 1rem;
}
p {
font-size: 1.3rem;
line-height: 1.6rem;
margin: 0 auto;
max-width: 45ch;
}
input, label {
font-size: 1.2rem;
line-height: 1.4rem;
font-family: "Lato", sans-serif;
margin-left: 1.2rem;
margin-bottom: 1.2rem;
max-width: 45ch;
}
input[type=radio] {
appearance: none;
min-width: 1rem;
width: 1rem;
height: 1rem;
border: 2px solid #3700B3;
border-radius: 100%;
}
input[type=radio]:checked {
background-color: #3700B3;
width: 1rem;
height: 1rem;
border-radius: 100%;
padding: 7px;
transform: translate(-2px, -2px);
}
input:hover {
cursor: pointer;
}
label {
margin-left: 0.5rem;
}
#Shadow-Panel {
background-color: rgba(0, 0, 0, 0.4);
height: 100%;
min-width: 330px;
position: absolute;
width: 100%;
z-index: 5;
}
#Start-Menu, #Nothing-Selected-Notice, #Failed-Menu-Answer, #Failed-Menu-Time, #Quitting-Pug {
background-color: #FFFFFF;
padding: 1rem;
border-radius: 15px;
box-shadow: 0 0 5px rgba(18, 18, 18, 0.3);
}
#Start-Menu p, #Nothing-Selected-Notice p, #Failed-Menu-Answer p, #Failed-Menu-Time p, #Quitting-Pug p {
text-align: justify;
}
#Nothing-Selected-Notice {
position: absolute;
bottom: 50%;
right: 50%;
transform: translate(50%, 50%);
max-width: 80%;
width: 100%;
z-index: 10;
}
#Nothing-Selected-Notice .menu-content-wrap {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
#Nothing-Selected-Notice input {
margin: 0 0;
padding: 0 0;
background-color: #018786;
border-radius: 5px;
box-shadow: 0 0 5px rgba(18, 18, 18, 0.3);
color: #FFFFFF;
font-weight: 700;
padding: 1rem;
margin-top: 1rem;
}
#Failed-Menu-Answer, #Failed-Menu-Time {
background-color: rgba(176, 0, 32, 0.4);
}
#Failed-Menu-Answer .menu-content-wrap, #Failed-Menu-Time .menu-content-wrap {
border: 3px solid #B00020;
background-color: rgba(176, 0, 32, 0.4);
color: #FFFFFF;
}
#Quitting-Pug {
position: relative;
padding-top: 2rem;
}
#Quitting-Pug .menu-content-wrap {
margin: 0 0;
padding: 0 0;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
border: none;
}
#Quitting-Pug #It-Me-Paragraph {
position: absolute;
top: 12.5%;
}
#Quitting-Pug img {
border: 3px solid #B00020;
border-radius: 8px;
max-height: 40rem;
max-width: 100%;
}
#Quitting-Pug .small-paragraph {
margin-top: 0.5rem;
}
#Menu-h3 {
text-align: center;
}
.small-paragraph {
font-size: 1rem;
line-height: 1.3rem;
}
.radio-button-wrapper {
display: flex;
flex-direction: row;
}
.menu-content-wrap {
background-color: #FFFFFF;
padding: 1.5rem;
border: 3px solid #018786;
border-radius: 8px;
}
.quiz-title {
font-size: 2rem;
line-height: 2.2rem;
font-weight: 900;
margin-bottom: 0.8em;
text-align: center;
}
.hidden {
display: none;
}
.active-panel {
display: block;
}
.winner-panel {
text-align: center;
}
.winner-panel img {
border-radius: 15px;
box-shadow: 2px 2px 8px rgba(18, 18, 18, 0.3);
margin: 1rem auto;
width: 100%;
}
.failure-background-color {
background-color: #B00020;
}
/* MEDIA QUERY TEMPLATE FROM https://www.w3schools.com/css/css_rwd_mediaqueries.asp */
/* Extra small devices (phones, 600px and down) */
@media only screen and (min-width: 460px) {
html, body {
background-color: #bdbdbd;
}
.question, .winner-panel {
background-color: #FFFFFF;
padding: 1rem;
border-radius: 15px;
box-shadow: 0 0 5px rgba(18, 18, 18, 0.3);
accent-color: #6200EE;
background: linear-gradient(#FFFFFF, #FFFFFF) padding-box, linear-gradient(to bottom, #6200EE, #3700B3) border-box;
border: 20px solid transparent;
border-radius: 25px;
padding: clamp(2rem, 1rem + 10vw, 3rem);
}
}
/* Extra large devices (large laptops and desktops, 1200px and up) */
@media only screen and (min-width: 1200px) {
body {
background-image: linear-gradient(to right, #FFFFFF, #bdbdbd, #bdbdbd, #bdbdbd, #bdbdbd, #bdbdbd, #FFFFFF);
}
}
// ********** GLOBAL VARIABLES DECLERATIONS **********
// light theme color global variables
const lightBase = '#bdbdbd';
const lightBackground = '#FFFFFF';
const lightShadow = 'rgba(18, 18, 18, .3)';
const lightPrimary = '#6200EE';
const lightPrimaryDark = '#3700B3';
const lightSecondary = '#03DAC6';
const lightSecondaryDark = '#018786';
const lightErrorColor = '#B00020';
// dark theme color global variables
const darkBase = '#1d1d1d';
const darkBackground = '#121212';
const darkShadow = 'rgba(255, 255, 255, .1)'
const darkPrimary = '#BB86FC';
const darkPrimaryDark = '#3700B3';
const darkSecondary = '#03DAC6';
const darkErrorColor = '#CF6679';
// html elements global variables
const headerHTML = document.querySelector('header');
const footerHTML = document.querySelector('footer');
const shadowPanel = document.getElementsByClassName('shadow-panel');
// menu global variables
const startMenu = document.querySelector('#Start-Menu');
const failedMenus = document.querySelectorAll('.fail-notice');
const failedMenuAnswer = document.querySelector('#Failed-Menu-Answer');
const failedMenuTime = document.querySelector('#Failed-Menu-Time');
const nothingSelectedNotice = document.querySelector('#Nothing-Selected-Notice');
const winnerPanel = document.querySelector('#You-Won');
const quittingPugPanel = document.getElementsByClassName('quitting-pug');
// button global variables
const startButton = document.querySelector('#Start-Button');
const nextButton = document.querySelector('#Next-Button');
const closeButton = document.querySelector('#Close-Button');
const retryButton = document.querySelector('#Retry-Button');
const quitButton = document.querySelector('#Quit-Button');
const currentButtonColor = lightSecondaryDark;
let quizIterationCount = 0;
// question collections global variables
const questions = document.getElementsByClassName('question');
const questionOne = document.querySelector('#Question-One');
const questionTwo = document.querySelector('#Question-Two');
const questionThree = document.querySelector('#Question-Three');
const questionOneForm = document.querySelector('#Question-One > form');
const questionTwoForm = document.querySelector('#Question-Two > form');
const questionThreeForm = document.querySelector('#Question-Three > form');
// answer collections global variables
const allAnswers = document.querySelectorAll('.answer');
const correctAnswers = document.getElementsByClassName('correct-answer');
const wrongAnswers = document.getElementsByClassName('wrong-answer');
const questionOneWrongAnswers = questionOneForm.querySelectorAll('.wrong-answer');
const questionTwoWrongAnswers = questionTwoForm.querySelectorAll('.wrong-answer');
const questionThreeWrongAnswers = questionThreeForm.querySelectorAll('.wrong-answer');
// footer panels global variables
const quizFooterElements = document.querySelector('#Quiz-Button-Wrap');
const startFooterElements = document.querySelector('#Start-Button-Wrap');
const menuFooterElements = document.querySelector('#Retry-Button-Wrap');
// timer global variables
const minutesCounter = document.getElementById("timer-mins");
const secondsCounter = document.getElementById("timer-secs");
// test completion and puppy images global variables
const puppiesSmall = document.getElementsByClassName('puppies-small-img');
const puppiesMedium = document.getElementsByClassName('puppies-medium-img');
const quittingPugSmall = document.getElementsByClassName('quitting-pug-small');
const quittingPugMedium = document.getElementsByClassName('quitting-pug-medium');
let testCompleted = false;
let testCompletedCounter = 0;
// ********** START VOID **********
startVoid();
// the above code line is necessary due to an unresolved bug that causes this element to be visible upon page load, but it shouldn't be visible until after the user presses the start button.
changeBackgroundColor();
// ********** FUNCTION DECLERATIONS **********
// function to start/reset the quiz starter screen
function startVoid() {
footerElementsInvisible(quizFooterElements);
footerElementsInvisible(menuFooterElements);
}
// function to remove .active-panel class from all question elements
function removeActiveQuestionClass() {
for (let question of questions) {
question.classList.remove('active-panel');
}
}
// function to remove .active-panel class from all failure menus
function removeActiveFailureMenuClass() {
for (let menu of failedMenus) {
menu.classList.remove('active-panel');
}
}
// function returns the id of the current active question
function checkForActiveQuestion() {
for (let question of questions) {
if (question.classList.contains('active-panel')) {
return question.id;
}
}
}
// function returns true if a wrong answer has been checked
function currentWrongAnswersChecked(currentWrongAnswers) {
for (let wrongAnswer of currentWrongAnswers) {
if (wrongAnswer.checked) {
return true;
}
}
}
// function to change footer & header background colors for failure message
function setFailureBackgroundColor() {
headerHTML.classList.add('failure-background-color');
footerHTML.classList.add('failure-background-color');
retryButton.style.backgroundColor = darkErrorColor;
quitButton.style.backgroundColor = darkErrorColor;
}
// function to remove footer & header background colors of failure message
function removeFailureBackgroundColor() {
headerHTML.classList.remove('failure-background-color');
footerHTML.classList.remove('failure-background-color');
retryButton.style.backgroundColor = currentButtonColor;
quitButton.style.backgroundColor = currentButtonColor;
}
// function to activate the appropriate failure menu or notice based on the state
function activateFailureMenu(failureMenu) {
switch (failureMenu) {
default:
nothingSelectedNotice.classList.add('active-panel');
shadowPanel[0].classList.remove('hidden');
break;
case failedMenuAnswer:
removeActiveQuestionClass();
failedMenuAnswer.classList.add('active-panel')
footerElementsInvisible(quizFooterElements);
footerElementsVisible(menuFooterElements);
setFailureBackgroundColor();
break;
case failedMenuTime:
removeActiveQuestionClass();
removeActiveFailureMenuClass();
failedMenuTime.classList.add('active-panel');
footerElementsInvisible(quizFooterElements);
footerElementsVisible(menuFooterElements);
setFailureBackgroundColor();
// removes Nothing-Selected-Panel in case times runs out during this notification sequence.
if (nothingSelectedNotice.classList.contains('active-panel')) {
removeNothingSelectedDisplay()
}
return quizIterationCount = 0;
}
}
// function to select which group of answers to pass througth the currentWrongAnswers function
function currentWrongAnswersCheckedSelector(questionNumberWrongAnswers) {
if (currentWrongAnswersChecked(questionNumberWrongAnswers)) {
activateFailureMenu(failedMenuAnswer);
} else {
activateFailureMenu();
}
}
// function to check if any wrong answer has been selected on the current question
function wrongAnswerChecked() {
let currentQuestion = checkForActiveQuestion();
// Selects only the group of wrong answers from the current question
switch (currentQuestion) {
case "Question-One":
currentWrongAnswersCheckedSelector(questionOneWrongAnswers);
break;
case "Question-Two":
currentWrongAnswersCheckedSelector(questionTwoWrongAnswers);
break;
case "Question-Three":
currentWrongAnswersCheckedSelector(questionThreeWrongAnswers);
break;
default:
activateFailureMenu();
break;
}
}
// function reverts checked value to false for all possible answers (even ones hidden by "display: none")
function deselectAllInputs() {
for (let answer of allAnswers) {
answer.checked = false;
}
}
// function to remove selected footerElements Group from visibility
function footerElementsInvisible(footerElements) {
switch(footerElements) {
default:
console.log("No Footer Elements Group was selected. Please review code and select appropriate grouping.")
case startFooterElements:
startFooterElements.classList.remove('active-panel');
startFooterElements.style.display = 'none';
break;
case quizFooterElements:
quizFooterElements.classList.remove('active-panel');
quizFooterElements.style.display = 'none';
break;
case menuFooterElements:
menuFooterElements.classList.remove('active-panel');
menuFooterElements.style.display = 'none';
break;
}
}
// function to return selected footerElements Group to visibility
function footerElementsVisible(visibilitySelector) {
switch(visibilitySelector) {
default:
console.log("No Footer Elements Group was selected. Please review code and select appropriate grouping.")
case startFooterElements:
startFooterElements.classList.add('active-panel');
startFooterElements.style.display = 'flex';
break;
case quizFooterElements:
quizFooterElements.classList.add('active-panel');
quizFooterElements.style.display = 'flex';
break;
case menuFooterElements:
menuFooterElements.classList.add('active-panel');
menuFooterElements.style.display = 'flex';
break;
}
}
// function creates a timer at the initialization of the quiz
function createTimer() {
if (quizIterationCount < 2) {
// Creates a two minute timer countdown
quitButton.addEventListener('click', function() {
clearInterval(timer);
minutesCounter.innerHTML = "02";
secondsCounter.innerHTML = "00";
});
let countDownTime = (new Date(Date.now()).getTime() + ((2 * 60000) + 1000));
// In practice, it has been taking 2 seconds for the timer to load and appear on screen, therefore, and extra second is added to allow for this latency (code seen in above line); the timer is hard-coded to start at 2 minutes in the HTML. Adjust the time will have to include adjusting the starting value in HTML.
const timer = setInterval(function() {
let currentTime = new Date(Date.now()).getTime();
let t = countDownTime - currentTime;
while (t > 0 && !testCompleted) {
let mins = Math.floor((t % (1000 * 60 * 60)) / (1000 * 60));
let secs = Math.floor((t % (1000 * 60)) / 1000);
minutesCounter.innerHTML = ("0"+mins).slice(-2);
secondsCounter.innerHTML = ("0"+secs).slice(-2);
if (winnerPanel.classList.contains('active-panel')) {
testCompleted = true;
continue;
}
return t;
}
if (!testCompleted) {
activateFailureMenu(failedMenuTime);
}
clearInterval(timer);
minutesCounter.innerHTML = "02";
secondsCounter.innerHTML = "00";
}, 1000);
quitButton.removeEventListener('click', function() {});
}
}
// function to deterministically select puppy image to display based upon screen size
function puppyImageSelector() {
if (window.innerWidth > 992) {
puppiesMedium[testCompletedCounter].classList.add('active-panel');
} else {
puppiesSmall[testCompletedCounter].classList.add('active-panel');
}
}
// function to deterministically select quitting pug image to display based upon screen size
function quittingPugImageSelector() {
if (window.innerWidth > 992) {
quittingPugSmall[0].classList.remove('active-panel');
quittingPugMedium[0].classList.add('active-panel');
} else {
quittingPugMedium[0].classList.remove('active-panel');
quittingPugSmall[0].classList.add('active-panel');
}
}
// function to act as a catch-all removal of active panel elements from previous states
function setDefaultState() {
removeActiveFailureMenuClass();
removeFailureBackgroundColor();
deselectAllInputs();
startVoid();
}
// function changes background color for starter panel and quitting-pug panel
function changeBackgroundColor() {
if (startMenu.classList.contains('active-panel') || quittingPugPanel[0].classList.contains('active-panel')) {
document.body.style.backgroundColor=lightBase;
} else {
if (window.innerWidth > 460) {
document.body.style.backgroundColor=lightBase;
} else {
document.body.style.backgroundColor=lightBackground;
}
}
}
// function removes components of Nothing Selected Panel Display from DOM
function removeNothingSelectedDisplay() {
nothingSelectedNotice.classList.remove('active-panel');
shadowPanel[0].classList.add('hidden');
}
// ********** EVENT HANDLER DECLERATIONS **********
// Start Button begins Test
startButton.addEventListener('click', function() {
quizIterationCount++;
footerElementsInvisible(startFooterElements);
footerElementsVisible(quizFooterElements);
startMenu.classList.remove('active-panel');
questions[0].classList.add('active-panel');
createTimer();
changeBackgroundColor();
});
// Next Button Moves Through Questions when Correct Answer is Selected {
let nextButtonClickedCount = 0;
let correctAnswerCounter = 0;
nextButton.addEventListener('click', function() {
if (correctAnswers[correctAnswerCounter].checked) {
nextButtonClickedCount++;
correctAnswerCounter++;
while (correctAnswerCounter <= questions.length) {
removeActiveQuestionClass();
if(questions[nextButtonClickedCount]) {
questions[(nextButtonClickedCount)].classList.add('active-panel');
// activates Test Completion (or "Winner's") Screen
} else {
winnerPanel.classList.add('active-panel');
puppyImageSelector();
footerElementsInvisible(quizFooterElements);
footerElementsVisible(menuFooterElements);
}
return correctAnswers[correctAnswerCounter-1].checked = false;
// This clears the checkmark on the correct answer of the previous question; this is necessary because although the question is hidden from view, it is still existing in the DOM, and so needs to be cleared in order to allow the Next Button to rely on the next question's correct answer to function.
}
} else {
wrongAnswerChecked();
}
changeBackgroundColor();
});
// Close Button closes the "Nothing Was Selected" Notice
closeButton.addEventListener('click', function() {
removeNothingSelectedDisplay()
});
// Retry Button returns user to the first question of the quiz; if on winner panel, resets the timer.
retryButton.addEventListener('click', function() {
const testCompletedChecker = function () {
if (testCompletedCounter < 3) {
testCompletedCounter++
} else {
testCompletedCounter = 0;
}
return testCompleted = false,
quizIterationCount = 0;
}
setDefaultState();
// resets quiz variables if user wishes to retake the quiz post victory
if (winnerPanel.classList.contains('active-panel')) {
winnerPanel.classList.remove('active-panel');
puppiesSmall[testCompletedCounter].classList.remove('active-panel');
puppiesMedium[testCompletedCounter].classList.remove('active-panel');
testCompletedChecker();
} else if (quittingPugPanel[0].classList.contains('active-panel')) {
quittingPugPanel[0].classList.remove('active-panel');
testCompletedChecker();
}
// prepares question one of the quiz state
footerElementsVisible(quizFooterElements);
questions[0].classList.add('active-panel');
nextButtonClickedCount = 0;
correctAnswerCounter = 0;
quizIterationCount++;
createTimer();
changeBackgroundColor();
return nextButtonClickedCount,
quizIterationCount,
correctAnswerCounter,
testCompleted,
testCompletedCounter;
});
// Quit Button returns user to the main menu, resetting all variables
quitButton.addEventListener('click', function() {
// notifies createTimer() function that the Quit Button has been pressed and so the timer should end.
const resetQuiz = function() {
setDefaultState();
// returns quiz to start menu state
footerElementsVisible(startFooterElements);
startMenu.classList.add('active-panel');
// resets and returns variables for start menu state
return nextButtonClickedCount = 0,
correctAnswerCounter = 0,
testCompleted = false,
testCompletedCounter = 0,
quizIterationCount = 0;
}
if (quittingPugPanel[0].classList.contains('active-panel')) {
quittingPugPanel[0].classList.remove('active-panel');
resetQuiz();
} else if (winnerPanel.classList.contains('active-panel')) {
winnerPanel.classList.remove('active-panel');
puppiesSmall[testCompletedCounter].classList.remove('active-panel');
puppiesMedium[testCompletedCounter].classList.remove('active-panel');
footerElementsVisible(menuFooterElements);
quittingPugPanel[0].classList.add('active-panel');
quittingPugImageSelector();
setFailureBackgroundColor();
changeBackgroundColor();
} else {
resetQuiz();
}
changeBackgroundColor();
return nextButtonClickedCount,
correctAnswerCounter,
testCompleted,
testCompletedCounter,
quizIterationCount;
});
// Window resize checks to make sure body background color is accurate based upon window size
window.addEventListener('resize', function() {
changeBackgroundColor();
});
// // FOR DEBUGGING
// const addAllButton = document.querySelector('#Add-All-Button');
// const allHidden = document.querySelectorAll('.hidden');
// function returnAll() {
// for (let hidden of allHidden) {
// hidden.classList.add('active-panel');
// // hidden.classList.remove('hidden');
// }
// removeActiveFailureMenuClass();
// nothingSelectedNotice.classList.remove('active-panel');
// };
// addAllButton.addEventListener('click', function() {
// returnAll();
// });
Also see: Tab Triggers