Last active
February 11, 2025 21:30
-
-
Save chappy84/86eb4aeeca7fff5f5ae79ee451ecc4cd to your computer and use it in GitHub Desktop.
Provide last.fm links, and optionally scrobble stats, on albumoftheyear.org
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name Album of the Year Last.fm integration | |
// @namespace https://www.albumoftheyear.org/ | |
// @version 0.2.1 | |
// @description Adds link to a user's scrobble pages for artist and album names | |
// @author tomc.dev | |
// @match https://www.albumoftheyear.org/* | |
// @license MIT | |
// @icon https://www.google.com/s2/favicons?sz=64&domain=albumoftheyear.org | |
// @downloadURL https://gist.github.com/chappy84/86eb4aeeca7fff5f5ae79ee451ecc4cd/raw/albumoftheyear.org-last.fm-integration.user.js | |
// @updateURL https://gist.github.com/chappy84/86eb4aeeca7fff5f5ae79ee451ecc4cd/raw/albumoftheyear.org-last.fm-integration.user.js | |
// @supportURL https://gist.github.com/chappy84/86eb4aeeca7fff5f5ae79ee451ecc4cd | |
// @grant GM_getValue | |
// @grant GM_setValue | |
// @grant GM_addValueChangeListener | |
// ==/UserScript== | |
(async function() { | |
'use strict'; | |
String.prototype.ucFirst = function() { | |
return this.charAt(0).toUpperCase() + this.substring(1); | |
} | |
function encodeForUrl(name) { | |
return encodeURIComponent(name).replace(/(%20)+/g, '+').replace(/%26amp%3B/g, '&'); | |
} | |
// GM_ functions aren't defined in Userscripts on iOS, so fall back to localStorage instead. | |
if (typeof GM_getValue == 'undefined') { | |
// defining by reference to localStorage.getItem breaks iOS, thus wrapper arrow function | |
window.GM_getValue = (key) => { | |
return localStorage.getItem(key); | |
}; | |
} | |
if (typeof GM_setValue == 'undefined') { | |
window.GM_setValue = (key, val) => { | |
localStorage.setItem(key, val); | |
}; | |
} | |
// Code Configuration | |
class LastFmConfig { | |
#storageKeyApiKey = 'lastFmApiKey'; | |
#storageKeyUsername = 'lastFmUsername'; | |
constructor(remoteChangeCallback) { | |
// If the user changes the values in another tab, we want to ensure everything is ok in this tab too. | |
if (remoteChangeCallback && typeof GM_addValueChangeListener != 'undefined') { | |
GM_addValueChangeListener(this.#storageKeyUsername, (key, oldValue, newValue, remote) => { | |
if (remote) { | |
remoteChangeCallback(); | |
} | |
}); | |
GM_addValueChangeListener(this.#storageKeyApiKey, (key, oldValue, newValue, remote) => { | |
if (remote) { | |
remoteChangeCallback(); | |
} | |
}); | |
} | |
} | |
get username() { | |
return GM_getValue(this.#storageKeyUsername); | |
} | |
set username(username) { | |
GM_setValue(this.#storageKeyUsername, username); | |
} | |
/** | |
* Last FM API Key. | |
* Register for your own!! https://www.last.fm/api/account/create | |
* | |
* Definitely don't source one from, say, the code of the Chrome Web Scrobbler extension: | |
* https://github.com/web-scrobbler/web-scrobbler/blob/master/src/core/scrobbler/lastfm/lastfm-scrobbler.ts#L21-L24 | |
*/ | |
get apiKey() { | |
return GM_getValue(this.#storageKeyApiKey); | |
} | |
set apiKey(apiKey) { | |
GM_setValue(this.#storageKeyApiKey, apiKey); | |
} | |
get webBaseUrl() { | |
return `https://www.last.fm/${this.username ? `user/${this.username}/library/` : ''}music/`; | |
} | |
getWebUrl(artist, album, track) { | |
return `${this.webBaseUrl}${encodeForUrl(artist)}${album != undefined ? `/${encodeForUrl(album)}` : ''}`; | |
} | |
get apiBaseUrl() { | |
return `https://ws.audioscrobbler.com/2.0/?username=${this.username}`; | |
} | |
getApiAlbumUrl(artist, album) { | |
return this.getApiUrl('album.getinfo', {artist: artist, album: album}); | |
} | |
getApiArtistUrl(artist) { | |
return this.getApiUrl('artist.getinfo', {artist: artist}); | |
} | |
// getApiTrackUrl(artist, track) { | |
// return this.getApiUrl('track.getinfo', {artist: artist, track: track}); | |
// } | |
getApiUrl(method, params) { | |
let baseUrl = `${this.apiBaseUrl}&method=${method}&api_key=${this.apiKey}&format=json`; | |
if (params != undefined) { | |
let paramArr = []; | |
for (const [name, value] of Object.entries(params)) { | |
paramArr.push(`${encodeForUrl(name)}=${encodeForUrl(value)}`); | |
} | |
baseUrl += `&${paramArr.join('&')}`; | |
} | |
return baseUrl; | |
} | |
get showPlayCounts() { | |
return this.username && this.apiKey; | |
} | |
} | |
const cardinals = { | |
'B': Math.pow(10, 9), | |
'M': Math.pow(10, 6), | |
'K': Math.pow(10, 3), | |
}; | |
function formatPlayCount(playCount) { | |
for (const [suffix, divisor] of Object.entries(cardinals)) { | |
if (playCount >= divisor) { | |
return (playCount / divisor).toFixed(1) + suffix; | |
} | |
} | |
return playCount; | |
} | |
const linkTypeAlbum = 'album'; | |
const linkTypeArtist = 'artist'; | |
const iconSuffixArtist = 'user-music'; | |
const lastFmConfig = new LastFmConfig(refreshPageLinks); | |
async function getJson(url) { | |
try { | |
const response = await fetch(url); | |
if (!response.ok) { | |
throw new Error(`Response status: ${response.status}`); | |
} | |
return await response.json(); | |
} catch (error) { | |
console.error(error.message); | |
return {}; | |
} | |
} | |
async function getArtistPlayCount(artistName) { | |
if (!lastFmConfig.showPlayCounts) { | |
return ''; | |
} | |
const json = await getJson(lastFmConfig.getApiArtistUrl(artistName)); | |
return (json.artist && json.artist.stats && json.artist.stats.userplaycount | |
? formatPlayCount(json.artist.stats.userplaycount) : 0) | |
+ ''; | |
} | |
async function getAlbumPlayCount(artistName, albumName) { | |
if (!lastFmConfig.showPlayCounts) { | |
return ''; | |
} | |
const json = await getJson( | |
lastFmConfig.getApiAlbumUrl(artistName, albumName) | |
); | |
let playCount = (json.album && json.album.userplaycount ? json.album.userplaycount : 0) + ''; | |
if (json.album && json.album.tracks && json.album.tracks.track && json.album.tracks.track.length) { | |
playCount += ` / ${formatPlayCount(json.album.tracks.track.length || 0)}`; | |
} | |
return playCount; | |
} | |
function addItemPageLink(parentDiv, type, artistName, albumName) { | |
const isAlbumLink = type == linkTypeAlbum; | |
const linkTitle = `Last.fm${type ? ' ' + type.ucFirst() : ''}`; | |
const link = document.createElement('div'); | |
link.dataset.lastFm = type; | |
link.className = 'albumLinksFlex'; | |
link.innerHTML = `<a href="${lastFmConfig.getWebUrl(artistName, albumName)}" rel="nofollow" target="_blank" title="${linkTitle}"><div class="albumButton lastfm"> | |
<i class="fab fa-lastfm"></i>${type ? `<i class="fa-regular fa-${isAlbumLink ? linkTypeAlbum : iconSuffixArtist}"></i>` : ''} | |
<span>${linkTitle}</span> | |
</div></a>`; | |
parentDiv.appendChild(link); | |
return link; | |
} | |
function addPlayCountToItemPageLink(link, playCount, isAlbumLink) { | |
if (isAlbumLink && playCount.length && -1 == playCount.indexOf(' / ')) { | |
const albumLengthSelectors = ['.trackListTable > tbody > tr', '.trackList > ol > li']; | |
let albumLength = 0; | |
for (let i = 0; i < albumLengthSelectors.length; i++) { | |
albumLength = document.querySelectorAll(albumLengthSelectors[i]).length; | |
if (albumLength) { | |
break; | |
} | |
} | |
playCount += ` / ${albumLength}`; | |
} | |
const countSpan = document.createElement('span'); | |
countSpan.className = 'count'; | |
countSpan.innerHTML = playCount; | |
const linkText = link.querySelector('.lastfm > span'); | |
// Colon needs to be in span, so it's hidden on smaller screens | |
linkText.appendChild(document.createTextNode(': ')); | |
linkText.parentNode.appendChild(countSpan); | |
} | |
function addCommonStyle() { | |
const pagesStyleId = 'lastFmCommonStyle'; | |
if (!document.getElementById(pagesStyleId)) { | |
const style = document.createElement('style'); | |
style.id = pagesStyleId; | |
style.textContent = ` | |
:root { | |
/* Colours sourced from last.fm website css | |
Default last.fm colour */ | |
--color-last-fm-scarlet: #b90000; | |
/* lighter last.fm colour to make ratings page links easier on the eyes */ | |
--color-last-fm-habanero: #f71414; | |
} | |
@media screen and (min-width: 0) and (max-width: 1023px) { | |
/* Little fixes for site css that makes these not display quite right on small screens | |
Extra 0.333% takes it up to 1/3 of the width, including the 1% L/R margin */ | |
.albumButton { | |
width: 31.333%; | |
} | |
/* These elements use :first-child in the site css, as as there's | |
up to two, but with only one, it doesn't look right */ | |
.albumLinksFlex { | |
margin-right: 10px; | |
} | |
.albumLinksFlex:last-child { | |
margin-right: 0; | |
} | |
} | |
`; | |
document.head.appendChild(style); | |
} | |
} | |
function addPrefsDialogBox() { | |
const dialogElementId = 'lastfmSaveDialog'; | |
if (!document.getElementById(dialogElementId)) { | |
const style = document.createElement('style'); | |
style.id = 'lastFmDialogStyle'; | |
style.textContent = ` | |
/* Ensure the rest of the page can't be interacted with when the dialog is displayed */ | |
*:has(~ dialog#lastfmSaveDialog[open]):first-of-type::after { | |
content: ""; | |
position: fixed; | |
top: 0; | |
left: 0; | |
bottom: 0; | |
right: 0; | |
display: block; | |
background-color: rgba(50, 50, 50, 0.4); | |
backdrop-filter: blur(5px); | |
z-index: 2147483648; /* 1 more than the page header (2^31) */ | |
} | |
.dark *:has(~ dialog#lastfmSaveDialog[open]):first-of-type::after { | |
background-color: rgba(128, 128, 128, 0.4); | |
} | |
#lastfmSaveDialog { | |
min-width: 30%; | |
margin: auto; | |
padding: 20px; | |
z-index: 2147483649; /* 2 more than the page header (one over 2^31) */ | |
top: 0; | |
right: 0; | |
bottom: 0; | |
left: 0; | |
border-color: #323232; | |
border-radius: 10px; | |
} | |
#lastfmSaveDialog #lastfmClose { | |
position: absolute; | |
top: 20px; | |
right: 20px; | |
border-radius: 50%; | |
width: 2em; | |
height: 2em; | |
/* Fixes poor positioning of x on iOS */ | |
padding: 0; | |
} | |
#lastfmSaveDialog label, | |
#lastfmSaveDialog input, | |
#lastfmSaveDialog div { | |
display: block; | |
width: 100%; | |
} | |
#lastfmSaveDialog h4 { | |
font-size: 1.75em; | |
margin: 0 0 25px; | |
} | |
#lastfmSaveDialog label { | |
font-size: 1.25em; | |
margin: 15px 0 5px; | |
} | |
#lastfmSaveDialog input { | |
box-sizing: border-box; | |
padding: 5px; | |
} | |
#lastfmSaveDialog p { | |
text-align: right; | |
margin: 0.1ex; | |
font-size: 0.8em; | |
} | |
#lastfmSaveDialog #lastfmSave { | |
margin-left: auto; | |
margin-right: 0; | |
margin-top: 15px; | |
display: block; | |
} | |
.dark #lastfmSaveDialog { | |
background-color: #2F3136; | |
border-color: #202225; | |
color: #DCDDDE; | |
} | |
.mobileLastfm { | |
display: none; | |
} | |
@media screen and (min-width: 0) and (max-width: 480px) { | |
.mobileLastfm { | |
height: 40px; | |
width: 40px; | |
display: inline-block; | |
right: 140px; | |
top: 10px; | |
position: absolute; | |
font-size: 4ex; | |
} | |
} | |
`; | |
document.head.appendChild(style); | |
const navBar = document.querySelector('.nav #content'); | |
const lastFmPrefsNavBar = document.createElement('div'); | |
lastFmPrefsNavBar.className = 'navBlock lastfm'; | |
lastFmPrefsNavBar.innerHTML = '<a href="javascript:;">Last.fm Prefs</a>'; | |
navBar.insertBefore(lastFmPrefsNavBar, navBar.querySelector('.navBlock.signIn')); | |
const header = document.querySelector('.header #content'); | |
const lastFmPrefsHeader = document.createElement('div'); | |
lastFmPrefsHeader.className = 'mobileLastfm'; | |
lastFmPrefsHeader.innerHTML = '<a href="javascript:;"><i class="fab fa-lastfm"></i></a>'; | |
header.insertBefore(lastFmPrefsHeader, header.querySelector('.mobileProfile')); | |
const dialogBox = document.createElement('dialog'); | |
dialogBox.id = dialogElementId; | |
dialogBox.innerHTML = ` | |
<button type="button" id="lastfmClose"><i class="fa fa-xmark"></i></button> | |
<h4>Last.fm Preferences</h4> | |
<div> | |
<label for="lastfmUsername">Username</label> | |
<input type="text" id="lastfmUsername" placeholder="Last.fm Username" value="${lastFmConfig.username}"/> | |
<p>Make Last.fm links point to your library, rather than the generic pages</p> | |
</div> | |
<div> | |
<label for="lastfmApiKey">API Key</label> | |
<input type="text" id="lastfmApiKey" placeholder="Last.fm API Key" value="${lastFmConfig.apiKey}"/> | |
<p>Required to show your scrobble counts. Register for your own <a target="_blank" href="https://www.last.fm/api/account/create">here</a></p> | |
</div> | |
<button type="button" id="lastfmSave">Save</button> | |
`; | |
document.body.appendChild(dialogBox); | |
const showLastfmPrefs = () => { | |
document.getElementById('lastfmUsername').value = lastFmConfig.username; | |
document.getElementById('lastfmApiKey').value = lastFmConfig.apiKey; | |
dialogBox.show(); | |
}; | |
lastFmPrefsNavBar.addEventListener('click', showLastfmPrefs); | |
lastFmPrefsHeader.addEventListener('click', showLastfmPrefs); | |
document.getElementById('lastfmClose').addEventListener('click', () => { dialogBox.close(); }); | |
document.getElementById('lastfmSave').addEventListener('click', () => { | |
lastFmConfig.username = document.getElementById('lastfmUsername').value.trim(); | |
lastFmConfig.apiKey = document.getElementById('lastfmApiKey').value.trim(); | |
dialogBox.close(); | |
refreshPageLinks(); | |
}); | |
} | |
} | |
function addPagesStyle() { | |
const pagesStyleId = 'lastFmLinkPageStyle'; | |
if (!document.getElementById(pagesStyleId)) { | |
const style = document.createElement('style'); | |
style.id = pagesStyleId; | |
style.textContent = ` | |
/* artist and album pages */ | |
.albumButton.lastfm:hover { | |
background-color: var(--color-last-fm-scarlet); | |
color: white; | |
} | |
.dark .albumButton.lastfm:hover { | |
color: #DCDDDE; | |
} | |
/* genre / ratings pages */ | |
.albumListLinks .lastfm:hover { | |
border-color: var(--color-last-fm-scarlet); | |
color: var(--color-last-fm-scarlet); | |
} | |
.dark .albumListLinks .lastfm:hover { | |
border-color: var(--color-last-fm-habanero); | |
color: var(--color-last-fm-habanero); | |
} | |
/* artist pages */ | |
.artistTopBox .socialRow .albumButton.lastfm { | |
padding: 0 10px; | |
} | |
/* Thinner displays */ | |
@media screen and (min-width: 0) and (max-width: 1023px) { | |
/* artist and album pages */ | |
.albumButton.lastfm .count { | |
display: inline; | |
line-height: 32px; | |
font-size: 12px; | |
} | |
/* artist pages */ | |
.artistTopBox .socialRow .albumButton.lastfm { | |
display: inline-block; | |
min-width: 100px; | |
margin: 0 1% 15px 0; | |
} | |
/* album pages */ | |
.albumLinksFlex a:has(.albumButton.lastfm):hover, | |
.albumLinksFlex .albumButton.lastfm:hover { | |
text-decoration: none; | |
} | |
.albumLinksFlex .albumButton.lastfm { | |
margin: 10px 0 0; | |
padding: 0; | |
display: block; | |
width: auto; | |
line-height: 32px; | |
height: 34px; | |
font-size: 12px; | |
} | |
/* genre / ratings pages */ | |
.albumListCover { | |
margin: 0 20px 15px 0; | |
} | |
.albumListLinks div { | |
margin-top: 5px; | |
} | |
/* resets touch scroll area on album list links | |
so we don't have to scroll to see last fm stats / links */ | |
.albumListLinks { | |
white-space: normal; | |
width: auto; | |
overflow-x: visible; | |
overflow-y: visible; | |
-webkit-overflow-scrolling: auto; | |
-ms-overflow-style: auto; | |
} | |
} | |
/* end of year lists pages */ | |
@media screen and (min-width: 0) and (max-width: 480px) { | |
.pointsTable { | |
margin: 10px 0 15px; | |
} | |
} | |
@media screen and (min-width: 481px) { | |
.albumListLinks.listSummary { | |
margin-top: 5px; | |
} | |
} | |
`; | |
document.head.appendChild(style); | |
} | |
} | |
function addAlbumPageLinks() { | |
const buyButtons = document.querySelector('.thirdPartyLinks > .buyButtons'); | |
if (buyButtons) { | |
// Deliberately don't go for the anchor tag, as there can be multiple when two artists have colaborated | |
const artistEl = document.querySelector('.artist span[itemprop="name"]'); | |
const albumLinks = document.createElement('div'); | |
albumLinks.dataset.lastFm = 'links'; | |
albumLinks.className = 'albumLinks'; | |
buyButtons.appendChild(albumLinks); | |
if (artistEl) { | |
const artistName = artistEl.textContent.trim(); | |
const artistLink = addItemPageLink(albumLinks, linkTypeArtist, artistName); | |
if (lastFmConfig.showPlayCounts) { | |
(async function() { | |
addPlayCountToItemPageLink(artistLink, await getArtistPlayCount(artistName)); | |
})(); | |
} | |
const albumEl = document.querySelector('.albumTitle > span[itemprop="name"]'); | |
if (albumEl) { | |
const albumName = albumEl.textContent.trim(); | |
const albumLink = addItemPageLink(albumLinks, linkTypeAlbum, artistName, albumName); | |
if (lastFmConfig.showPlayCounts) { | |
(async function() { | |
addPlayCountToItemPageLink( | |
albumLink, | |
await getAlbumPlayCount(artistName, albumName), | |
true | |
); | |
})(); | |
} | |
} | |
} | |
} | |
} | |
function addArtistPageLink() { | |
const artistHeadlineDiv = document.querySelector('.artistHeadline'); | |
const artistTopBoxDiv = document.querySelector('.artistTopBox'); | |
if (artistHeadlineDiv && artistTopBoxDiv) { | |
const socialRow = document.createElement('div'); | |
socialRow.dataset.lastFm = 'social'; | |
socialRow.className = 'socialRow'; | |
artistTopBoxDiv.appendChild(socialRow); | |
const artistName = artistHeadlineDiv.textContent.trim(); | |
const artistLink = addItemPageLink(socialRow, linkTypeArtist, artistName); | |
if (lastFmConfig.showPlayCounts) { | |
(async function() { | |
addPlayCountToItemPageLink(artistLink, await getArtistPlayCount(artistName)); | |
})(); | |
} | |
} | |
} | |
function addListPageLinks() { | |
// [id^="rank-"] doesn't work for selector on list pages that have no rank | |
const albumRows = document.querySelectorAll('.albumListRow'); | |
if (albumRows) { | |
for (let i = 0; i < albumRows.length; i++) { | |
const albumRow = albumRows[i]; | |
const albumDetails = albumRow.querySelector('.albumListTitle meta[itemprop="name"]').content; | |
const albumLinkCont = albumRow.querySelector('.albumListLinks'); | |
if (albumDetails && albumLinkCont) { | |
const albumDetailParts = albumDetails.match(/^(.+?) - (.+?)$/); | |
if (3 === albumDetailParts.length) { | |
const artistName = albumDetailParts[1]; | |
const albumName = albumDetailParts[2]; | |
function createAnchorLink(href, title, type) { | |
const iconSuffix = type === linkTypeAlbum ? type : iconSuffixArtist; | |
const lastFmLink = document.createElement('a'); | |
lastFmLink.dataset.lastFm = type; | |
lastFmLink.href = href; | |
lastFmLink.rel = 'nofollow'; | |
lastFmLink.target = '_blank'; | |
lastFmLink.innerHTML = | |
`<div class="lastfm"><i class="fab fa-lastfm"></i><i class="fa-regular fa-${iconSuffix}"></i>${title}</div>`; | |
return lastFmLink; | |
} | |
const titlePrefix = 'Last.fm'; | |
const lastFmArtistLink = createAnchorLink( | |
lastFmConfig.getWebUrl(artistName), | |
`${titlePrefix} Artist`, | |
linkTypeArtist | |
); | |
albumLinkCont.appendChild(lastFmArtistLink); | |
const lastFmAlbumLink = createAnchorLink( | |
lastFmConfig.getWebUrl(artistName, albumName), | |
`${titlePrefix} Album`, | |
linkTypeAlbum | |
); | |
albumLinkCont.appendChild(lastFmAlbumLink); | |
if (lastFmConfig.showPlayCounts) { | |
(async function () { | |
lastFmArtistLink.querySelector('.lastfm').appendChild( | |
document.createTextNode(`: ${await getArtistPlayCount(artistName)}`) | |
); | |
})(); | |
(async function () { | |
lastFmAlbumLink.querySelector('.lastfm').appendChild( | |
document.createTextNode(`: ${await getAlbumPlayCount(artistName, albumName)}`) | |
); | |
})(); | |
} | |
} | |
} | |
} | |
} | |
} | |
function addSummaryPageLinks() { | |
const albumRows = document.querySelectorAll('.listSummaryRow'); | |
if (albumRows) { | |
for (let i = 0; i < albumRows.length; i++) { | |
const albumRow = albumRows[i]; | |
const artistCont = albumRow.querySelector('.artistTitle'); | |
const albumCont = albumRow.querySelector('.albumTitle'); | |
const albumLinkCont = albumRow.querySelector('.albumListLinks'); | |
if (artistCont && albumCont && albumLinkCont) { | |
const artistName = artistCont.textContent.trim(); | |
const albumName = albumCont.textContent.trim(); | |
function createAnchorLink(href, title, type) { | |
const lastFmLink = document.createElement('a'); | |
lastFmLink.dataset.lastFm = type; | |
lastFmLink.href = href; | |
lastFmLink.rel = 'nofollow'; | |
lastFmLink.target = '_blank'; | |
lastFmLink.innerHTML = `<div>${title}</div>`; | |
return lastFmLink; | |
} | |
const titlePrefix = 'Last.fm'; | |
const lastFmArtistLink = createAnchorLink( | |
lastFmConfig.getWebUrl(artistName), | |
`${titlePrefix} Artist`, | |
linkTypeArtist | |
); | |
albumLinkCont.appendChild(lastFmArtistLink); | |
const lastFmAlbumLink = createAnchorLink( | |
lastFmConfig.getWebUrl(artistName, albumName), | |
`${titlePrefix} Album`, | |
linkTypeAlbum | |
); | |
albumLinkCont.appendChild(lastFmAlbumLink); | |
if (lastFmConfig.showPlayCounts) { | |
(async function () { | |
lastFmArtistLink.querySelector('div').appendChild( | |
document.createTextNode(`: ${await getArtistPlayCount(artistName)}`) | |
); | |
})(); | |
(async function () { | |
lastFmAlbumLink.querySelector('div').appendChild( | |
document.createTextNode(`: ${await getAlbumPlayCount(artistName, albumName)}`) | |
); | |
})(); | |
} | |
} | |
} | |
} | |
} | |
function addPageLinks() { | |
let addLinksFunction; | |
if (/\/album\//.test(document.location)) { | |
// Album page | |
addLinksFunction = addAlbumPageLinks; | |
} else if (/\/artist\//.test(document.location)) { | |
// Artist Page | |
addLinksFunction = addArtistPageLink; | |
} else if (/\/(genre|list|ratings)\/[0-9]/.test(document.location)) { | |
// Ratings pages | |
addLinksFunction = addListPageLinks; | |
} else if (/\/list\/summary\//.test(document.location)) { | |
addLinksFunction = addSummaryPageLinks; | |
} | |
if (addLinksFunction) { | |
addPagesStyle(); | |
addLinksFunction(); | |
} | |
} | |
function refreshPageLinks() { | |
const existingLastFmElements = document.querySelectorAll('*[data-last-fm]'); | |
existingLastFmElements.forEach((lastFmEl) => { lastFmEl.remove(); }); | |
addPageLinks(); | |
} | |
// iOS Safari caches pages after these have been applied sometimes, | |
// so check they don't already exist before starting our changes | |
if (!document.querySelector('.lastfm')) { | |
addCommonStyle(); | |
addPrefsDialogBox(); | |
addPageLinks(); | |
} | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment