您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Display percentage of plays and statistics on user profile
// ==UserScript== // @name Last.fm - Polish the profile // @namespace http://no.name.space/ // @description Display percentage of plays and statistics on user profile // @include http://www.last.fm/user/* // @include http://www.lastfm.fr/user/* // @include http://www.lastfm.de/user/* // @include http://www.lastfm.it/user/* // @include http://www.lastfm.se/user/* // @include http://www.lastfm.es/user/* // @include http://www.lastfm.com.br/user/* // @exclude http://www.last.fm/user/*/group* // @version 0.0.1.20140511024802 // ==/UserScript== //Changelog: //2005-08-14 [email protected] 1.0 - Initial version of percentage script //2005-12-16 [email protected] - modified version to display more detail and lower threshold //2006-12-29 [email protected] - Modified to work with the latest last.fm changes // 2007-03-27 snyde1 - fix for Opera // 2007-04-28 snyde1 - merge stats and text colour fix, optimise the math // 2007-04-04 snyde1 - set up comma separation for numbers > 1000 // 2007-08-08 snyde1 - add "landmark" track plays and then album stats and position limits // 2007-08-11 snyde1 - add album section and limits, reorganise // 2007-08-12 snyde1 - add internationalisation (FR, DE, SE, ES, PT, IT) // 2008-01-09 snyde1 - add support for time period used on profile // 2008-09-17 snyde1 - fix for recent format change // 2008-09-20 - remove landmarks, add tracker link, move tracks played around // 2008-09-25 - fix non-English sites // 2009-03-25 - fix header for top tracks // Initiation values // Set the following to zero (0) to disable var noFlip = 1; // Get rid of background images var darkText = 1; // Make text over bar the colour set below (darkTextClr) var doPCTage = 1; // Include percentage of plays for the bars var doStats = 1; // Include monthly/weekly/etc. breakdown of plays var limitCount = 25; // limit line count in artist/track charts ... set to 0 (or over 50) to ignore var squishRecent = 0; // merge lines in recent tracks var squishLibrary = 1; // collapse pictures in Library var addAlbum = 0; // add block for album stats - can be time consuming var useBasis = 0; // Add notation when using weekly stats rather than overall // Colour for dark text var darkTextClr = "#338"; // Change this to the number of decimal places you wish displayed var num_dec = 1; /* BEGIN LICENSE BLOCK Copyright (C) 2005 Arvid Jakobsson This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You can download a copy of the GNU General Public License at http://www.gnu.org/licenses/gpl.html or get a free printed copy by writing to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. END LICENSE BLOCK */ var monthStr = new Array(); monthStr[0] = "Jan"; monthStr[1] = "Feb"; monthStr[2] = "Mar"; monthStr[3] = "Apr"; monthStr[4] = "May"; monthStr[5] = "Jun"; monthStr[6] = "Jul"; monthStr[7] = "Aug"; monthStr[8] = "Sep"; monthStr[9] = "Oct"; monthStr[10] = "Nov"; monthStr[11] = "Dec"; // Regexps for languages // English (default) var regDateRE = /<small>since ([^<]*)</i; var rstDateRE = /\(reset on ([^<]*)\)/; var rstDataRE = /\(reset on /; var trkRE = /Tracks/; var albST = "Albums"; var traxPlydRE = /Tracks played:/; var prefA = "... per "; var prefB = new Array; prefB[0] = "hour"; prefB[1] = "day"; prefB[2] = "week"; prefB[3] = "month"; prefB[4] = "year"; var monthN = new Object; var comma = ","; // number separator var decimal = "."; var albumHDRa = "<H2 Class='heading'><SPAN class='h2Wrapper'><A HREF='"; var albumHDRb = "'>Top Albums Overall</a></span></h2>"; var RTtext = "Reply Tracker"; // Français if (location.href.match(/lastfm\.fr\//)) { regDateRE = /<small>depuis le ([^<]*)</i; rstDataRE = /\(r.initialisation le /; rstDateRE = /\(r.initialisation le ([^<]*)\)/; traxPlydRE = /Titres jou.s :/; trkRE = /titres/; albST = "albums"; prefA = " ... par "; prefB = new Array; prefB[0] = "heur"; prefB[1] = "jour"; prefB[2] = "semaine"; prefB[3] = "mois"; prefB[4] = "an"; albumHDR = 'Top des albums global <span>(voir plus)</span>'; comma = " "; decimal = ","; monthN["jan."] = "Jan"; monthN["fév."] = "Feb"; monthN["mars"] = "Mar"; monthN["avr."] = "Apr"; monthN["mai"] = "May"; monthN["juin"] = "Jun"; monthN["jui."] = "Jul"; monthN["août"] = "Aug"; monthN["sept"] = "Sep"; monthN["oct."] = "Oct"; monthN["nov."] = "Nov"; monthN["déc."] = "Dec"; monthStr[0] = "jan."; monthStr[1] = "f&eactue;v"; monthStr[2] = "mars"; monthStr[3] = "avr."; monthStr[4] = "mai"; monthStr[5] = "juin"; monthStr[6] = "jui."; monthStr[7] = "août"; monthStr[8] = "sept"; monthStr[9] = "oct."; monthStr[10] = "nov."; monthStr[11] = "déc."; RTtext = "Suivi des réponses"; } // Deutsch if (location.href.match(/lastfm\.de\//)) { regDateRE = /<small>seit ([^<]*)</i; rstDataRE = /\(zur.ckgesetzt am /; rstDateRE = /\(zur.ckgesetzt am ([^<]*)\)/; traxPlydRE = /Geh.rte Titel:/; trkRE = /Titel/; albST = "Alben"; prefA = "Titel pro "; prefB = new Array; prefB[0] = "Stunde"; prefB[1] = "Tag"; prefB[2] = "Woche"; prefB[3] = "Monat"; prefB[4] = "Jahr"; albumHDR = 'Allgemeine Top-Alben <span>(weitere anzeigen)</span>'; comma = "."; decimal = ","; monthN["Jan."] = "Jan"; monthN["Feb."] = "Feb"; monthN["Mär."] = "Mar"; monthN["Apr."] = "Apr"; monthN["Mai."] = "May"; monthN["Jun."] = "Jun"; monthN["Jul."] = "Jul"; monthN["Aug."] = "Aug"; monthN["Sep."] = "Sep"; monthN["Okt."] = "Oct"; monthN["Nov."] = "Nov"; monthN["Dez."] = "Dec"; monthStr[0] = "Jan."; monthStr[1] = "Feb."; monthStr[2] = "Mär."; monthStr[3] = "Apr."; monthStr[4] = "Mai."; monthStr[5] = "Jun."; monthStr[6] = "Jul."; monthStr[7] = "Aug."; monthStr[8] = "Sep."; monthStr[9] = "Okt."; monthStr[10] = "Nov."; monthStr[11] = "Dez."; RTtext = "Antworten verfolgen"; } // Svenska if (location.href.match(/lastfm\.se\//)) { regDateRE = /<small>sedan ([^<]*)</i; rstDataRE = /\(.terst.llt den /; rstDateRE = /\(.terst.llt den ([^<]*)\)/; traxPlydRE = /L.tar spelade:/; trkRE = /Toppl.tar/; albST = "Toppalbum"; prefA = "LÅtar per "; prefB = new Array; prefB[0] = "timme"; prefB[1] = "dag"; prefB[2] = "vecka"; prefB[3] = "månad"; prefB[4] = "år"; albumHDR = 'Toppartister totalt <span>(se fler)</span>'; comma = ","; monthN["jan"] = "Jan"; monthN["feb"] = "Feb"; monthN["mar"] = "Mar"; monthN["apr"] = "Apr"; monthN["maj"] = "May"; monthN["jun"] = "Jun"; monthN["jul"] = "Jul"; monthN["aug"] = "Aug"; monthN["sep"] = "Sep"; monthN["okt"] = "Oct"; monthN["nov"] = "Nov"; monthN["dec"] = "Dec"; monthStr[0] = "jan"; monthStr[1] = "feb"; monthStr[2] = "mar"; monthStr[3] = "apr"; monthStr[4] = "maj"; monthStr[5] = "jun"; monthStr[6] = "jul"; monthStr[7] = "aug"; monthStr[8] = "sep"; monthStr[9] = "okt"; monthStr[10] = "nov"; monthStr[11] = "dec"; RTtext = "Svarshistorik"; } // Español if (location.href.match(/lastfm\.es\//)) { regDateRE = /<small>desde ([^<]*)</i; rstDataRE = /\(reiniciar /; rstDateRE = /\(reiniciar ([^<]*)\)/; traxPlydRE = /Temas escuchados:/; trkRE = /Temas/; albST = "Álbumes"; prefA = "Temas por "; prefB = new Array; prefB[0] = "hora"; prefB[1] = "dia"; prefB[2] = "semana"; prefB[3] = "mes"; prefB[4] = "año"; albumHDR = 'Álbumes más escuchados <span>(ver más)</span>'; comma = ","; monthN["Ene"] = "Jan"; monthN["Feb"] = "Feb"; monthN["Mar"] = "Mar"; monthN["Abr"] = "Apr"; monthN["May"] = "May"; monthN["Jun"] = "Jun"; monthN["Jul"] = "Jul"; monthN["Ago"] = "Aug"; monthN["Sep"] = "Sep"; monthN["Oct"] = "Oct"; monthN["Nov"] = "Nov"; monthN["Dic"] = "Dec"; monthStr[0] = "Ene"; monthStr[1] = "Feb"; monthStr[2] = "Mar"; monthStr[3] = "Abr"; monthStr[4] = "May"; monthStr[5] = "Jun"; monthStr[6] = "Jul"; monthStr[7] = "Ago"; monthStr[8] = "Sep"; monthStr[9] = "Oct"; monthStr[10] = "Nov"; monthStr[11] = "Dic"; RTtext = "Mis respuestas"; } // Português if (location.href.match(/lastfm\.com\.br\//)) { regDateRE = /<small>desde ([^<]*)</i; rstDataRE = /\(Reiniciar em /; rstDateRE = /\(Reiniciar em ([^<]*)\)/; traxPlydRE = /Faixas executadas:/; trkRE = /Faixas/; albST = "Álbuns"; prefA = "Faixas por "; prefB = new Array; prefB[0] = "hora"; prefB[1] = "dia"; prefB[2] = "semana"; prefB[3] = "mês"; prefB[4] = "ano"; albumHDR = 'Álbuns mais tocadas em geral <span>(ver mais)</span>'; comma = "."; decimal = ","; monthN["Jan"] = "Jan"; monthN["Fev"] = "Feb"; monthN["Mar"] = "Mar"; monthN["Abr"] = "Apr"; monthN["Mai"] = "May"; monthN["Jun"] = "Jun"; monthN["Jul"] = "Jul"; monthN["Ago"] = "Aug"; monthN["Set"] = "Sep"; monthN["Out"] = "Oct"; monthN["Nov"] = "Nov"; monthN["Dez"] = "Dec"; monthStr[0] = "Jan"; monthStr[1] = "Fev"; monthStr[2] = "Mar"; monthStr[3] = "Abr"; monthStr[4] = "Mai"; monthStr[5] = "Jun"; monthStr[6] = "Jul"; monthStr[7] = "Ago"; monthStr[8] = "Sep"; monthStr[9] = "Out"; monthStr[10] = "Nov"; monthStr[11] = "Dez"; RTtext = "Suas respostas"; } // Italiano if (location.href.match(/lastfm\.it\//)) { regDateRE = /<small>dal ([^<]*)</i; rstDataRE = /\(reimpostato il /; rstDateRE = /\(reimpostato il ([^<]*)\)/; traxPlydRE = /Brani ascoltati:/; trkRE = /Brani/; albST = "Album"; prefA = "brani "; prefB = new Array; prefB[0] = "all'ora"; prefB[1] = "al giorno"; prefB[2] = "alla settimana"; prefB[3] = "al mese"; prefB[4] = "all'anno"; albumHDR = 'Album più ascoltati <span>(visualizza tutti)</span>'; comma = ","; monthN["Gen"] = "Jan"; monthN["Feb"] = "Feb"; monthN["Mar"] = "Mar"; monthN["Apr"] = "Apr"; monthN["Mag"] = "May"; monthN["Giu"] = "Jun"; monthN["Lug"] = "Jul"; monthN["Ago"] = "Aug"; monthN["Set"] = "Sep"; monthN["Ott"] = "Oct"; monthN["Nov"] = "Nov"; monthN["Dic"] = "Dec"; monthStr[0] = "Gen"; monthStr[1] = "Feb"; monthStr[2] = "Mar"; monthStr[3] = "Apr"; monthStr[4] = "Mag"; monthStr[5] = "Giu"; monthStr[6] = "Lug"; monthStr[7] = "Ago"; monthStr[8] = "Set"; monthStr[9] = "Ott"; monthStr[10] = "Nov"; monthStr[11] = "Dic"; RTtext = "Tracker delle risposte"; } function xpath(query, context) { if (!context) { context = document; } return document.evaluate(query, context, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null); } (function () { var tenpow = Math.pow(10, num_dec); var teninv = 1.0/tenpow; if (! location.href.match(/last[^\/]*\/user\/([^\/]*)$/)) {return;} var username = location.href.match(/last[^\/]*\/user\/([^\/]*)$/)[1]; var userData = xpath("//DIV[@Class='userData']"); if (userData.snapshotLength <= 0) { return; } var panel = userData.snapshotItem(0); var panelPart = xpath("//DIV[@Class='userData']/SPAN[@Class='userPlays']/Strong/SPAN[@Class='count']"); var tracksplayed = 0; var panelText = ""; if (panelPart.snapshotLength > 0) { panelText = panelPart.snapshotItem(0).innerHTML; tracksplayed = panelText.replace(/<span class="flip">/ig,""); tracksplayed = tracksplayed.replace(/<.span>/ig,""); if (noFlip == 1) { panelPart.snapshotItem(0).innerHTML = tracksplayed; } tracksplayed = tracksplayed.replace(/[^0-9]/g,""); } else { var panel = document.getElementById("hcard-"+username); panelText = panel.innerHTML+""; panelText = panelText.match(/<span title="[^\"]*">(.*)<\/span>/i)[1]; var tracksplayed = panelText.match(/([^ ]*) [^0-9]/i)[1]+""; tracksplayed = tracksplayed.replace(/[^0-9]/g,''); } if (!tracksplayed){ return; } var reg_date = panel.innerHTML.match(regDateRE)[1]; if (!reg_date) { return; } if (panel.innerHTML.match(rstDataRE)) { var up_Date = panel.innerHTML.match(rstDateRE)[1]; if (up_Date) { reg_date = up_Date; } } // Language specific date if (! location.href.match(/www\.last\.fm\//)){ reg_date = reg_date.replace(/^ */,""); var fr_date = new Array; fr_date = reg_date.split(/ /); reg_date = fr_date[0]+" "+monthN[fr_date[1]]+" "+fr_date[2]; reg_date = reg_date.replace(/\./g,""); // Just for German } var reg_date_ms = Date.parse(reg_date); var now = new Date(); var now_ms = Date.parse(now); var diff = Math.round((now_ms - reg_date_ms)/1000); // Add tracker link var userText = userData.snapshotItem(0).innerHTML+""; if (userText.match(/\/grapevine[^<]*<\/a>/i)) { var repTrackBack = userText.match(/grapevine[^<]*<.a>/i); repTrackBack += " | <a href=\"/user/"+username+"/replytracker\">"+RTtext+"</a> "; userData.snapshotItem(0).innerHTML = userText.replace(/grapevine[^<]*<\/a>/i,repTrackBack); } // Side panel stuff if ( (doStats != 0) ) { var tps = tracksplayed / diff; // Tracks per second var tph = tps * 3600; var newtph = commatize(tph.toFixed(num_dec),comma,decimal); var tpd = tps * 86400; var newtpd = commatize(tpd.toFixed(num_dec),comma,decimal); var tpw = tps * 604800; var newtpw = commatize(tpw.toFixed(num_dec),comma,decimal); var tpm = tps * 2628000; // Average month length, not 31 days var newtpm = commatize(tpm.toFixed(num_dec),comma,decimal); var tpy = tps * 31536000; commatize(tpy.toFixed(3),comma,decimal); var newtpy = commatize(tpy.toFixed(num_dec),comma,decimal); var paragraph = panel.parentNode; // xpath(".//DIV[@class='c']/P", panel); if (doStats != 0) { var trxText = document.createElement("span"); var parJour = "<table class=\"userData\"><tr><td>"+prefA+prefB[0]+"</td><td align=right>"+newtph+"</td></tr>"; parJour += "<tr><td>"+prefA+prefB[1]+"</td><td align=right>"+newtpd+"</td></tr>"; parJour += "<tr><td>"+prefA+prefB[2]+"</td><td align=right>"+newtpw+"</td></tr>"; parJour += "<tr><td>"+prefA+prefB[3]+"</td><td align=right>"+newtpm+"</td></tr>"; parJour += "<tr><td>"+prefA+prefB[4]+"</td><td align=right>"+newtpy+"</td></tr></table>"; trxText.innerHTML = parJour+"<br>"; panel.insertBefore(trxText, panel.lastChild.previousSibling); } } // Squish Recents if (squishRecent != 0) { var bars = xpath("//TABLE[@id='recentTracks']/TBODY/TR/TD[@class='subjectCell']"); for (var i=0; i<bars.snapshotLength; i++) { bars.snapshotItem(i).innerHTML = bars.snapshotItem(i).innerHTML.replace(/<br[^>]*>/i," – "); } var bars = xpath("//TABLE[@id='recentTracks']/TBODY/TR/TD[@class='subjectCell featured featuredTrack']"); for (var i=0; i<bars.snapshotLength; i++) { bars.snapshotItem(i).innerHTML = bars.snapshotItem(i).innerHTML.replace(/<br[^>]*>/i," – "); } bars = xpath("//TABLE[@id='recentTracks']/TBODY/TR"); for (var i=0; i<bars.snapshotLength; i++) { var tmpItem = bars.snapshotItem(i).firstChild; tmpItem.setAttribute("style","height: 18px;");// display:none;"); tmpItem.nextSibling.setAttribute("style","height: 18px;"); // display:none;"); tmpItem.parentNode.setAttribute("style","height: 18px;"); tmpItem.innerHTML = ""; } bars = xpath("//TABLE[@id='recentTracks']/TBODY/TR/TD[@class='featured featuredImage']"); for (var i=0; i<bars.snapshotLength; i++) { bars.snapshotItem(i).setAttribute("style","height: 18px;"); // display:none;"); } } // Zap Library pics if (squishLibrary != 0) { var libpics = xpath("//SPAN[@Class='pictureFrame']"); for (var i=0; i<libpics.snapshotLength; i++) { libpics.snapshotItem(i).setAttribute("style","display:none;"); libpics.snapshotItem(i).parentNode.parentNode.setAttribute("style","height: 40px; width: 155px;"); libpics.snapshotItem(i).parentNode.parentNode.parentNode.setAttribute("style","height: 120px;"); } var libpics = xpath("//A[@Class='playbutton']"); // var libpics = xpath("//SPAN[@Class='overlay']"); for (var i=0; i<libpics.snapshotLength; i++) { libpics.snapshotItem(i).setAttribute("style","display:none;"); } } // Album panel if ((addAlbum != 0) && (location.href.match(/\/user\/[^\/]*$/)) ) { var theURL = location.href+"/charts?rangetype=overall&subtype=albums"; var centerField = xpath("//DIV[@Class='module modulechartstracks']"); if (centerField.snapshotLength>0) { var newSection = document.createElement("div"); var xmlhttp=new XMLHttpRequest(); xmlhttp.open("GET", theURL, false); xmlhttp.send(null); var xmlText = xmlhttp.responseText; if (xmlText) { centerField.snapshotItem(0).parentNode.insertBefore(newSection,centerField.snapshotItem(0).nextSibling); xmlText = xmlText+""; var xmlTable = "<table"+xmlText.split(/<table/)[1]; xmlTable = xmlTable.split(/<\/table>/)[0]+"</table>"; if (xmlTable) { xmlTable = xmlTable.replace(/div style="width:20%;"/g,"div style='width:40%;'"); var addText = albumHDRa+theURL+albumHDRb; addText += '<div class="chartWithQuiltChart" id="MyTopAlbums">'+xmlTable+'</div></div>'; newSection.innerHTML = addText; } } if (limitCount == 0) {limitCount = 50; } } } // Loop for everything else if ( (doPCTage != 0) || (darkText != 0) || (limitCount != 0) ) { var basis = ""; if ( (doPCTage != 0) && (location.href.match(/charttype=weekly/)) ) { panel = document.getElementById("selectedWeekStats"); tracksplayed = panel.innerHTML.match(/<td>Total Plays:<\/td><td><strong>([0-9,]+)<\/strong><\/td>/i)[1].replace(/,/, ""); if (useBasis != 0) { basis = " wkly"; } } var bars = xpath("//TD[@class='chartbarCell']/DIV/SPAN"); var poses = xpath("//TD[@class='positionCell']"); var labelz = xpath("//TD[@class='subjectCell']/DIV"); var oldPos = 1000000; var posIndex = 0; for (var i = 0; i < bars.snapshotLength; i++) { var newCell = document.createElement("td"); newCell.setAttribute("Class","myPcnt"); newCell.innerHTML = " "; poses.snapshotItem(i).parentNode.insertBefore(newCell,poses.snapshotItem(i).parentNode.childNodes(poses.snapshotItem(i).parentNode.childNodes.length - 1)); var posCount = poses.snapshotItem(i).innerHTML.replace(/ */g,"")-0; if (posCount < oldPos) { posIndex = 0; } oldPos = posCount+0; posIndex++; if ((limitCount != 0) && (! location.href.match(/charts/)) && (posIndex > limitCount) ) { poses.snapshotItem(i).parentNode.setAttribute("style","display:none;"); } else { var bar = bars.snapshotItem(i); if (doPCTage != 0) { var played = bar.innerHTML; var playedInt = played.replace(/[, \.]/g, ""); var percentage = (playedInt / tracksplayed) * 100; if (percentage >= teninv) { newCell.innerHTML =commatize(percentage.toFixed(num_dec),comma,decimal) + "%" + basis; // labelz.snapshotItem(i).innerHTML += " - (" + commatize(percentage.toFixed(num_dec),comma,decimal) + "%" + basis + ")"; } } if (darkText != 0) { // bar.parentNode.parentNode.style.color = darkTextClr; bar.style.color = darkTextClr; } } } } })(); // // Insert "commas" to split number into blocks of 3 digits // function commatize(number,comma,deci) { number = number+""; // Make text if (!comma) { var comma = ","; } if (!deci) { var deci = "."; } var numNeg = 0; if (number.match(/^-/)) { numNeg = 1; number = number.replace(/^-/,""); } var numdp = number.split("."); // Not input decimal symbol - this is from the js stuff if (numdp.length == 2) { var decimal = numdp[1]; } var integer = numdp[0]; if (integer.length < 4) { if (numdp.length == 2) { number = integer + deci + decimal; } if (numNeg == 1) { number = "-" + number; } return(number); } var stubFrnt = integer.length % 3; if (stubFrnt == 0) {stubFrnt = 3;} var newnumber = integer.substr(0,stubFrnt); var oldPos = stubFrnt; while(oldPos < integer.length ) { newnumber = newnumber + comma + integer.substr(oldPos, 3); oldPos = oldPos + 3; } if (numdp.length == 2) { newnumber = newnumber + deci + decimal; } if (numNeg == 1) { newnumber = "-" + newnumber; } return(newnumber); } // line eater fodder