Greasy Fork is available in English.
Adding album links and headers to tracks on Last.Fm's recent plays listings
当前为
// ==UserScript==
// @name Stig's Last.fm Album Linkr
// @namespace dk.rockland.userscript.lastfm.linkr
// @description Adding album links and headers to tracks on Last.Fm's recent plays listings
// @version 2016.07.11.0
// @author Stig Nygaard, http://www.rockland.dk
// @homepageURL http://www.rockland.dk/userscript/lastfm/linkr/
// @supportURL http://www.rockland.dk/userscript/lastfm/linkr/
// @match *://*.last.fm/*
// @match *://*.lastfm.de/*
// @match *://*.lastfm.es/*
// @match *://*.lastfm.fr/*
// @match *://*.lastfm.it/*
// @match *://*.lastfm.ja/*
// @match *://*.lastfm.pl/*
// @match *://*.lastfm.pt/*
// @match *://*.lastfm.ru/*
// @match *://*.lastfm.sv/*
// @match *://*.lastfm.tr/*
// @match *://*.lastfm.zh/*
// @grant none
// @noframes
// ==/UserScript==
var linkr = linkr || {
// CHANGELOG - The most important updates/versions:
changelog: [
{version: '2016.07.08.1', description: 'Fine-tuning album-headers with light red background color and more...'},
{version: '2016.07.08.0', description: 'Don\'t put album-header at very top of Recent Tracks if the 1st track is scrobbling now.'},
{version: '2016.07.07.0', description: 'Album "headers" in play listings added.'},
{version: '2016.07.04.0', description: '1st release'}
],
INFO: true,
DEBUG: false,
observed: null,
linking_running: false,
log: function(s, info) {
if ((info && window.console) || (linkr.DEBUG && window.console)) {
window.console.log('*Linkr* '+s);
}
},
insertStyle: function() {
if (!document.getElementById('linkrStyle')) {
var style = document.createElement('style');
style.type = 'text/css';
style.id = 'linkrStyle';
style.innerHTML = 'tr.albumlink-row, tr.albumlink-row > td {background-color:#f1cccc !important; font-style:italic} tr.albumlink-row:hover, tr.albumlink-row:hover > td {background-color:#f9d4d4 !important;}';
document.getElementsByTagName('head')[0].appendChild(style);
linkr.log('linkrStyle has been ADDED');
} else {
linkr.log('linkrStyle was already present');
}
},
linking: function (mutations) {
if(linkr.linking_running) return;
linkr.linking_running = true;
function altvalue(elem) {
if (elem && elem.firstElementChild) {
if (elem.firstElementChild.classList.contains('albumlink-row')) {
return null;
} else if (elem.firstElementChild.firstElementChild && elem.firstElementChild.firstElementChild.firstElementChild && elem.firstElementChild.firstElementChild.firstElementChild.firstElementChild) {
return elem.firstElementChild.firstElementChild.firstElementChild.firstElementChild.alt;
}
}
return null;
}
linkr.log('Running linking()... ', linkr.INFO);
var l = document.querySelectorAll('table.chartlist tr div > img');
for (var i=0; i < l.length; i++) {
linkr.log('iteration '+ i + ' of ' + l.length);
if (l[i].alt && l[i].alt!='') {
l[i].title = l[i].alt;
var tr = parent = l[i].parentNode;
while (tr.tagName.toUpperCase()!=='TR') tr = tr.parentNode;
var a = tr.querySelector('span.chartlist-artists a');
if (a) {
linkr.log('Found img.alt='+l[i].alt);
var albumlink = a.href + '/' + encodeURIComponent(l[i].alt).replace(/%20/g,'+') + '/';
linkr.log('giving albumlink='+albumlink);
var link = document.createElement('a');
link.setAttribute('href', albumlink);
parent.replaceChild(link, l[i]);
link.appendChild(l[i]);
} else {
linkr.log('Artist link not found');
}
}
}
var tlists = document.querySelectorAll('section#recent-tracks-section table.chartlist tbody, section.tracklist-section tbody');
linkr.log('tlists.length='+tlists.length);
for (var j=0; j<tlists.length; j++) {
linkr.log('Loop with tlists['+j+'].');
if (tlists[j] && tlists[j].children && tlists[j].children.length > 2) {
linkr.log('tlists['+j+'] has ' + tlists[j].children.length + ' children');
var loopstart=1;
if (j===0 && tlists[j].children[0].classList.contains('now-scrobbling')) {
loopstart=2; // Don't put album-header at very top of Recent Tracks if the 1st row is a currently scrobbling track
}
for (i = loopstart; i < tlists[j].children.length; i++) {
linkr.log('for-loop. i=' + i);
if (i===1 || !tlists[j].children[i - 2].classList.contains('albumlink-row')) {
linkr.log('for-loop. i=' + i + ' og i-2 er IKKE allerede albumlink-row');
if ( altvalue(tlists[j].children[i])
&& altvalue(tlists[j].children[i - 1])
&& altvalue(tlists[j].children[i]) != ''
&& altvalue(tlists[j].children[i]) === altvalue(tlists[j].children[i - 1])
&& (i===1 || altvalue(tlists[j].children[i]) != altvalue(tlists[j].children[i - 2]))) {
linkr.log('for-loop. i=' + i + ' og vi har fundet en album-gruppes start', linkr.INFO);
var artistlink = tlists[j].children[i].querySelector('td.chartlist-name span.chartlist-artists > a');
var albumtitle = altvalue(tlists[j].children[i]);
var albumcover = tlists[j].children[i].querySelector('td.chartlist-play a > img');
if (albumcover) albumcover=albumcover.src;
if (artistlink) {
var artistname = artistlink.textContent;
artistlink = artistlink.href;
albumlink = artistlink + '/' + encodeURIComponent(altvalue(tlists[j].children[i])).replace(/%20/g,'+') + '/';
tr = document.createElement("tr");
tr.classList.add('albumlink-row','js-link-block','js-lazy-buylinks-focus-container');
tr.innerHTML = '<td class="chartlist-play"><div class="chartlist-play-image"><a href="'+albumlink+'"><img title="'+albumtitle+'" src="'+albumcover+'" class="cover-art"></a></div></td><td class="chartlist-loved"><a href="'+albumlink.replace(/\/user\/[^\/]+\/library\//,'/')+'"><img src="http://www.rockland.dk/img/album244c.png" class="cover-art" alt="album" /></a></td><td class="chartlist-name"><span class="chartlist-ellipsis-wrap"><span class="chartlist-artists"><a href="'+artistlink+'" title="'+artistname+'">'+artistname+'</a></span><span class="artist-name-spacer"> — </span><a href="'+albumlink+'" class="link-block-target" title="'+artistname+' — '+albumtitle+'">'+albumtitle+'</a></span></td><td class="chartlist-buylinks"><div class="lazy-buylinks"><button class="disclose-trigger lazy-buylinks-toggle" aria-expanded="false" data-lazy-buylink="" data-lazy-buylink-url="'+albumlink.replace(/\/user\/[^\/]+\/library\//,'/')+'/+partial/buylinks">Buy</button></div></td><td class="chartlist-timestamp"></td><td class="chartlist-delete"></td>';
linkr.log('Now trying to add tr...');
tlists[j].insertBefore(tr, tlists[j].children[i - 1]);
linkr.log('and should be added now!?');
i += 2; // or http://stackoverflow.com/questions/8766910/is-there-a-loop-start-over ?
}
}
}
}
} else {
linkr.log('but not enough children found...');
}
}
linkr.linking_running = false;
},
setupObserver: function () {
linkr.log('Running setupObserver()');
linkr.insertStyle();
linkr.observed = document.querySelector('table.chartlist > tbody');
if (!linkr.observed || !linkr.observed.classList) {
linkr.log('Object to observe NOT found - re-trying later...');
} else if (linkr.observed.classList.contains('hasObserver')) {
linkr.log('Everything is okay! - But checking again later...');
} else {
linkr.linking();
linkr.log('Now adding Observer and starting...', linkr.INFO);
var observer = new MutationObserver(linkr.linking);
var config = {attributes: false, childList: true, subtree: false, characterData: false};
observer.observe(linkr.observed, config);
linkr.observed.classList.add('hasObserver');
linkr.log('Observer added and running...');
}
},
init: function () {
linkr.log('Running init() on last.fm');
linkr.insertStyle();
linkr.linking();
setInterval(linkr.setupObserver,2000);
}
};
linkr.init();