Javascript Flash Card Project for Beginners





Hey guys in this post, we will create a Javascript flashcard project for beginners. Follow this tutorial till the end to understand the javascript concepts. we will create this project step by step. The final version of the app is live on the internet.

Topics covered


This application involves the following topics –

  • Object-Oriented JavaScript
  • JavaScript Constructor Functions
  • JavaScript Prototypal Inheritance
  • JavaScript CSS Manipulation
  • JavaScript DOM Manipulation

Complete source code


The below image shows you the project structure –

Screenshot-2021-06-16-at-4-29-14-PM

Add styles to the application


Create a main.css file and add the following content –

:root {
  --mainWhite: #f5f5f5;
  --mainDark: #333333;
  --mainOrange: #ff8552;
  --mainGreen: #297373;
}
body {
  background: var(--mainWhite);
  color: var(--mainDark);
}
.show-btn {
  border-color: var(--mainOrange);
  color: var(--mainOrange);
  background: transparent;
}
.show-btn:hover {
  background: var(--mainOrange);
  color: var(--mainDark);
}

.question-card {
  display: none;
  position: relative;
  background: transparent;
  border-color: var(--mainOrange);
}
.feedback {
  display: none;
}

textarea {
  border-radius: 0.25rem;
  border-color: var(--mainOrange);
}
.close-btn {
  position: absolute;
  top: 0;
  right: 2%;
  font-size: 2rem;
  color: var(--mainOrange);
  cursor: pointer;
}
.close-btn:hover {
  color: var(--mainGreen);
}
.submitBtn {
  border: 0.2rem solid var(--mainGreen);
  color: var(--mainGreen);
  background: transparent;
}
.submitBtn:hover {
  background: var(--mainGreen);
  color: var(--mainWhite);
}
.edit-flashcard {
  border: 0.2rem solid var(--mainGreen);
  color: var(--mainGreen);
  background: transparent;
}
.edit-flashcard:hover {
  background: var(--mainGreen);
  color: var(--mainDark);
}
.delete-flashcard {
  border: 0.2rem solid var(--mainOrange);
  color: var(--mainOrange);
  background: transparent;
}
.delete-flashcard:hover {
  background: var(--mainOrange);
  color: var(--mainDark);
}
.answer {
  display: none;
}
.showItem {
  display: block;
}

Add scripts to the application


Create an app.js file and add the following content –

//event listeners - will be invoked after DOM Content is loaded
function eventListeners(){
    const showBtn = document.getElementById("show-btn");
    const questionCard = document.querySelector(".question-card");
    const closeBtn = document.querySelector(".close-btn");
    const form = document.getElementById("question-form");
    const feedback = document.querySelector(".feedback");
    const questionInput = document.getElementById("question-input");
    const answerInput = document.getElementById("answer-input");
    const questionList = document.getElementById("questions-list");
    //let data = [];
    let id;

    //new ui instance
    const ui = new UI();
    //retrieve questions from local storage
    let data = ui.retrieveLocalStorgage();
    if (data.length > 0){
        id = (data[(data.length-1)].id)+1;
    } else {
        id = 1;
    }
    data.forEach(function(question){
        ui.addQuestion(questionList, question);
    })
    //show question form
    showBtn.addEventListener('click', function(){
        ui.showQuestion(questionCard);
    });
    //hide question form
    closeBtn.addEventListener('click', function(){
        ui.hideQuestion(questionCard);
    });
    //add question
    form.addEventListener('submit', function(event){
        event.preventDefault();

        const questionValue = questionInput.value;
        const answerValue = answerInput.value;

        if(questionValue === '' || answerValue === ''){
            feedback.classList.add('showItem', 'alert-danger');
            feedback.textContent = 'cannot add empty values';

            setTimeout(function(){
                feedback.classList.remove('alert-danger', 'showItem');    
            }, 3000)
        } else {
            const question =  new Question(id, questionValue, answerValue);
            data.push(question);
            ui.addToLocalStorage(data);
            id++;
            ui.addQuestion(questionList, question)
            ui.clearFields(questionInput, answerInput);
        }
    });
    //work with a question
    questionList.addEventListener('click', function(event){
        event.preventDefault();
    if(event.target.classList.contains('delete-flashcard')){
        let id = event.target.dataset.id;

        questionList.removeChild(event.target.parentElement.parentElement.parentElement);
        // rest of data
        let tempData = data.filter(function(item){
            return item.id !== parseInt(id);
        });
        data = tempData;
        ui.addToLocalStorage(data);

    } else if (event.target.classList.contains('show-answer')){
            event.target.nextElementSibling.classList.toggle('showItem');
    } else if (event.target.classList.contains('edit-flashcard')){
        //delete question from DOM
        let id = event.target.dataset.id;
        questionList.removeChild(event.target.parentElement.parentElement.parentElement);

        //show question in question card
        ui.showQuestion(questionCard);
        //find specific question clicked
        const tempQuestion = data.filter(function(item){
            return item.id === parseInt(id);
        });
        // rest of data
        let tempData = data.filter(function(item){
            return item.id !== parseInt(id);
        });
        data = tempData;
        questionInput.value = tempQuestion[0].title;
        questionInput.value = tempQuestion[0].answer;
    }  
    });
}
//Contructor function responsible for the display
function UI(){
    //show question card
    UI.prototype.showQuestion = function(element){
        element.classList.add('showItem');
    }
    //hide question card
    UI.prototype.hideQuestion = function(element){
        element.classList.remove('showItem');
    }
    //add question
    UI.prototype.addQuestion = function(element, question){
        const div = document.createElement('div');
        div.classList.add('col-md-4');
        div.innerHTML = `<div class="card card-body flashcard my-3">
        <h4 class="text-capitalize">${question.title}</h4>
        <a href="#" class="text-capitalize my-3 show-answer">Show/Hide Answer</a>
        <h5 class="answer mb-3">${question.answer}</h5>
        <div class="flashcard-btn d-flex justify-content-between">
   
         <a href="#" id="edit-flashcard" class=" btn my-1 edit-flashcard text-uppercase" data-id="${question.id}">edit</a>
         <a href="#" id="delete-flashcard" class=" btn my-1 delete-flashcard text-uppercase" data-id="${question.id}">delete</a>
        </div>
       </div>`;
       element.appendChild(div);
    }
    //add to Local Storage
    UI.prototype.addToLocalStorage = function(data){
        localStorage.clear();
        const dataJSON = JSON.stringify(data);
        localStorage.setItem('flash-questions', dataJSON)
    }
    //retrieve from localStorage
    UI.prototype.retrieveLocalStorgage = function(){

        let savedQuestions = localStorage.getItem('flash-questions');
        if (savedQuestions){
            const savedQuestionsParsed = JSON.parse(savedQuestions);
            return savedQuestionsParsed;
        } else {
            return savedQuestions = [];
        }
        
    }

    //clear fields
    UI.prototype.clearFields = function(question, answer){
        question.value = '';
        answer.value = '';
    }
}
//Constructor function responsible for each question
function Question(id, title, answer){
    this.id = id;
    this.title = title;
    this.answer = answer;
}
// dom event listener to run when content is loaded
document.addEventListener('DOMContentLoaded', function(){
    eventListeners();
})

