arrow left
Back to Developer Education

Building a Lyrics Search App using Vanilla JavaScript with OVH API

Building a Lyrics Search App using Vanilla JavaScript with OVH API

Not knowing the lyrics of a song is a problem most song-lovers encounter. In this article, we will create a platform where users can search for lyrics by entering the name of an artist or song title. <!--more--> We will create the lyrics web application using HTML5, CSS3, Vanilla JavaScript, async-await with fetch() method, OVH API, and ECMAScript 2015 (ES6) arrow functions.

Table of contents

Prerequisites

To follow along with this tutorial, you need:

  • A code editor such as Visual Studio Code.
  • Basic knowledge of HTML5, CSS, and JavaScript.
  • A computer with an internet connection.

Structuring the lyrics search app with HTML5

To begin, create a folder named lyrics-app, and add three files in the folder: lyrics.html, lyrics.css, and lyrics.js.

We will use HTML5 to structure the lyrics search app. This section deals with the lyrics.html.

In the head tag of the HTML file, you will input pre-defined meta tags that are essential for all web apps.

We will also link the CSS file to the HTML file and give the web app the title of Lyrics Search App.

Next, create a div with a class container. This div will contain other divs that will be created later.

Add another div with a class intro-text with two other h1 and h2 tags, respectively.

The content of the h1 tag is Learn your favorite song while the h2 tag will contain song lyrics.

Inside the div with a class container, you will create a div with an id of lyrics-search where we create a form containing an input field, and also another div to display fetched lyrics.

Your HTML code should look as follows:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" type="text/css" href="lyrics.css"/>
    <title>Lyrics Search App</title>
</head>
<body>
    <div class="container">
        <div class="intro-text">
            <h1>Learn your favorite</h1>
            <h2>song lyrics</h2>
        </div>
        <div id="lyrics-search">
            <form action="" id="searchMe">
                <input type="text" id="lyricSearch" placeholder="artist name or song title"/>
            </form>
            <div id="search-result">
                
            </div>
        </div>
    </div>
    <script src="lyrics.js">
        
    </script>
</body>
</html>

Designing the lyrics search app

The next step is to design the web app with CSS (Lyrics.css).

First, style the overall HTML, body, and the div with the class container which embodies all other divs.

html {
    box-sizing:border-box;
}

/**Use pseudo elements to set some static styles**/
*,
*:before,
*:after {
    margin:0;
    Padding:0;
}

body {
    background:#333333;
}

.container {
    margin:0 auto;
}

Next, style the contents of the body tag - starting from the text that defines what the web app does to the placeholder, and input field:

/**This is how placeholders are styled**/
::placeholder {
    color:gold;
}

We now need to style up the page description with the text Learn your favorite song lyrics as shown below:

/**Styling the intro text `div` which has the content of “learn your favorite song” lyrics**/
.intro-text {
    font-family: Verdana, Geneva, Tahoma, sans-serif;/**If the device doesn't have any of the first three font-family sans-serif will automatically be used **/
    padding:2rem 0;
    color:gold;
}

/**Styling the h1 header(learn your favourite):centering the h1 element**/
h1 {
    text-align:center;
    padding:1rem 0;
}

/**Styling the h1 header(learn your favourite):centering the h1 element**/
h2 {
    text-align:center;
    padding:1rem 0;
}
 /**You can use the comma-separated form of styling tags with the same properties. 

Centering the div container where the form and input field are embedded, using its id (lyrics-search).

#lyrics-search {
    text-align:center;
    align-items:center;
    margin:20px;
    padding:20px;
}

Finally, style the form and the input field as follows:

form {
    margin:0 auto;
    padding-left:10rem;
}

/**style the input field using its id(lyricSearch)**/
#lyricSearch {
    background-color: transparent;
    color:#eeeeee;
    outline:none;
    height:30px;
    width:64%;
    margin:0 auto;
    padding-right:2rem;
    font-size:16px;
    font-family:cursive;
    outline-style:none;
    border-top:none;
    border-left:none;
    border-right:none;
    border-bottom:1px solid #eeeeee;
}

We have now successfully designed the web page by adding colors, font sizes, font family, padding, and margin.

Here is what your web page should look like:

Screenshot for design

A brief introduction to OVH API

OVH API is a simple API that helps us retrieve the lyrics of a song. We use two parameters to fetch data (lyrics). These are:

  • Artist's name.
  • Title of the song.

When a request is made, data is returned in JSON format. We also get two status codes:

  • Status code 200 means that the API call is successful.
  • Status code 404 indicates that the API call failed.

You can read more about the OVH API here.

An example of the URL in action looks like this: https://api.lyrics.ovh/v1/Drake/Toosie Slide.

In the example above, Drake stands as the artist's name, and Toosie Slide is the song title.

Adding functionality with JavaScript

In your lyrics.js file, declare variables and use the DOM selectors to connect with elements in the lyrics.html file, using the code snippet below:

//defining variables
const form = document.getElementById("searchMe"); //target the form tag in the html file
const search = document.getElementById("lyricSearch"); //target the input field
const output = document.getElementById("search-result"); //target the output `div`

The desired API to retrieve data (lyrics) for this web app is OVH API.

Declare the API URL using the code below:

const api = "https://api.lyrics.ovh";

The next phase is to submit the form. You will define what would happen if the input field has a value or is empty.

To do this, create an event listener using DOM events to listen for a submit event. Note that we can't use the click event since we do not have a button.

Here is the code snippet for this functionality:

// Get Search Value
form.addEventListener("submit", e => {
    e.preventDefault();
    searchValue = search.value.trim();

    if (!searchValue) {
        alert("Nothing to search");
    } else {
        startSearch(searchValue);
    }
})

In the code above:

  • You listened for a submit event after which you declared a variable searchValue to be equal to search.value.trim(). The trim() method simply removes whitespaces.

  • if the searchValue equals an empty string, the app shows an alert message, otherwise, it invokes the startSearch() function and takes the searchValue as an argument.

It is highly recommended to go through the OVH API documentation before proceeding.

Now, we can use async-await with the fetch method to retrieve data from the OVH lyrics API.

Here is the code snippet to fetch the data:

async function startSearch(searchValue) {
    const searchResult = await fetch(`${api}/suggest/${searchValue}`);
    const data = await searchResult.json();
    console.log(data);
    showData(data);
}

Testing the current state of the web app

We need to test if the web app is returning data from the OVH API when you input the title of a song or artist's name in the search field.

First, comment out the showData function in the code snippet above (remember to uncomment the showData function later).

Launch the web app using the live server vscode extension.

Type in a song in the search field (note that some suggested song lyrics are not available on this API).

Console log the result (To access the console, right-click inside the webpage, click the inspect option then navigate to the console in the chrome dev tools).

Your screen should be like the screenshot below:

Screenshot for consoled data

In the screenshot above, I searched for a song with the title of cast.

We need to create a function showData() that displays the data in the console. The showData() method is called from the startSearch() function.

Here is the code for the showData() function:

// Display Search Result
function showData(data) {
    output.innerHTML = `
    <ul class="lyrics">
      ${data.data
        .map(song=> `<li>
                    <div>
                        <strong>${song.artist.name}</strong> -${song.title} 
                    </div>
                    <span class="btn" data-artist="${song.artist.name}" data-songtitle="${song.title}">Get Lyrics</span>
                </li>`
        )
        .join('')}
    </ul>
  `;
}

The above function will display lyrics inside an empty div in the lyrics.html file.

Inner - HTML

This is the DOM property that either sets or retrieves the content of an HTML element.

We will set the content of the empty div in the lyrics.html file to display the lyrics' suggestions in a list form.

The data from the API has some set of objects with properties that we want to display on the webpage.

Our concern is how to display the song title and song artist's name on the webpage.

map() is one of the most used methods. It returns a new array based on the values of the existing array.

For example, we have a numbers array and we want to multiply each value by 3 and add them to a new array:

const numbers = [2 , 4, 6, 8];
const tripleNo = numbers.map(tripleNum);
function tripleNum(number) {
   return number * 3;
}
console.log(tripleNo);//logs [6,12,18,24]

Normally, to access the song title and artist's name, you would have invoked data.data.title for the song title and data.data.artist.name for the artist's name. If you recall, the argument - song represents the resulting data.

Since we have mapped the data, you can access the song title using song.title as well as the artist's name by using song.artist.name.

The following code helps us listen for a click event inside the output InnerHTML:

//event listener in get lyrics button
output.addEventListener('click', e=>{
    const clickedElement = e.target;

    //checking clicked element is button or not
    if (clickedElement.tagName === 'SPAN'){
        const artist = clickedElement.getAttribute('data-artist');
        const songTitle = clickedElement.getAttribute('data-songtitle');
        
        getLyrics(artist, songTitle);
    }
})

The code above helps to know if the clicked element is the span tag (i.e if the variable clickedElement contains span as tagName). If so, the statement in the if block is executed.

You will store the attribute data-song.title in the variable songTitle as well as the attribute data-artist in the variable artist, which the getLyrics() function takes in the two variables as parameters.

Note that arguments are the actual values passed to a function when it is invoked, while parameters are the values passed when a function is defined.

GetLyrics() - Async function

This is the most important function because it allows us to display the song lyrics.

The function takes in two parameters, artist and songTitle respectively. Recall that you can search for lyrics by inputting either the artist's name or the song title.

Below is the code for getLyrics() function:

async function getLyrics(artist, songTitle) {
    const response = await fetch(`${api}/v1/${artist}/${songTitle}`);
    const data = await response.json();
  
    const lyrics = data.lyrics;
    if (lyrics === undefined){
        alert('lyrics doesnt exist in this api');
        console.log('lyrics doesnt exist in this api');
    }
  
    output.innerHTML = `<h2><strong>${artist}</strong> - ${songTitle}</h2>
    <p id="lyrics-display">${lyrics}</p>`; 
}

Note, the OVH API doesn't have access to all the lyrics, under its free version. If you wish to have access to all the lyrics, I would suggest you get a paid version.

If a particular lyric is not available, it will show undefined in the div. It also alerts you that the lyrics are not available on the API.

Next, you can decide to implement Regular Expression (REGEX) syntax in the variable lyrics using the replace method by adding .replace(/(\r\n|\r|\n)/g ,'<br>'); to the lyrics variable:

const lyrics = data.lyrics.replace(/(\r\n|\r|\n)/g ,'<br>');

This will return well-aligned lyrics that can be displayed on the webpage.

REGEX usage helps to look through our data (lyrics) for:

  • Carriage returned alone.
  • Carriage returned with a new line.

If any of the instances defined above are found, the replace() method replaces it with the <br> (break line).

The /g is a regular expression flag, it means globally. The entire data (lyrics) should be searched through (for all matches).

The lyrics will be displayed in the paragraph tag when the span tag is clicked.

Styling and centering the lyrics

Navigate to your CSS file and add the code below to style and center the lyrics:

.lyrics {
    width: 70%;
    list-style: none;
    margin: 0 auto;
    padding: 2rem 0;
}

.lyrics li {
    font-size: 1.4rem;
    text-align: center;
    display: flex;
    justify-content: center;
    align-items: center;
    padding: 5px 0;
    border-bottom: 1px solid  gold;
}

.lyrics li span {
    font-size: 1.4rem;
    padding: 5px;
    margin: 5px;
    cursor: pointer;
}

.lyrics li span:hover {
    background-color: lightyellow;
}

/*styling the button to get the lyrics*/
.btn {
    padding: 4px;
    display: flex;
    justify-content: center;
    align-items: center;
    text-align: center;
    outline: none;
    border-radius: 3px;
    text-decoration: none;
    font-size: 1.2rem;
    cursor: pointer;
    background-color: gold;
    color: white;
}

You can find the full JavaScript code here:

//defining the variables
const form = document.getElementById("searchMe");//target the form tag in the html file
const search = document.getElementById("lyricSearch");//target th input field
const output = document.getElementById("search-result");

const api = "https://api.lyrics.ovh";

//structuring how the result will be displayed using the suggestion mode the API supports
function showData(data) {
    output.innerHTML = `
    <ul class="lyrics">
      ${data.data
        .map(song=> `<li>
                    <`div`>
                        <strong>${song.artist.name}</strong> -${song.title} 
                    </`div`>
                    <span class="btn" data-artist="${song.artist.name}" data-songtitle="${song.title}">Get Lyrics</span>
                </li>`
        )
        .join('')}
    </ul>
  `;
}

//declaring async function to fetch data from api
async function startSearch(searchValue) {
    const searchResult = await fetch(`${api}/suggest/${searchValue}`);
    const data = await searchResult.json();

    showData(data);
}

//calling the function that gets and displays the lyrics
async function getLyrics(artist, songTitle) {
    const response = await fetch(`${api}/v1/${artist}/${songTitle}`);
    const data = await response.json();
  
    const lyrics = data.lyrics;
    if (lyrics === undefined){
        alert('lyrics doesnt exist in this api');
        console.log('lyrics does not exist in this api');
    }
  
    output.innerHTML = `<h2><strong>${artist}</strong> - ${songTitle}</h2>
    <p id="lyrics-display">${lyrics}</p>`;
  
}

//listening if the clicked event is on the span tag, so lyrics can be called and displayed
output.addEventListener('click', e=>{
    const clickedElement = e.target;

    //checking clicked element is button or not
    if (clickedElement.tagName === 'SPAN'){
        const artist = clickedElement.getAttribute('data-artist');
        const songTitle = clickedElement.getAttribute('data-songtitle');
        
        getLyrics(artist, songTitle)
    }
})


//listening for a submit event

form.addEventListener("submit", e => {
    e.preventDefault();
    searchValue = search.value.trim();

    if (!searchValue) {
        alert("Nothing to search");
    } else {
        startSearch(searchValue);
    }
})

Conclusion

In this tutorial, we learned how to build a lyrics search app using HTML5, CSS3, Vanilla JavaScript, OVH API, alongside ES6 features.

You can, therefore, use this knowledge to craft other quality and productive applications.

You can find the full source code on this GitHub repository.


Peer Review Contributions by: Srishilesh P S

Published on: Feb 1, 2022
Updated on: Jul 12, 2024
CTA

Start your journey with Cloudzilla

With Cloudzilla, apps freely roam across a global cloud with unbeatable simplicity and cost efficiency