Create a World Holiday Search Engine using HTML, CSS, and JavaScript

Faraz

By Faraz -

Build a holiday search engine using HTML, CSS, and JavaScript. Explore worldwide festivities with ease. Follow our step-by-step guide.


Create a World Holiday Search Engine using HTML, CSS, and JavaScript.jpg

Table of Contents

  1. Project Introduction
  2. HTML Code
  3. CSS Code
  4. JavaScript Code
  5. Preview
  6. Conclusion

In this blog post, we'll guide you through creating a web application that allows users to explore holidays celebrated worldwide. Whether you're a seasoned developer or just starting, our step-by-step instructions will help you build a user-friendly holiday lookup tool using HTML, CSS, and JavaScript.

Firstly, Sign up for Calendarific API

  1. Go to the Calendarific API website and sign up for an API key.
  2. Once you have the API key, you can use it to make requests to the Calendarific API.

Let's start making an amazing world holiday lookup using HTML, CSS, and JavaScript step by step.

Join My Telegram Channel to Download the Project Source Code: Click Here

Prerequisites:

Before starting this tutorial, you should have a basic understanding of HTML, CSS, and JavaScript. Additionally, you will need a code editor such as Visual Studio Code or Sublime Text to write and save your code.

Source Code

Step 1 (HTML Code):

To get started, we will first need to create a basic HTML file. In this file, we will include the main structure for our holiday search engine.

After creating the files just paste the following codes into your file. Make sure to save your HTML document with a .html extension, so that it can be properly viewed in a web browser.

Let's break down each part of the code:

1. <!DOCTYPE html>: This declaration specifies the document type and version of HTML being used, which is HTML5 in this case.

2. <html lang="en">: This is the opening tag for the HTML document. It specifies the language of the document as English ("en").

3. <head>: This is the head section of the HTML document, which contains meta-information about the web page and links to external resources. Inside the <head>, you have:

  • <meta charset="UTF-8">: This meta tag specifies the character encoding of the document as UTF-8, which includes a wide range of characters and symbols from various languages.
  • <meta http-equiv="X-UA-Compatible" content="IE=edge">: This meta tag instructs Internet Explorer to use the latest rendering engine available (edge mode).
  • <meta name="viewport" content="width=device-width, initial-scale=1.0">: This meta tag sets the viewport settings for responsive web design. It ensures that the web page adapts to different screen sizes and devices.
  • <title>World Holiday Lookup</title>: This sets the title of the web page, which is displayed in the browser's title bar or tab.
  • <link rel="icon" href="assets/favicon.ico" type="image/xicon">: This specifies the website's favicon, the small icon displayed in the browser tab.
  • <link rel="stylesheet" href="styles.css">: This links an external CSS (Cascading Style Sheets) file called "styles.css" to style the web page.
  • <script src="https://code.jquery.com/jquery-3.6.4.min.js" integrity="sha256-oP6HI9z1XaZNBrJURtCoUT5SUnxFr8s3BzRl+cbzUq8=" crossorigin="anonymous"></script>: This includes the jQuery library from a content delivery network (CDN). jQuery is a JavaScript library that simplifies DOM manipulation and event handling.
  • <script defer src="script.js"></script>: This includes an external JavaScript file called "script.js" with the "defer" attribute, which means it will be executed after the HTML content is parsed.

4. <body>: This is the body section of the HTML document, which contains the visible content of the web page. Inside the <body>, you have:

  • Various elements like headings, labels, input fields, buttons, and a form that make up the user interface for a holiday lookup tool.
  • <main id="card-container">: This is a placeholder for the main content of the web page. It will be populated dynamically by JavaScript when the user interacts with the page.

This is the basic structure of our holiday search engine using HTML, and now we can move on to styling it using CSS.

Step 2 (CSS Code):

Once the basic HTML structure of the holiday search engine is in place, the next step is to add styling to the web app using CSS.

Next, we will create our CSS file. In this file, we will use some basic CSS rules to style our web app. Let's break down each section of the code:

1. Styling the Body:

  • margin: auto 0;: This centers the content horizontally by setting auto margin for the left and right margins.
  • text-align: center;: This centers the text within the body.
  • background-image: Sets a background image for the body.
  • background-color: lightblue;: Sets the background color of the body to light blue.
  • font-family: sans-serif;: Specifies a sans-serif font for the text in the body.

