Reputation: 193
I have a JavaScript code that gets the lyrics of a song that is currently playing through an API.
Sometimes (not always) the lyric returns the title at the beginning which is what I want to remove.
Sometimes the title at the beginning is in uppercase, other times in uppercase and lowercase.
Example:
SWEET CHILD O' MINE
She's got a smile that it seems to me
Reminds me of childhood memories
Where everything was as fresh as the bright blue sky
Now and then when I see her face
She takes me away to that special place
And if I stare too long, I'd probably break down and cry
........
I have created a somewhat cumbersome code that removes the title from the beginning with success.
I want to see if they help me simplify that code in fewer lines.
I will share the part of the code that interests us to facilitate the help, if you want all the code I have no problem sharing it.
currentSong
contains the title of the song that is playing
lyric
contains full lyric obtained with the API
this.refreshLyric = function(currentSong, currentArtist) {
//another code that does not interest
//...
//...
//lyric variable contains the complete lyrics of a song obtained through an API
var lyric = data.mus[0].text;
//divide the string CurrentSong (contains the song title) into parts
let splitCurrenSong = currentSong.split(' ');
//I get the length of the array
let largeCurrentSong = splitCurrenSong.length;
//divide the string lyric into parts
let splitLyric = lyric.split(' ');
//I get the first elements of the lyric array with the length limit of largeCurrentSong
let pieceLyric = splitLyric.slice(0, largeCurrentSong);
//I get all elements of the splitCurrenSong array
let pieceSong = splitCurrenSong.slice(0, largeCurrentSong);
//join arrays
let joinLyric = pieceLyric.join(' ');
let joinSong = pieceSong.join(' ');
//I check if the chunk of the joinLyric string matches the same chunk of joinSong
if (joinLyric.toLocaleLowerCase() == joinSong.toLocaleLowerCase()) {
//remove the matching items
splitLyric.splice(0, largeCurrentSong);
//put the resulting join array into a variable
lyrics = splitLyric.join(' ');
//remove the spaces from the beginning and end of lyrics
lyric = lyrics.trim()
}
//another code that does not interest
//...
//...
}
EDIT: to reply to @iamaword
As shown in the screenshot of the API return:
text:
contains the lyrics of the complete song
name:
song title
I can perfectly get the name of the song with this line:
var nameSong = data.mus[0].name
But I don't think it's necessary since I get the name of the song from the currentSong
variable, which is the one sent in the GET
command to get the lyric.
FINAL EDIT: credits to @CerebralFart
full code:
this.refreshLyric = function(currentSong, currentArtist) {
var proxy_URL = PROXYURL;
var vagalume_api = 'https://api.vagalume.com.br/search.php?';
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState === 4) {
if (this.status === 200) {
var data = JSON.parse(this.responseText);
if (data.type === 'exact' || data.type === 'aprox') {
var lyric = normalizeText(data);
document.getElementById('lyric').innerHTML = lyric.replace(/\n/g, '<br />');
var openLyric = document.getElementsByClassName('lyrics')[0];
openLyric.style.opacity = "1";
openLyric.setAttribute('data-toggle', 'modal');
var powered = "Vagalume"
var URL_lyric = 'https://www.vagalume.com.br';
//Powered by image src...
const parent = document.querySelector('.chartlyrics');
parent.innerHTML = '';
var img = document.createElement("img");
img.src = "img/103-fundo-escuro.jpg"
img.setAttribute('class', "")
parent.appendChild(img);
parent.appendChild(document.createElement('br'));
parent.append('Powered by ');
// Powered by link a href...
document.getElementById('powered_by').innerHTML = ''
var a = document.getElementById('powered_by')
.appendChild(document.createElement("a"));
a.href = URL_lyric;
a.target = "_blank";
a.rel = "noopener noreferrer";
a.textContent = powered;
} else {
var page = new Page();
page.refreshLyric2(currentSong, currentArtist);
}
} else {
var page = new Page();
page.refreshLyric2(currentSong, currentArtist);
}
}
}
xhttp.open('GET', proxy_URL + vagalume_api + API_KEY + '&art=' + currentArtist + '&mus=' + currentSong.toLowerCase(), true);
xhttp.send()
}
function normalizeText(response){
// First unpack the data, get the right name and text values
let {mus:[{name, text}]} = response;
// Now get the part of the text that might be the title
let titleLength = name.length;
let maybeTitle = text.substring(0, titleLength);
// Compare the two titles and trim if they match
if (name.toLowerCase() === maybeTitle.toLowerCase() && exceptions.includes(maybeTitle.toLowerCase()) == false){
text = text.substring(titleLength)
}
//Remove any leading or trailing whitespace and return
return text.trim();
}
//song names excepted from being removed in lowercase ['one song', 'two song', etc..]
const exceptions = ['sweet emotion'];
I have created a list of song names excepted from being removed, in case any of them mention the song title as part of the lyric.
This is the case for example of the well-known Aerosmith - Sweet Emotion song.
Sweet emotion
Sweet emotion
You talk about things and nobody cares
You're wearing other things that nobody wears
You're calling my name but you gotta make clear
I can't say baby where I'll be in a year
.....
I added a new condition to the normalizeText
function to check if the name of the song to be removed is not within the exceptions.
// Compare the two titles and trim if they match
if (name.toLowerCase() === maybeTitle.toLowerCase() && exceptions.includes(maybeTitle.toLowerCase()) == false){
And I created a constant exceptions
where the name of the songs in lowercase must be added manually separated by commas.
//song names excepted from being removed in lowercase ['one song', 'two song', etc..]
const exceptions = ['sweet emotion'];
Upvotes: 4
Views: 327
Reputation: 3490
There are a few ways in which your code can be cleaned up, mainly in how you unpack the data and in how you compare the two strings.
function normalizeText(response){
// First unpack the data, get the right name and text values
let {mus:[{name, text}]} = response;
// Now get the part of the text that might be the title
let titleLength = name.length;
let maybeTitle = text.substring(0, titleLength);
// Compare the two titles and trim if they match
if (name.toLowerCase() === maybeTitle.toLowerCase()){
text = text.substring(titleLength)
}
//Remove any leading or trailing whitespace and return
return text.trim();
}
EDIT: sintax error toLowerCase added ()
Upvotes: 1