Friday, December 13, 2024
HomeProgrammingEasy methods to Make a Easy JavaScript Quiz: Code Tutorial — SitePoint

Easy methods to Make a Easy JavaScript Quiz: Code Tutorial — SitePoint


Quizzes are enjoyable! They’re a good way of studying about new topics, and so they mean you can have interaction your viewers with one thing enjoyable and playful. From a developer’s perspective, “How do I make a JavaScript quiz?” is among the commonest questions requested by individuals studying internet growth, and for good purpose.

Coding your personal JavaScript quiz sport is a improbable studying train. It teaches you tips on how to cope with occasions, manipulate the DOM, deal with consumer enter, and use native storage to trace their rating. When you’ve gotten a primary quiz up and working, there are a complete bunch of potentialities so as to add extra superior performance, similar to pagination.

On this tutorial, I’ll stroll you thru tips on how to make a quiz in JavaScript that you simply’ll be capable of adapt to your wants and add to your personal website. For those who’d prefer to see what we’ll be ending up with, you’ll be able to skip forward and see the working JavaScript quiz code.

For extra in-depth JavaScript data and challenges, get out our free guide: Study to Code with JavaScript.

Key Takeaways

  • Constructing a Quiz Construction: Easy methods to create the essential construction of a quiz utilizing HTML, CSS, and JavaScript.
  • Dynamic Content material Creation: Dynamically generate quiz questions and solutions with JavaScript.
  • Superior JavaScript Options: Acquire sensible expertise with JavaScript options like dealing with inputs, manipulating the DOM, dealing with occasions, and many others.
  • Pagination: The tutorial consists of steps to implement pagination with JavaScript to enhance the consumer expertise.
  • Styling: Easy methods to apply easy CSS styling to the quiz to make sure a constant consumer expertise.

Issues to Be Conscious of Earlier than Beginning

Right here are some things to know earlier than beginning:

  • This can be a front-end tutorial, that means anybody who is aware of tips on how to look by way of the supply code of a web page can discover the solutions. For severe quizzes, the info must be dealt with by way of the again finish, which is past the scope of this tutorial.
  • The code on this article makes use of fashionable JavaScript syntax (ES6+), that means it won’t be suitable with any model of Web Explorer. Nevertheless, it is going to work simply fantastic on fashionable browsers, together with Microsoft Edge.
  • If it’s worthwhile to assist older browsers, I’ve written a JavaScript quiz tutorial suitable with IE8. Or, if you happen to’d like a refresher on ES6, try this course by Darin Haener over on SitePoint Premium.
  • You’ll want some familiarity with HTML, CSS, and JavaScript, however every line of code will likely be defined individually.

Step 1 – The Primary Construction of Your JavaScript Quiz

Ideally, we would like the quiz’s questions and solutions to be in our JavaScript code and have our script routinely generate the quiz app. That means, we gained’t want to put in writing loads of repetitive markup, and we are able to add and take away questions simply.

On this instance, we’ll be structuring our mission utilizing three key recordsdata:

  • An HTML file for the essential consumer interface (UI).
  • A CSS file for styling.
  • A JavaScript file to deal with all of the interactive performance.

Nevertheless, if you happen to desire, you may as well embrace the CSS and JavaScript code straight inside the HTML file as inline code.

When studying tips on how to make a quiz in HTML and JavaScript, it’s essential to grasp how the HTML construction interacts with the JavaScript logic. So, as step one, let’s arrange the HTML construction of our JavaScript quiz sport.

  • A <div> to carry the quiz.
  • A <button> to submit the solutions.
  • A <div> to show the outcomes.

Right here’s how that will look:

<div id="quiz"></div>
<button id="submit">Submit Quiz</button>
<div id="outcomes"></div>

This construction is an easy instance of tips on how to create quiz HTML code that serves as a basis on your JavaScript quiz template. For those who run the appliance now, you’ll simply see a “Submit Quiz” button.

Step 2 – Initialize JavaScript Variables

Now, we are able to use the JavaScript doc.getElementById methodology to pick the above HTML parts and retailer references to them within the JavaScript quiz code like beneath:

const quizContainer = doc.getElementById('quiz');
const resultsContainer = doc.getElementById('outcomes');
const submitButton = doc.getElementById('submit');