2. Styling the Form:

  • background: rgb(157, 221, 221);: Sets the background color of the form to a specific shade of light blue.
  • width: 500px;: Sets the width of the form to 500 pixels.
  • margin: 0 auto;: Centers the form horizontally.
  • padding: 5px;: Adds padding around the form.
  • border-radius: 10px;: Rounds the corners of the form.
  • display: grid;: Turns the form into a grid container.
  • grid-template-columns and grid-template-rows: Specifies the grid layout with two columns and five rows.

3. Styling the Button Container:

  • grid-column: span 2;: Makes the button container span two columns in the grid.
  • display: flex;: Makes the button container a flex container.
  • flex-direction: row-reverse;: Reverses the order of items in the container horizontally.
  • justify-content: space-around;: Distributes space evenly around the items in the container.

4. Styling the Main Section:

  • background: rgb(157, 221, 221);: Sets the background color of the main section to the same light blue as the form.

5. Styling Headings and Paragraphs:

  • h1: Removes margin and padding from the h1 element.
  • p, h3: Removes margin and adds padding to paragraphs and h3 elements.

6. Styling Input and Select Elements:

  • input and select: Styles input and select elements with specific width, background color, and no borders.

7. Styling Section Elements:

  • section: Styles section elements as inline-block elements with specific width, height, margins, borders, and background color.

8. Styling Buttons:

  • button: Centers buttons within their containers.

9. Styling Placeholder Text:

  • ::placeholder: Styles the placeholder text inside input elements with padding.

10. Styling the Title:

  • #title: Styles a title element with a specific background color, width, margins, and padding.
  • #title p and #title h1: Further styles the elements inside the title container.

11. Styling Buttons with IDs:

  • #input-button, #today-button, and #reset-button: Styles buttons with specific IDs, setting borders, width, height, background color, and border radius.

12. Styling the Card Container:

  • #card-container: Styles a container for cards with specific margins, width, border radius, and flex layout.

13. Styling a Class:

  • .first-choice: Styles elements with the class "first-choice" by changing their text color.

14. Media Query for Responsive Design:

  • @media only screen and (max-width: 650px): This media query applies specific styles when the screen width is 650 pixels or less. It adjusts the width and layout of the sections and the form to make the page responsive on smaller screens.

This will give our holiday search engine an upgraded presentation. Create a CSS file with the name of styles.css and paste the given codes into your CSS file. Remember that you must create a file with the .css extension.

body {
  margin: auto 0;
  text-align: center;
  background-image: url('https://static.vecteezy.com/system/resources/thumbnails/006/858/865/small/squared-paper-seamless-pattern-for-school-notebook-millimeter-graph-paper-grid-graph-4x4-per-inch-notebook-for-writing-hieroglyphs-editable-stroke-illustration-on-white-background-free-vector.jpg');
  background-color: lightblue;
  font-family: sans-serif;
}

form{
  background: rgb(157, 221, 221);

  width: 500px;
  margin: 0 auto;
  padding: 5px;
  border-radius: 10px;

  display: grid;
  grid-template-columns: 40% 60%;
  grid-template-rows: 5;
}

#button-container {
  grid-column: span 2;

  display: flex;
  flex-direction: row-reverse;
  justify-content: space-around;

}

main {
  background: rgb(157, 221, 221);
}

h1 {
  padding: 0;
  margin: 0;
}

p, h3 {
  padding: 0 10px;
}

input {
  margin: 5px;
  width: 250px;
  background-color: rgb(250, 237, 215);
  border: none;
}

select {
  margin: 5px;
  width: 254px;
  background: rgb(250, 237, 215);
  border: none;
}

section {
  display: inline-block;
  text-align: center;

  width: 30%;
  height: 325px;

  margin: 5px;
  border: 1px solid black;
  border-radius: 10%;
  background: rgb(250, 237, 215);
}


button {
  place-self: center;
}

::placeholder {
  padding: 0 0 0 3px;
}

#title {
  background-color: rgb(157, 221, 221);
  border-radius: 5px;
  width: 300px;
  margin: 0 auto 10px auto;
  padding: 0 0 5px 0;
}

#title p {
  padding: 5px 0 0 0;
}

#title h1 {
  padding: 0 0 10px 0;
}

#input-button, #today-button, #reset-button{
  border: 1px solid black;
  width: 150px;
  height: 20px;
  background: rgb(205, 235, 238);
  border-radius: 5px;
}

