أخر الاخبار

Quiz Application with Timer design


 




file index. html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>exam | امتحان</title>
    <link rel="stylesheet" href="style.css">
    <!-- FontAweome CDN Link for Icons-->
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css"/>
</head>
<body>
    <!-- start Quiz button -->
    <div class="start_btn"><button>أبد الامتحان</button></div>

    <!-- Info Box -->
    <div class="info_box" style=" direction: rtl;
    text-align: right;">
        <div class="info-title"><span>بعض القواعد لأداء الامتحان</span></div>
        <div class="info-list">
            <div class="info">1. سيكون لديك فقط <span>15 seconds</span> لكل سؤال.</div>
            <div class="info">2. بمجرد تحديد إجابتك ، لا يمكن التراجع عنها</div>
            <div class="info">3. لا يمكنك تحديد أي خيار بمجرد انتهاء الوقت.</div>
            <div class="info">4. لا يمكنك الخروج من الاختبار أثناء الامتحان .</div>
            <div class="info">5. ستحصل على نقاط بناءً على إجاباتك الصحيحة.</div>
        </div>
        <div class="buttons">
            <button class="quit">الخروج </button>
            <button class="restart">الاستمرار</button>
        </div>
    </div>

    <!-- Quiz Box -->
    <div class="quiz_box" >
        <header>
            <div class="title">تطبيق مسابقة رهيبة</div>
            <div class="timer">
                <div class="time_left_txt">الوقت المتبقي</div>
                <div class="timer_sec">15</div>
            </div>
            <div class="time_line"></div>
        </header>
        <section>
            <div class="que_text" >
                <!-- Here I've inserted question from JavaScript -->
            </div>
            <div class="option_list" >
                <!-- Here I've inserted options from JavaScript -->
            </div>
        </section>

        <!-- footer of Quiz Box -->
        <footer>
            <div class="total_que" style=" direction: rtl;
            text-align: right;">
                <!-- Here I've inserted Question Count Number from JavaScript -->
            </div>
            <button class="next_btn">السؤال التالي</button>
        </footer>
    </div>

    <!-- Result Box -->
    <div class="result_box" style=" direction: rtl;
    text-align: right;">
        <div class="icon">
            <i class="fas fa-crown"></i>
        </div>
        <div class="complete_text">لقد اكملت الامتحان </div>
        <div class="score_text" >
            <!-- Here I've inserted Score Result from JavaScript -->
        </div>
        <div class="buttons" style=" direction: rtl;
        text-align: right;">
            <button class="restart">أعادة الامتحان</button>
            <button class="quit">خروج من الامتحان</button>
        </div>
    </div>

    <!-- Inside this JavaScript file I've inserted Questions and Options only -->
    <script src="js/questions.js"></script>

    <!-- Inside this JavaScript file I've coded all Quiz Codes -->
    <script src="js/script.js"></script>

</body>
</html>

file css

/* importing google fonts */
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@200;300;400;500;600;700&display=swap');
*{
    margin0;
    padding0;
    box-sizingborder-box;
    font-family'Poppins'sans-serif;
}

body{
    background#007bff;
}

::selection{
    color#fff;
    background#007bff;
}

.start_btn,
.info_box,
.quiz_box,
.result_box{
    positionabsolute;
    top50%;
    left50%;
    transformtranslate(-50%-50%);
    box-shadow0 4px 8px 0 rgba(0000.2), 
                0 6px 20px 0 rgba(0000.19);
                
}

.info_box.activeInfo,
.quiz_box.activeQuiz,
.result_box.activeResult{
    opacity1;
    z-index5;
    pointer-eventsauto;
    transformtranslate(-50%-50%scale(1);
}

.start_btn button{
    font-size25px;
    font-weight500;
    color#007bff;
    padding15px 30px;
    outlinenone;
    bordernone;
    border-radius5px;
    background#fff;
    cursorpointer;
}

.info_box{
    width650px;
    background#fff;
    border-radius5px;
    transformtranslate(-50%-50%scale(0.9);
    opacity0;
    pointer-eventsnone;
    transitionall 0.3s ease;
}

.info_box .info-title{
    height60px;
    width100%;
    border-bottom1px solid lightgrey;
    displayflex;
    align-itemscenter;
    padding0 30px;
    border-radius5px 5px 0 0;
    font-size20px;
    font-weight600;
}

.info_box .info-list{
    padding15px 30px;
}

.info_box .info-list .info{
    margin5px 0;
    font-size17px;
}

.info_box .info-list .info span{
    font-weight600;
    color#007bff;
}
.info_box .buttons{
    height60px;
    displayflex;
    align-itemscenter;
    justify-contentflex-end;
    padding0 30px;
    border-top1px solid lightgrey;
}

.info_box .buttons button{
    margin0 5px;
    height40px;
    width100px;
    font-size16px;
    font-weight500;
    cursorpointer;
    bordernone;
    outlinenone;
    border-radius5px;
    border1px solid #007bff;
    transitionall 0.3s ease;
}

.quiz_box{
    width740px;
    background#fff;
    border-radius5px;
    transformtranslate(-50%-50%scale(0.9);
    opacity0;
    pointer-eventsnone;
    transitionall 0.3s ease;
}

.quiz_box header{
    positionrelative;
    z-index2;
    height70px;
    padding: 0 30px;
    background: #fff;
    border-radius: 5px 5px 0 0;
    display: flex;
    align-items: center;
    justify-content: space-between;
    box-shadow: 0px 3px 5px 1px rgba(0,0,0,0.1);
}

.quiz_box header .title{
    font-size: 20px;
    font-weight: 600;
}

.quiz_box header .timer{
    color: #004085;
    background: #cce5ff;
    border: 1px solid #b8daff;
    height: 45px;
    padding: 0 8px;
    border-radius: 5px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    width: 145px;
}

.quiz_box header .timer .time_left_txt{
    font-weight: 400;
    font-size: 17px;
    user-select: none;
}

.quiz_box header .timer .timer_sec{
    font-size: 18px;
    font-weight: 500;
    height: 30px;
    width: 45px;
    color: #fff;
    border-radius: 5px;
    line-height: 30px;
    text-align: center;
    background: #343a40;
    border: 1px solid #343a40;
    user-select: none;
}

.quiz_box header .time_line{
    position: absolute;
    bottom: 0px;
    left: 0px;
    height: 3px;
    background: #007bff;
}

section{
    padding: 25px 30px 20px 30px;
    background: #fff;
}

section .que_text{
    font-size: 25px;
    font-weight: 600;
}

section .option_list{
    padding: 20px 0px;
    display: block;   
}

section .option_list .option{
    background: aliceblue;
    border: 1px solid #84c5fe;
    border-radius: 5px;
    padding: 8px 15px;
    font-size: 17px;
    margin-bottom: 15px;
    cursor: pointer;
    transition: all 0.3s ease;
    display: flex;
    align-items: center;
    justify-content: space-between;
}

section .option_list .option:last-child{
    margin-bottom: 0px;
}

section .option_list .option:hover{
    color: #004085;
    background: #cce5ff;
    border: 1px solid #b8daff;
}

section .option_list .option.correct{
    color: #155724;
    background: #d4edda;
    border: 1px solid #c3e6cb;
}

section .option_list .option.incorrect{
    color: #721c24;
    background: #f8d7da;
    border: 1px solid #f5c6cb;
}

section .option_list .option.disabled{
    pointer-events: none;
}

section .option_list .option .icon{
    height: 26px;
    width: 26px;
    border: 2px solid transparent;
    border-radius: 50%;
    text-align: center;
    font-size: 13px;
    pointer-events: none;
    transition: all 0.3s ease;
    line-height: 24px;
}
.option_list .option .icon.tick{
    color: #23903c;
    border-color: #23903c;
    background: #d4edda;
}

.option_list .option .icon.cross{
    color: #a42834;
    background: #f8d7da;
    border-color: #a42834;
}

footer{
    height: 60px;
    padding: 0 30px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    border-top: 1px solid lightgrey;
}

footer .total_que span{
    display: flex;
    user-select: none;
}

footer .total_que span p{
    font-weight: 500;
    padding: 0 5px;
}

footer .total_que span p:first-child{
    padding-left: 0px;
}

footer button{
    height: 40px;
    padding: 0 13px;
    font-size: 18px;
    font-weight: 400;
    cursor: pointer;
    border: none;
    outline: none;
    color: #fff;
    border-radius: 5px;
    background: #007bff;
    border: 1px solid #007bff;
    line-height: 10px;
    opacity: 0;
    pointer-events: none;
    transform: scale(0.95);
    transition: all 0.3s ease;
}

footer button:hover{
    background: #0263ca;
}

footer button.show{
    opacity: 1;
    pointer-events: auto;
    transform: scale(1);
}

.result_box{
    background: #fff;
    border-radius: 5px;
    display: flex;
    padding: 25px 30px;
    width: 450px;
    align-items: center;
    flex-direction: column;
    justify-content: center;
    transform: translate(-50%, -50%) scale(0.9);
    opacity: 0;
    pointer-events: none;
    transition: all 0.3s ease;
}

.result_box .icon{
    font-size: 100px;
    color: #007bff;
    margin-bottom: 10px;
}

.result_box .complete_text{
    font-size: 20px;
    font-weight: 500;
}

.result_box .score_text span{
    display: flex;
    margin: 10px 0;
    font-size: 18px;
    font-weight: 500;
}

.result_box .score_text span p{
    padding: 0 4px;
    font-weight: 600;
}

.result_box .buttons{
    display: flex;
    margin: 20px 0;
}

.result_box .buttons button{
    margin: 0 10px;
    height: 45px;
    padding: 0 20px;
    font-size: 18px;
    font-weight: 500;
    cursor: pointer;
    border: none;
    outline: none;
    border-radius: 5px;
    border: 1px solid #007bff;
    transition: all 0.3s ease;
}

.buttons button.restart{
    color: #fff;
    background: #007bff;
}

.buttons button.restart:hover{
    background: #0263ca;
}

.buttons button.quit{
    color: #007bff;
    background: #fff;
}

.buttons button.quit:hover{
    color: #fff;
    background: #007bff;
}
@media (max-width:1024px){
    .info_box{
        width: 750px;
    }
    .quiz_box{
        width: 750px;
    }
    .result_box{
        width: 550px;
    }
    .buttons button.restart{
        font-size: 35px;
    }
    .buttons button.quit{
        font-size: 35px;
    }
    .info_box .info-title{
        font-size: 20px;
    }

    } 
@media (max-width:641px){
    .info_box{
        width: 450px;
    }
    .quiz_box{
        width: 450px;
    }
    .result_box{
        width: 450px;
    }
    .buttons button.restart{
        font-size: 25px;
    }
    .buttons button.quit{
        font-size: 25px;
    }
    .info_box .info-title{
        font-size: 18px;
    }

    } 
@media (max-width:425px){
    .info_box{
        width: 350px;
    }
    .quiz_box{
        width: 350px;
    }
    .result_box{
        width: 350px;
    }
    .buttons button.restart{
        font-size: 18px;
    }
    .buttons button.quit{
        font-size: 18px;
    }
    .info_box .info-title{
        font-size: 15px;
    }
}

file question.js

// creating an array and passing the number, questions, options, and answers
let questions = [
    {
    numb: 1,
    question: "What does HTML stand for?",
    answer: "Hyper Text Markup Language",
    options: [
      "Hyper Text Preprocessor",
      "Hyper Text Markup Language",
      "Hyper Text Multiple Language",
      "Hyper Tool Multi Language"
    ]
  },
    {
    numb: 2,
    question: "Who is making the Web standards?",
    answer: "The World Wide Web Consortium ",
    options: [
      "Google",
      "The World Wide Web Consortium ",
      "Mozilla",
      "Microsoft"
    ]
  },
    {
    numb: 3,
    question: "Choose the correct HTML element for the largest heading:",
    answer: 'h1',
    options: [
      'head',
      'heading',
      'h6',
      'h1'
    ]
  },
    {
    numb: 4,
    question: "What is the correct HTML element for inserting a line break?",
    answer: "br",
    options: [
      "lb",
      "br",
      "break",
      "vr"
      
    ]
  },
    
  {
    numb: 5,
    question: "Choose the correct HTML element to define important text",
    answer: "strong",
    options: [
      "strong",
      "important",
      "b",
      "i"
    ]
  },
  {
    numb: 6,
    question: "Choose the correct HTML element to define emphasized text",
    answer: "em",
    options: [
      "i",
      "em",
      "b",
      "italic"
    ]
  },
  {
    numb: 7,
    question: "Which character is used to indicate an end tag?",
    answer: "/",
    options: [
      "*",
      "<",
      "/",
      "^"
    ]
  },
  {
    numb: 8,
    question: "How can you make a numbered list?",
    answer: "ol",
    options: [
      "ol",
      "ul",
      "list",
      "dl"
    ]
  },
  {
    numb: 9,
    question: "How can you make a bulleted list?",
    answer: "ul",
    options: [
      "list",
      "ol",
      "ul",
      "dl"
    ]
  },
  {
    numb: 10,
    question: "Which HTML attribute specifies an alternate text for an image, if the image cannot be displayed?",
    answer: "alt",
    options: [
      "alt",
      "longdesc",
      "src",
      "title"
    ]
  },
  
  // you can uncomment the below codes and make duplicate as more as you want to add question
  // but remember you need to give the numb value serialize like 1,2,3,5,6,7,8,9.....

  //   {
  //   numb: 6,
  //   question: "Your Question is Here",
  //   answer: "Correct answer of the question is here",
  //   options: [
  //     "Option 1",
  //     "option 2",
  //     "option 3",
  //     "option 4"
  //   ]
  // },
];

file script.js

//selecting all required elements
const start_btn = document.querySelector(".start_btn button");
const info_box = document.querySelector(".info_box");
const exit_btn = info_box.querySelector(".buttons .quit");
const continue_btn = info_box.querySelector(".buttons .restart");
const quiz_box = document.querySelector(".quiz_box");
const result_box = document.querySelector(".result_box");
const option_list = document.querySelector(".option_list");
const time_line = document.querySelector("header .time_line");
const timeText = document.querySelector(".timer .time_left_txt");
const timeCount = document.querySelector(".timer .timer_sec");

// if startQuiz button clicked
start_btn.onclick = ()=>{
    info_box.classList.add("activeInfo"); //show info box
}

// if exitQuiz button clicked
exit_btn.onclick = ()=>{
    info_box.classList.remove("activeInfo"); //hide info box
}

// if continueQuiz button clicked
continue_btn.onclick = ()=>{
    info_box.classList.remove("activeInfo"); //hide info box
    quiz_box.classList.add("activeQuiz"); //show quiz box
    showQuetions(0); //calling showQestions function
    queCounter(1); //passing 1 parameter to queCounter
    startTimer(15); //calling startTimer function
    startTimerLine(0); //calling startTimerLine function
}

let timeValue =  15;
let que_count = 0;
let que_numb = 1;
let userScore = 0;
let counter;
let counterLine;
let widthValue = 0;

const restart_quiz = result_box.querySelector(".buttons .restart");
const quit_quiz = result_box.querySelector(".buttons .quit");

// if restartQuiz button clicked
restart_quiz.onclick = ()=>{
    quiz_box.classList.add("activeQuiz"); //show quiz box
    result_box.classList.remove("activeResult"); //hide result box
    timeValue = 15
    que_count = 0;
    que_numb = 1;
    userScore = 0;
    widthValue = 0;
    showQuetions(que_count); //calling showQestions function
    queCounter(que_numb); //passing que_numb value to queCounter
    clearInterval(counter); //clear counter
    clearInterval(counterLine); //clear counterLine
    startTimer(timeValue); //calling startTimer function
    startTimerLine(widthValue); //calling startTimerLine function
    timeText.textContent = "Time Left"//change the text of timeText to Time Left
    next_btn.classList.remove("show"); //hide the next button
}

// if quitQuiz button clicked
quit_quiz.onclick = ()=>{
    window.location.reload(); //reload the current window
}

const next_btn = document.querySelector("footer .next_btn");
const bottom_ques_counter = document.querySelector("footer .total_que");

// if Next Que button clicked
next_btn.onclick = ()=>{
    if(que_count < questions.length - 1){ //if question count is less than total question length
        que_count++; //increment the que_count value
        que_numb++; //increment the que_numb value
        showQuetions(que_count); //calling showQestions function
        queCounter(que_numb); //passing que_numb value to queCounter
        clearInterval(counter); //clear counter
        clearInterval(counterLine); //clear counterLine
        startTimer(timeValue); //calling startTimer function
        startTimerLine(widthValue); //calling startTimerLine function
        timeText.textContent = "Time Left"//change the timeText to Time Left
        next_btn.classList.remove("show"); //hide the next button
    }else{
        clearInterval(counter); //clear counter
        clearInterval(counterLine); //clear counterLine
        showResult(); //calling showResult function
    }
}

// getting questions and options from array
function showQuetions(index){
    const que_text = document.querySelector(".que_text");

    //creating a new span and div tag for question and option and passing the value using array index
    let que_tag = '<span>'questions[index].numb + ". " + questions[index].question +'</span>';
    let option_tag = '<div class="option"><span>'questions[index].options[0] +'</span></div>'
    + '<div class="option"><span>'questions[index].options[1] +'</span></div>'
    + '<div class="option"><span>'questions[index].options[2] +'</span></div>'
    + '<div class="option"><span>'questions[index].options[3] +'</span></div>';
    que_text.innerHTML = que_tag//adding new span tag inside que_tag
    option_list.innerHTML = option_tag//adding new div tag inside option_tag
    
    const option = option_list.querySelectorAll(".option");

    // set onclick attribute to all available options
    for(i=0i < option.lengthi++){
        option[i].setAttribute("onclick""optionSelected(this)");
    }
}
// creating the new div tags which for icons
let tickIconTag = '<div class="icon tick"><i class="fas fa-check"></i></div>';
let crossIconTag = '<div class="icon cross"><i class="fas fa-times"></i></div>';

//if user clicked on option
function optionSelected(answer){
    clearInterval(counter); //clear counter
    clearInterval(counterLine); //clear counterLine
    let userAns = answer.textContent//getting user selected option
    let correcAns = questions[que_count].answer//getting correct answer from array
    const allOptions = option_list.children.length//getting all option items
    
    if(userAns == correcAns){ //if user selected option is equal to array's correct answer
        userScore += 1//upgrading score value with 1
        answer.classList.add("correct"); //adding green color to correct selected option
        answer.insertAdjacentHTML("beforeend"tickIconTag); //adding tick icon to correct selected option
        console.log("Correct Answer");
        console.log("Your correct answers = " + userScore);
    }else{
        answer.classList.add("incorrect"); //adding red color to correct selected option
        answer.insertAdjacentHTML("beforeend"crossIconTag); //adding cross icon to correct selected option
        console.log("Wrong Answer");

        for(i=0i < allOptionsi++){
            if(option_list.children[i].textContent == correcAns){ //if there is an option which is matched to an array answer 
                option_list.children[i].setAttribute("class""option correct"); //adding green color to matched option
                option_list.children[i].insertAdjacentHTML("beforeend"tickIconTag); //adding tick icon to matched option
                console.log("Auto selected correct answer.");
            }
        }
    }
    for(i=0i < allOptionsi++){
        option_list.children[i].classList.add("disabled"); //once user select an option then disabled all options
    }
    next_btn.classList.add("show"); //show the next button if user selected any option
}

function showResult(){
    info_box.classList.remove("activeInfo"); //hide info box
    quiz_box.classList.remove("activeQuiz"); //hide quiz box
    result_box.classList.add("activeResult"); //show result box
    const scoreText = result_box.querySelector(".score_text");
    if (userScore >=9){ // if user scored more than 3
        //creating a new span tag and passing the user score number and total question number
        let scoreTag = `<span>ومبروك! 🎉, لقد أخذت  <p>${userScore}</p>من <p>${questions.length}</p></span>`;
        scoreText.innerHTML = scoreTag;  //adding new span tag inside score_Text
    }
    else if(userScore >=5){ // if user scored more than 1
        let scoreTag = `<span><p>وجميل 😎, لقد أخذت </p><p>${userScore}</p><p> من </p><p>${questions.length}</p></span>`;
        scoreText.innerHTML = scoreTag;
    }
    else// if user scored less than 1
        let scoreTag = `<span>وأسف 😐, لقد أخذت فقط  <p>${userScore}</p> من <p>${questions.length}</p></span>`;
        scoreText.innerHTML = scoreTag;
    }
}

function startTimer(time){
    counter = setInterval(timer1000);
    function timer(){
        timeCount.textContent = time//changing the value of timeCount with time value
        time--; //decrement the time value
        if(time < 9){ //if timer is less than 9
            let addZero = timeCount.textContent
            timeCount.textContent = "0" + addZero//add a 0 before time value
        }
        if(time < 0){ //if timer is less than 0
            clearInterval(counter); //clear counter
            timeText.textContent = "Time Off"//change the time text to time off
            const allOptions = option_list.children.length//getting all option items
            let correcAns = questions[que_count].answer//getting correct answer from array
            for(i=0i < allOptionsi++){
                if(option_list.children[i].textContent == correcAns){ //if there is an option which is matched to an array answer
                    option_list.children[i].setAttribute("class""option correct"); //adding green color to matched option
                    option_list.children[i].insertAdjacentHTML("beforeend"tickIconTag); //adding tick icon to matched option
                    console.log("Time Off: Auto selected correct answer.");
                }
            }
            for(i=0i < allOptionsi++){
                option_list.children[i].classList.add("disabled"); //once user select an option then disabled all options
            }
            next_btn.classList.add("show"); //show the next button if user selected any option
        }
    }
}

function startTimerLine(time){
    counterLine = setInterval(timer29);
    function timer(){
        time += 1//upgrading time value with 1
        time_line.style.width = time + "px"//increasing width of time_line with px by time value
        if(time > 549){ //if time value is greater than 549
            clearInterval(counterLine); //clear counterLine
        }
    }
}

function queCounter(index){
    //creating a new span tag and passing the question number and total question
    let totalQueCounTag = '<span><p>'index +'</p> of <p>'questions.length +'</p> Questions</span>';
    bottom_ques_counter.innerHTML = totalQueCounTag;  //adding new span tag inside bottom_ques_counter
}
تعليقات



حجم الخط
+
16
-
تباعد السطور
+
2
-