The following factor our quiz app wants is a few inquiries to show. We’ll use JavaScript object literals to symbolize the person questions and an array to carry all the questions that make up our quiz app. Utilizing an array will make the questions straightforward to iterate over:

const myQuestions = [
  {
    question: "Who invented JavaScript?",
    answers: {
      a: "Douglas Crockford",
      b: "Sheryl Sandberg",
      c: "Brendan Eich"
    },
    correctAnswer: "c"
  },
  {
    question: "Which one of these is a JavaScript package manager?",
    answers: {
      a: "Node.js",
      b: "TypeScript",
      c: "npm"
    },
    correctAnswer: "c"
  },
  {
    question: "Which tool can you use to ensure code quality?",
    answers: {
      a: "Angular",
      b: "jQuery",
      c: "RequireJS",
      d: "ESLint"
    },
    correctAnswer: "d"
  }
];

Be at liberty to place in as many questions or solutions as you need.

Observe: As that is an array, the questions will seem within the order they’re listed. If you wish to kind the questions in any means earlier than presenting them to the consumer, try our fast tip on sorting an array of objects in JavaScript.

Step 3 – Construct the Quiz Operate

Now that we now have our checklist of questions, we are able to present them on the web page. For that, we will likely be utilizing a operate named buildQuix(). Let’s undergo the next JavaScript line by line to see the way it works:

operate buildQuiz(){
  // variable to retailer the HTML output
  const output = [];

  // for every query...
  myQuestions.forEach(
    (currentQuestion, questionNumber) => {

      // variable to retailer the checklist of doable solutions
      const solutions = [];

      // and for every accessible reply...
      for(letter in currentQuestion.solutions){

        // ...add an HTML radio button
        solutions.push(
          `<label>
            <enter kind="radio" identify="query${questionNumber}" worth="${letter}">
            ${letter} :
            ${currentQuestion.solutions[letter]}
          </label>`
        );
      }

      // add this query and its solutions to the output
      output.push(
        `<div class="query"> ${currentQuestion.query} </div>
        <div class="solutions"> ${solutions.be part of('')} </div>`
      );
    }
  );

  // lastly mix our output checklist into one string of HTML and put it on the web page
  quizContainer.innerHTML = output.be part of('');
}

First, we create an output variable to include all of the HTML output, together with questions and reply selections.

Subsequent, we are able to begin constructing the HTML for every query. We’ll have to loop by way of every query like this:

myQuestions.forEach( (currentQuestion, questionNumber) => {
  // the code we wish to run for every query goes right here
});

For brevity, we’re utilizing an arrow operate to carry out our operations on every query. As a result of that is in a forEach loop, we get the present worth, the index (the place quantity of the present merchandise within the array), and the array itself as parameters. We solely want the present worth and the index, which for our functions, we’ll identify currentQuestion and questionNumber respectively.

Now let’s take a look at the code inside our loop:

// we'll wish to retailer the checklist of reply selections
const solutions = [];

// and for every accessible reply...
for(letter in currentQuestion.solutions){

  // ...add an html radio button
  solutions.push(
    `<label>
      <enter kind="radio" identify="query${questionNumber}" worth="${letter}">
      ${letter} :
      ${currentQuestion.solutions[letter]}
    </label>`
  );
}

// add this query and its solutions to the output
output.push(
  `<div class="query"> ${currentQuestion.query} </div>
  <div class="solutions"> ${solutions.be part of('')} </div>`
);

For every query, we’ll wish to generate the proper HTML. So, our first step is to create an array to carry the checklist of doable solutions.s.

Subsequent, we’ll use a loop to fill within the doable solutions for the present query. For every alternative, we’re creating an HTML radio button, which we enclose in a <label> aspect. This ensures that customers can click on anyplace on the reply textual content to pick that reply. If the label was omitted, then customers must click on on the radio button itself, which isn’t very accessible.

Right here, we’re utilizing template literals, that are strings however extra highly effective. We’ll make use of the next options of template literals:

  • Multi-line capabilities.
  • Don’t want to make use of escape quotes inside quotes as a result of template literals use backticks.
  • String interpolation permits embedding JavaScript expressions proper into your strings like this: ${code_goes_here}.

As soon as we now have our checklist of reply buttons, we are able to push the query HTML and the reply HTML onto our general checklist of outputs.