#card-container {
  margin: 20px auto;
  width: 80%;
  border-radius: 20px;

  display: flex;
  flex-flow: wrap;
  justify-content: center;
}

.first-choice {
  color: rgb(119,119,119);
}

@media only screen and (max-width: 650px) {
  section {
      width: 90%;
      height: 300px
  }

  form {
      width: 300px;
      margin: 0 auto;
      
      display: grid;
      grid-template-columns: 1fr;
      grid-template-rows: auto;
      justify-items: center;
  }

  #button-container {
      grid-column: span 1;
      flex-direction: column-reverse;
      padding: 5px 0 0 0;
  }
} 

Step 3 (JavaScript Code):

Finally, we need to create a function in JavaScript. This JavaScript code is part of a web application that allows users to input a country, year, month, and day and then retrieve and display information about holidays in that country on the specified date. Below is an explanation of the key parts of the code:

1. API Key: The variable k stores an API key from calendarific.com. This key is used to authenticate and authorize requests to the Calendarific API.

2. DOM Elements: Several DOM elements are selected and stored in variables using document.getElementById and jQuery's $ function. These elements are associated with various input fields and buttons on the web page.

3. Default Year: The variable today is initialized with the current date. The year input field is then set to the current year by extracting the year from today.

4. Event Handlers: Event handlers are set up for various elements in the DOM. These handlers trigger specific functions when certain events occur, such as clicking a button or submitting a form.

  • #today-button: When the "Today" button is clicked, the useToday function is called.
  • #reset-button: When the "Reset" button is clicked, the clearHolidays function is called.
  • form: When the form is submitted, the handleGetHolidays function is called.

5. API Calls:

  • handleGetCountries: This function makes an AJAX request to the Calendarific API to retrieve a list of countries. The retrieved data is used to populate a dropdown menu.
  • handleGetHolidays: This function is called when the form is submitted. It performs validation on the user's input (e.g., checking for leap years and valid dates) and then makes an API request to retrieve holiday information for the specified country and date.

6. Render Holiday Cards: After receiving a response from the API, the renderHoliday function is called to display the holiday information. It creates and appends HTML elements to display the holiday details in cards.

7. Utility Functions:

  • createCard: This function creates a new card element to display holiday information.
  • removeCards: This function removes all existing holiday cards from the page.
  • clearHolidays: This function is called to clear any displayed holiday cards when the "Reset" button is clicked.
  • nameFromIso: This function maps an ISO country code to the corresponding country name using the countryList data retrieved from the API.

8. useToday Function: This function is called when the "Today" button is clicked. It sets the month and day input fields to the current month and day, respectively.

Create a JavaScript file with the name script.js and paste the given codes into your JavaScript file and make sure it's linked properly to your HTML document so that the scripts are executed on the page. Remember, you’ve to create a file with .js extension.

k = `Your calendarific.com API Key`;

const userCountry = document.getElementById('country-input');
const userYear = document.getElementById('year-input');
const userMonth = document.getElementById('month-input');
const userDay = document.getElementById('day-input');

let today = new Date();
userYear.value = today.getFullYear();

const $cardContainer = $('#card-container');

let cardCount = 0;
let display = false;
let countryList = [];
let holidayList = [];

handleGetCountries();

$('#today-button').on('click', useToday);
$('#reset-button').on('click', clearHolidays);
$('form').on('submit', handleGetHolidays);

// API call for country list
function handleGetCountries() {
    $.ajax({
        url: `https://calendarific.com/api/v2/countries?&api_key=${k}`
    }).then(
        (data) => {
            countryList = data.response.countries;
            countryDropdown();
        },
        (error) => {
            console.log('bad request', error);
        }
    );
}

function countryDropdown() {
    let fragment = document.createDocumentFragment();
    countryList.forEach(country => {

        let opt = document.createElement('option');
        opt.innerHTML = country.country_name;
        opt.value = country['iso-3166'];
        opt.className = 'none';
        fragment.appendChild(opt);
    });
    userCountry.appendChild(fragment);
}