Add HTML to the application


Create an index.html file and add the following content –

<!DOCTYPE html>
<html lang="en">

<head>
 <meta charset="UTF-8">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <meta http-equiv="X-UA-Compatible" content="ie=edge">
 <!-- bootstrap css -->
 <link rel="stylesheet" href="./css/bootstrap.min.css">
 <!-- main css -->
 <link rel="stylesheet" href="./css/main.css">
 <!-- google fonts -->
 <link href="https://fonts.googleapis.com/css?family=Courgette" rel="stylesheet">

 <!-- font awesome -->
 <link rel="stylesheet" href="./css/all.css">
 <title>Flashcard Project</title>
 <style>
 </style>
</head>

<body>

 <div class="container">
  <div class="row">
   <div class="col-11 col-lg-6 my-3">
    <h3 class="text-capitalize">flashcards</h3>
    <button class="btn text-capitalize my-2 show-btn" id="show-btn">add question</button>
    <div class="card card-body my-3 question-card">
     <!-- close btn -->
     <a href="#" class="close-btn mt-0">
      <i class="fas fa-window-close"></i>
     </a>
     <!-- end of close btn -->
     <div class="feedback alert w-75 text-capitalize">
      customer feedback
     </div>
     <form id="question-form">
      <!-- single input -->
      <h5 class="text-capitalize">question</h5>
      <div class="form-group">
       <textarea class="w-100" id="question-input" rows="3"></textarea>
      </div>
      <!-- end of single input -->
      <!-- single input -->
      <h5 class="text-capitalize">answer</h5>
      <div class="form-group">
       <textarea class="w-100" id="answer-input" rows="3"></textarea>
      </div>
      <!-- end of single input -->
      <button type="submit" class="btn submitBtn text-capitalize w-50">save</button>
     </form>
    </div>
   </div>
  </div>

  <div class="row px-2" id="questions-list">
   <!-- <div class="col-md-4"> -->
    <!--Template for card data-->
    <!-- <div class="card card-body flashcard my-3">
     <h4 class="text-capitalize">question title?</h4>
     <a href="#" class="text-capitalize my-3 show-answer">show/hide answer</a>
     <h5 class="answer mb-3">question answer</h5>
     <div class="flashcard-btn d-flex justify-content-between">
      <a href="#" id="edit-flashcard" class=" btn my-1 edit-flashcard text-uppercase" data-id="">edit</a>
      <a href="#" id="delete-flashcard" class=" btn my-1 delete-flashcard text-uppercase">delete</a>
     </div> -->
    </div>
   </div>

  </div>
 </div>





 <!-- jquery -->
 <script src="./js/jquery-3.3.1.min.js"></script>
 <!-- bootstrap js -->
 <script src="./js/bootstrap.bundle.min.js"></script>
 <!-- script js -->
 <script src="./js/app.js"></script>
</body>

</html>

Screenshots


Screenshot-2021-06-16-at-4-32-16-PM

Download the complete source code from github repository

Original source https://jsbeginners.com/flashcard-javascript-oop-project/

That’s it for this post. Hope you liked it, if you did then please share this with your friends and colleagues. Also, share this post in your social media profiles. Thanks, I will see you in the next post.



Bushan Sirgur

Hey guys, I am Bushan Sirgur from Banglore, India. Currently, I am working as an Associate project in an IT company.

Leave a Reply