[JavaScript] Sending AJAX Request to Django Backend for Spotify Music Search
Task
Create a search input and add an event listener to it in JavaScript. Whenever the search query changes, send a request to the view in the backend via url.
Code
// Function to Get Token
function getCookie(name) {
let cookieValue = null;
if (document.cookie && document.cookie !== "") {
const cookies = document.cookie.split(";");
for (let i = 0; i < cookies.length; i++) {
const cookie = cookies[i].trim();
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) === name + "=") {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
// Get Token
const csrftoken = getCookie("csrftoken");
// Send Request
const sendSearchRequest = (e) => {
result_box.innerHTML = "";
const searchWord = e.target.value;
// If there is a search query send request
if (searchWord) {
fetch("search_query/", {
method: "POST",
credentials: "same-origin",
headers: {
Accept: "application/json",
"X-Requested-With": "XMLHttpRequest",
"X-CSRFToken": csrftoken,
},
body: JSON.stringify({ "search-word": searchWord }),
})
.then((Response) => {
return Response.json();
})
.then((data) => {
const results = data.tracks.items;
// Create HTML element for each result entry
showResult(results);
let result_entries = document.querySelectorAll(".result_entry");
// Add event listener to each entry
for (const entry of result_entries) {
entry.addEventListener("click", (e) => addToForm(e));
}
});
When a response is received, using the showResult
function, display the result on the page and add event listener in order to add the music info to the form when clicked.
// Show Result
const showResult = (results) => {
results.map((song) => {
const img_url = song.album.images[0].url;
const artists_list = song.artists.map((x) => x.name);
const title_src = song.name;
const preview_url = song.preview_url;
const result_entry = document.createElement("div");
result_entry.classList.add("result_entry");
const cover_container = document.createElement("div");
const cover = document.createElement("img");
cover.src = img_url;
cover.alt = title_src;
cover_container.appendChild(cover);
result_entry.appendChild(cover_container);
const info = document.createElement("div");
info.classList.add("info");
const title = document.createElement("p");
title.classList.add("title");
title.textContent = `${title_src}`;
info.appendChild(title);
const artists = document.createElement("p");
artists_list.map((artist) => {
artists.textContent += `${artist} `;
});
artists.textContent.trim();
artists.classList.add("artists");
info.appendChild(artists);
const preview = document.createElement("audio");
preview.src = preview_url;
preview.controls = "controls";
info.appendChild(preview);
result_entry.appendChild(info);
result_box.appendChild(result_entry);
});
};
// Add to Preview Section and to Form
const addToForm = (e) => {
e.preventDefault();
musicChoice.innerHTML = "";
const music = e.target;
const cover_url = music.querySelector("img").src;
const title = music.querySelector(".title").textContent;
const artist = music.querySelector(".artists").textContent.trim();
const preview_url = music.querySelector("audio").src;
const selection_cover = document.createElement("img");
selection_cover.src = cover_url;
selection_cover.alt = title;
musicChoice.appendChild(selection_cover);
const selection_title = document.createElement("p");
selection_title.textContent = title;
musicChoice.appendChild(selection_title);
const selection_artist = document.createElement("p");
selection_artist.textContent = artist;
musicChoice.appendChild(selection_artist);
const selection_preview = document.createElement("audio");
selection_preview.src = preview_url;
selection_preview.controls = "controls";
musicChoice.appendChild(selection_preview);
// Create hidden input to the form
const cover_input = document.createElement("input");
cover_input.value = cover_url;
cover_input.name = "track_album_cover";
cover_input.type = "hidden";
postForm.appendChild(cover_input);
const title_input = document.createElement("input");
title_input.value = title;
title_input.name = "track_title";
title_input.type = "hidden";
postForm.appendChild(title_input);
const artist_input = document.createElement("input");
artist_input.value = artist;
artist_input.name = "track_artist";
artist_input.type = "hidden";
postForm.appendChild(artist_input);
const audio_input = document.createElement("input");
audio_input.value = preview_url;
audio_input.name = "track_audio";
audio_input.type = "hidden";
postForm.appendChild(audio_input);
search_query.value = "";
result_box.innerHTML = "";
};
In this process, if the event listener is added to each result, clicking certain parts of the div would not trigger the div, but the child element that is actually clicked. Therefore, in order to make this a clickable item as a whole div, css pseudo-element ::after
is used, to create a sort of a cover for the entire div.
.result_entry {
position: relative;
z-index: 0;
display: flex;
justify-content: space-around;
width: 50vw;
}
.result_entry p {
z-index: 0;
}
.result_entry::after {
content: "";
position: absolute;
top: 0;
left: 0;
z-index: 5;
height: 100%;
width: 100%;
}