// API call for holidays
function handleGetHolidays(evt){
    evt.preventDefault();

    let leapYear = false;
    if ((0 == userYear.value % 4) && (0 != userYear.value % 100) || (0 == userYear.value % 400)){
        leapYear = true;
    }

    if (userCountry.value === 'Please Choose a Country') {
        alert('You must choose a country first!')
    } else if (!userYear.value) {
        alert('You must choose a year first!')
    } else if (!leapYear && userMonth.value === '2' && userDay.value > 28) {
        alert('February ends on the 28th unless it is a leap year. Please choose a valid date.')
    } else if (leapYear && userMonth.value === '2' && userDay.value>29) {
        alert(`The year ${userYear.value} is a Leap Year! February only gets one extra day though. Please choose a valid date.`)
    }else if (userDay.value === '31' && (userMonth.value === '4' || userMonth.value === '6' || userMonth.value === '9' || userMonth.value === '11')){
        alert(`The month in question does not have 31 days. Please choose a valid date.`)
    } else {
        $.ajax({
            url: `https://calendarific.com/api/v2/holidays?&api_key=${k}&country=${userCountry.value}&year=${userYear.value}&month=${userMonth.value}&day=${userDay.value}`
        }).then(
            (data) => {
                holidayList = data.response.holidays;
                if (holidayList === undefined) {
                    let countryName = nameFromIso(userCountry.value);
                    alert(`There is no data for ${countryName} during ${userYear.value}.  Please input another year.`)
                } else {
                renderHoliday();
                }
            },
            (error) => {
                console.log('bad request', error);
            }
        );
    }
}

function renderHoliday(){
    if (holidayList.length > 0) {
        holidayList.forEach(holiday => {
            createCard();

            let $cardDate = $(`#card-date-${cardCount}`);
            let $cardType = $(`#card-type-${cardCount}`);
            let $cardName = $(`#card-name-${cardCount}`);
            let $cardDesc = $(`#card-desc-${cardCount}`);

            $cardDate.text(holiday.date.iso.slice(0,10));
            $cardType.text(holiday.primary_type)
            $cardName.text(holiday.name);
            $cardDesc.text(holiday.description);
        });
    } else {
        createCard();

        let $cardDate = $(`#card-date-${cardCount}`);
        let $cardType = $(`#card-type-${cardCount}`);
        let $cardName = $(`#card-name-${cardCount}`);
        let $cardDesc = $(`#card-desc-${cardCount}`);

        let countryName = nameFromIso(userCountry.value);

        $cardDate.text(`${userYear.value}-${userMonth.value}-${userDay.value}`);
        $cardType.text(countryName)
        $cardName.text('None');
        $cardDesc.text(`Sadly, there is no official reason to celebrate in ${countryName} on the date in question :( \n We hope you still find many personal reasons to party!`);
    }
    display = true;
}

function createCard() {
    if (display) {
        removeCards();
    }
    
    cardCount++;
    let newCard = document.createElement('section');

    newCard.setAttribute('id',`card-${cardCount}`);
    newCard.innerHTML = `<span id='card-date-${cardCount}'></span><br><br><span id='card-type-${cardCount}'></span><h3 id='card-name-${cardCount}'>New Card</h3>
    <p id='card-desc-${cardCount}'>New Desc</p>`;

    $cardContainer.append(newCard);
}

function removeCards() {
    $cardContainer.empty();
    cardCount = 0;
    display = false;
}

function clearHolidays(evt) {
    evt.preventDefault();

    removeCards();
}

function nameFromIso(iso) {
    let countryName = countryList.find(country => country['iso-3166'] === iso)
    return countryName.country_name
}

function useToday(evt) {
    evt.preventDefault();
    userMonth.value = today.getMonth() + 1
    userDay.value = today.getDate()

    userMonth.classList.remove('first-choice');
}

Final Output:

Create a World Holiday Search Engine using HTML, CSS, and JavaScript.gif

Conclusion:

In conclusion, this journey of creating a web application for exploring holidays worldwide has been both exciting and informative. By following the steps outlined in this guide, you've not only built a valuable resource for holiday enthusiasts but also enhanced your web development skills.

We hope this guide has been instrumental in your project's success. Now it's time to share your holiday lookup tool with the world and watch as it brings joy to users exploring festivities across the globe. Start your holiday adventure now!

Code by: Daniel Victory

Demo World Holiday Lookup!

That’s a wrap!

I hope you enjoyed this post. Now, with these examples, you can create your own amazing page.

Did you like it? Let me know in the comments below 🔥 and you can support me by buying me a coffee.

And don’t forget to sign up to our email newsletter so you can get useful content like this sent right to your inbox!

Thanks!
Faraz 😊

End of the article

Subscribe to my Newsletter

Get the latest posts delivered right to your inbox


Latest Post