Discover that we’re utilizing a template literal and a few embedded expressions to first create the query div after which create the reply div. The be part of expression takes our checklist of solutions and places them collectively in a single string that we are able to output into our solutions div.

Now that we’ve generated the HTML for every query, we are able to be part of all of it collectively and present it on the web page:

quizContainer.innerHTML = output.be part of('');

Now, our buildQuiz operate is full, and you must be capable of run the quiz app and see the questions displayed.

Nevertheless, the construction of your code is essential. Attributable to one thing referred to as the temporal lifeless zone, you’ll be able to’t reference your query array earlier than it has been outlined.

To recap, that is the proper construction:

// Capabilities
operate buildQuiz(){ ... }
operate showResults(){ ... }

// Variables
const quizContainer = doc.getElementById('quiz');
const resultsContainer = doc.getElementById('outcomes');
const submitButton = doc.getElementById('submit');
const myQuestions = [ ... ];

// Kick issues off
buildQuiz();

// Occasion listeners
submitButton.addEventListener('click on', showResults);

Step 4 – Displaying the Quiz Outcomes

At this level, we wish to construct out our showResults operate to loop over the solutions, verify them, and present the outcomes. This can be a essential a part of any quiz sport JavaScript implementation, because it supplies speedy suggestions to the consumer based mostly on their efficiency.

Right here’s the operate, which we’ll undergo intimately subsequent:

operate showResults(){

  // collect reply containers from our quiz
  const answerContainers = quizContainer.querySelectorAll('.solutions');

  // hold observe of consumer's solutions
  let numCorrect = 0;

  // for every query...
  myQuestions.forEach( (currentQuestion, questionNumber) => {

    // discover chosen reply
    const answerContainer = answerContainers[questionNumber];
    const selector = `enter[name=question${questionNumber}]:checked`;
    const userAnswer = (answerContainer.querySelector(selector) || {}).worth;

    // if reply is appropriate
    if(userAnswer === currentQuestion.correctAnswer){
      // add to the variety of appropriate solutions
      numCorrect++;

      // coloration the solutions inexperienced
      answerContainers[questionNumber].type.coloration="lightgreen";
    }
    // if reply is mistaken or clean
    else{
      // coloration the solutions purple
      answerContainers[questionNumber].type.coloration="purple";
    }
  });

  // present variety of appropriate solutions out of complete
  resultsContainer.innerHTML = `${numCorrect} out of ${myQuestions.size}`;
}

First, we choose all the reply containers in our quiz’s HTML. Then, we’ll create variables to maintain observe of the consumer’s present reply and the full variety of appropriate solutions.

// collect reply containers from our quiz
const answerContainers = quizContainer.querySelectorAll('.solutions');

// hold observe of consumer's solutions
let numCorrect = 0;

Now, we are able to loop by way of every query and verify the solutions.

We will likely be utilizing 3 steps for that:

  • Discover the chosen reply within the HTML.
  • Deal with what occurs if the reply is appropriate.
  • Deal with what occurs if the reply is mistaken.

Let’s look extra carefully at how we’re discovering the chosen reply in our HTML:

// discover chosen reply
const answerContainer = answerContainers[questionNumber];
const selector = `enter[name=question${questionNumber}]:checked`;
const userAnswer = (answerContainer.querySelector(selector) || {}).worth;

First, we’re ensuring we’re wanting inside the reply container for the present query.

Within the subsequent line, we’re defining a CSS selector that may allow us to discover which radio button is checked.

Then we’re utilizing JavaScript’s querySelector to seek for our CSS selector within the beforehand outlined answerContainer. In essence, which means that we’ll discover which reply’s radio button is checked.

Lastly, we are able to get the worth of that reply through the use of .worth.

Coping with Incomplete Consumer Enter

What if the consumer has left a solution clean? On this case, utilizing .worth would trigger an error as a result of you’ll be able to’t get the worth of one thing that’s not there. To unravel this, we’ve added ||, which suggests “or”, and {}, which is an empty object. Now, the general assertion says:

  • Get a reference to our chosen reply aspect OR, if that doesn’t exist, use an empty object.
  • Get the worth of no matter was within the first assertion.

Consequently, the worth will both be the consumer’s reply or undefined, which suggests a consumer can skip a query with out crashing our quiz app.

Evaluating the Solutions and Displaying the End result

The following statements in our answer-checking loop will allow us to deal with appropriate and incorrect solutions.

// if reply is appropriate
if(userAnswer === currentQuestion.correctAnswer){
  // add to the variety of appropriate solutions
  numCorrect++;

  // coloration the solutions inexperienced
  answerContainers[questionNumber].type.coloration="lightgreen";
}
// if reply is mistaken or clean
else{
  // coloration the solutions purple
  answerContainers[questionNumber].type.coloration="purple";
}

If the consumer’s reply matches the proper alternative, improve the variety of appropriate solutions by one and (optionally) coloration the set of selections inexperienced. If the reply is mistaken or clean, coloration the reply selections purple (once more, optionally available).

As soon as the answer-checking loop is completed, we are able to present what number of questions the consumer received proper:

// present variety of appropriate solutions out of complete
resultsContainer.innerHTML = `${numCorrect} out of ${myQuestions.size}`;

And now we now have a working JavaScript quiz!

For those who’d like, you’ll be able to wrap the entire quiz in an IIFE (instantly invoked operate expression), which is a operate that runs as quickly as you outline it. This can hold your variables out of worldwide scope and be sure that your quiz app doesn’t intrude with every other scripts working on the web page.

(operate(){
  // put the remainder of your code right here
})();

Now you’re all set! Be at liberty so as to add or take away questions and solutions and magnificence the quiz nevertheless you want.

Now, if you happen to run the appliance, you’ll be able to choose the solutions and submit the quiz to get the outcomes.

Step 5 – Including Kinds

Since now we now have a working quiz, let’s make it extra consumer pleasant by including some types. Nevertheless, I gained’t be going into particulars of every type. You possibly can straight copy the beneath code into the types.css file.

 @import url(https://fonts.googleapis.com/css?household=Work+Sans:300,600);

physique{
  font-size: 20px;
  font-family: 'Work Sans', sans-serif;
  coloration: #333;
  font-weight: 300;
  text-align: middle;
  background-color: #f8f6f0;
}
h1{
  font-weight: 300;
  margin: 0px;
  padding: 10px;
  font-size: 20px;
  background-color: #444;
  coloration: #fff;
}
.query{
  font-size: 30px;
  margin-bottom: 10px;
}
.solutions {
  margin-bottom: 20px;
  text-align: left;
  show: inline-block;
}
.solutions label{
  show: block;
  margin-bottom: 10px;
}
button{
  font-family: 'Work Sans', sans-serif;
  font-size: 22px;
  background-color: #279;
  coloration: #fff;
  border: 0px;
  border-radius: 3px;
  padding: 20px;
  cursor: pointer;
  margin-bottom: 20px;
}

button:hover{
  background-color: #38a;
}

.slide{
  place: absolute;
  left: 0px;
  high: 0px;
  width: 100%;
  z-index: 1;
  opacity: 0;
  transition: opacity 0.5s;
}
.active-slide{
  opacity: 1;
  z-index: 2;
}
.quiz-container{
  place: relative;
  top: 200px;
  margin-top: 40px;
}

At this level, your quiz may appear like this (with a tiny little bit of styling):

As you’ll be able to see within the above pictures, the questions within the quiz are ordered one after one other. We have now to scroll down to pick our solutions. Though this appears fantastic with three questions, you may begin struggling to reply them when the variety of questions will increase. So, we have to discover a technique to present just one query at a time by way of pagination.

For that, you’ll want:

  • A technique to present and conceal questions.
  • Buttons to navigate the quiz.

So, let’s make some changes to our code, beginning with HTML:

<div class="quiz-container">
  <div id="quiz"></div>
</div>
<button id="earlier">Earlier Query</button>
<button id="subsequent">Subsequent Query</button>
<button id="submit">Submit Quiz</button>
<div id="outcomes"></div>

Most of that markup is similar as earlier than, however now we’ve added navigation buttons and a quiz container. The quiz container will assist us place the questions as layers that we are able to present and conceal.

Subsequent, contained in the buildQuiz operate, we have to add a <div> aspect with class slide to carry the query and reply containers that we simply created:

output.push(
  `<div class="slide">
    <div class="query"> ${currentQuestion.query} </div>
    <div class="solutions"> ${solutions.be part of("")} </div>
  </div>`
);

Subsequent, we are able to use some CSS positioning to make the slides sit as layers on high of each other. On this instance, you’ll discover we’re utilizing z-indexes and opacity transitions to permit our slides to fade out and in. Right here’s what that CSS may appear like:

.slide{
  place: absolute;
  left: 0px;
  high: 0px;
  width: 100%;
  z-index: 1;
  opacity: 0;
  transition: opacity 0.5s;
}
.active-slide{
  opacity: 1;
  z-index: 2;
}
.quiz-container{
  place: relative;
  top: 200px;
  margin-top: 40px;
}

Now we’ll add some JavaScript to make the pagination work. As earlier than, order is essential, so this the revised construction of our code:

// Capabilities
// New capabilities go right here

// Variables
// Similar code as earlier than

// Kick issues off
buildQuiz();

// Pagination
// New code right here

// Present the primary slide
showSlide(currentSlide);

// Occasion listeners
// New occasion listeners right here

We are able to begin with some variables to retailer references to our navigation buttons and hold observe of which slide we’re on. Add these after the decision to buildQuiz(), as proven above:

// Pagination
const previousButton = doc.getElementById("earlier");
const nextButton = doc.getElementById("subsequent");
const slides = doc.querySelectorAll(".slide");
let currentSlide = 0;

Subsequent we’ll write a operate to point out a slide. Add this beneath the present capabilities (buildQuiz and showResults):

operate showSlide(n) {
  slides[currentSlide].classList.take away('active-slide');
  slides[n].classList.add('active-slide');
  currentSlide = n;
  if(currentSlide === 0){
    previousButton.type.show = 'none';
  }
  else{
    previousButton.type.show = 'inline-block';
  }
  if(currentSlide === slides.length-1){
    nextButton.type.show = 'none';
    submitButton.type.show = 'inline-block';
  }
  else{
    nextButton.type.show = 'inline-block';
    submitButton.type.show = 'none';
  }
}

Right here’s what the primary three strains do:

  • Conceal the present slide by eradicating the active-slide class.
  • Present the brand new slide by including the active-slide class.
  • Replace the present slide quantity.

The following strains introduce the next JavaScript logic:

  • If we’re on the primary slide, cover the Earlier Slide button. In any other case, present the button.
  • If we’re on the final slide, cover the Subsequent Slide button and present the Submit button. In any other case, present the Subsequent Slide button and conceal the Submit button.

After we’ve written our operate, we are able to instantly name showSlide(0) to point out the primary slide. This could come after the pagination code:

// Pagination
...

showSlide(currentSlide);

Subsequent we are able to write capabilities to make the navigation buttons work. These go beneath the showSlide operate:

operate showNextSlide() {
  showSlide(currentSlide + 1);
}

operate showPreviousSlide() {
  showSlide(currentSlide - 1);
}

Right here, we’re making use of our showSlide operate to permit our navigation buttons to point out the earlier slide and the following slide.

Lastly, we’ll have to hook the navigation buttons as much as these capabilities. This comes on the finish of the code:

// Occasion listeners
...
previousButton.addEventListener("click on", showPreviousSlide);
nextButton.addEventListener("click on", showNextSlide);

Now your quiz has working navigation!

What’s Subsequent?

Now that you’ve got a primary JavaScript quiz app, it’s time to get artistic and experiment.

Listed below are some ideas you’ll be able to strive:

  • Strive alternative ways of responding to an accurate reply or a mistaken reply.
  • Model the quiz properly.
  • Add a progress bar.
  • Let customers overview solutions earlier than submitting.
  • Give customers a abstract of their solutions after they submit them.
  • Replace the navigation to let customers skip to any query quantity.
  • Create customized messages for every stage of outcomes. For instance, if somebody scores 8/10 or larger, name them a quiz ninja.
  • Add a button to share outcomes on social media.
  • Save your excessive scores utilizing localStorage.
  • Add a countdown timer to see if individuals can beat the clock.
  • Apply the ideas from this text to different makes use of, similar to a mission value estimator, or a social “which-character-are-you” quiz.

FAQs on Easy methods to Make a Easy JavaScript Quiz

How Can I Add Extra Inquiries to the JavaScript Quiz?

Including extra inquiries to your JavaScript quiz is an easy course of. You want to add extra objects to the questions array in your JavaScript code. Every object represents a query and has two properties: textual content (the query itself) and responses (an array of doable solutions). Right here’s an instance of how one can add a brand new query:

questions.push({ 
  textual content: 'What's the capital of France?', 
  responses: [ 
  { 
    text: 'Paris', 
    correct: true 
  }, 
  { 
    text: 'London', 
    correct: false 
  }, 
  {
    text: 'Berlin', 
    correct: false 
  }, 
  { 
    text: 'Madrid', 
    correct: false 
  } 
  ] 
});

On this instance, we’re including a query concerning the capital of France, with 4 doable solutions. The right reply is marked with ‘appropriate: true’.

How Can I Randomize the Order of Questions within the Quiz?

Randomizing the order of questions could make your quiz tougher and enjoyable. You possibly can obtain this through the use of the type() methodology mixed with the Math.random() operate. Right here’s how you are able to do it:

questions.kind(
  operate() { 
    return 0.5 - Math.random();
  }
);

This code will randomly kind the questions array every time the web page is loaded.

How Can I Add a Timer to the Quiz?

Including a timer could make your quiz extra thrilling. You possibly can simply add a timer to the quiz utilizing the JavaScript setInterval() operate. Right here’s a easy instance:

var timeLeft = 30;
var timer = setInterval(operate() { 
  timeLeft--; 
  doc.getElementById('timer').textContent = timeLeft; 
  if (timeLeft <= 0) { 
    clearInterval(timer); 
    alert('Time is up!'); 
  }
}, 1000);

On this instance, the quiz will final for 30 seconds. The timer will replace each second, and when the time is up, an alert will likely be proven.

How Can I Present the Appropriate Reply if the Consumer Will get it Fallacious?

You possibly can present the proper reply by modifying the checkAnswer() operate. You possibly can add an else clause to the if assertion that checks if the reply is appropriate. Right here’s how you are able to do it:

operate checkAnswer(query, response) { 
  if (query.responses[response].appropriate) { 
    rating++; 
  } else { 
    alert('The right reply is: ' + query.responses.discover(r => r.appropriate).textual content);
  }
}

On this instance, if the consumer’s reply is inaccurate, an alert will likely be proven with the proper reply.

How Can I Add Pictures to the Questions?

You possibly can add pictures to your questions by including an ‘picture’ property to the query objects. You possibly can then use this property to show the picture in your HTML. Right here’s an instance:

questions.push({
 textual content: 'What is that this animal?',
 picture: 'elephant.jpg',
 responses: [
 { text: 'Elephant', correct: true },
 { text: 'Lion', correct: false },
 { text: 'Tiger', correct: false },
 { text: 'Bear', correct: false }
 ]
});

In your HTML, you’ll be able to show the picture like this:

<img src="" id="questionImage">

And in your JavaScript, you’ll be able to replace the src attribute of the picture when displaying a brand new query:

doc.getElementById('questionImage').src = query.picture;

On this instance, a picture of an elephant will likely be displayed when the query is proven.

How Do I Deal with A number of Appropriate Solutions in a JavaScript Quiz?

Dealing with a number of appropriate solutions entails permitting the consumer to pick a couple of reply and checking if any of the chosen solutions are appropriate. For instance, right here is how one can replace the above showResults() operate to deal with a number of appropriate solutions.

 operate showResults() {
  const answerContainers = quizContainer.querySelectorAll('.solutions');
  let numCorrect = 0;

  myQuestions.forEach((currentQuestion, questionNumber) => {
    const answerContainer = answerContainers[questionNumber];
    const selector = `enter[name=question${questionNumber}]:checked`;
    const userAnswers = Array.from(answerContainer.querySelectorAll(selector)).map(enter => enter.worth);

    if (userAnswers.kind().toString() === currentQuestion.correctAnswers.kind().toString()) {
      numCorrect++;
      answerContainers[questionNumber].type.coloration="lightgreen";
    } else {
      answerContainers[questionNumber].type.coloration="purple";
    }
  });

  resultsContainer.innerHTML = `${numCorrect} out of ${myQuestions.size}`;
}

Is It Essential to Keep Seperate JavaScript File and a CSS File?

Sustaining separate JavaScript and CSS recordsdata is just not a should. Nevertheless, it’s usually thought of a finest apply because it improves the readability and maintainability of your code.

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments