// ==UserScript==
// @name Last.fm play statistics!
// @version 2.2.3
// @namespace http://code.google.com/p/lastfm-gm-scripts/
// @description Displays a statistic after the number of played tracks on Last.fm.
// @identifier http://lastfm-gm-scripts.googlecode.com/svn/trunk/lastfmplaystatistics.user.js
// @require http://alan71.free.fr/lastfm/settings.js
// @include http://www.last.fm/settings*
// @include http://www.last.fm/user/*
// @include http://beta.last.fm/user/*
// @include http://last.fm/user/*
// @exclude http://*last.fm/user/*/*
// ==/UserScript==
/*
Changelog:
[Alan71]
2008-09-28 2.2.3
Bug fix: didn't work with reset profile date
[Alan71]
2008-09-26 2.2.2
Works with latest changes in user profiles' code
[Alan71]
2008-07-23 2.2.1
Figures alignment
New conf item: changing precision
[Alan71]
2008-07-21 2.1.1
Grammatical issue
[Alan71]
2008-07-21 2.1
CSS
"On reset" option
Known issue: does not work with i18n-ed last.fm
[Alan71]
2008-07-21 2.0
Support for the new version of last.fm
Rewritten from scratch
Option to use the reset date not implemented
[M Lenzen - LucidCognition]
2007-07-08 1.3.2
Added Include for non-English domains
Added option to use reset date
2007-03-31 1.3.1
Use built in toFixed function
2007-03-29 1.3.0
Added automatic updates
2006-12-30 1.2f
* Changed to correctly parse tracks played on profiles that are reset.
2006-12-29 1.2f
* Updated parsing of tracksplayed to work with the latest last.fm update.
[Dennis Burke - theboinkbaron]
2006-09-23
* Changes to work with last.fm's new css layout
* I rewrote some of the functions to be more accurate. It used to calculate everything by multiplying each
successive statistic by the factor difference between them. It now calculates the difference in time and
multiplies out to give the correct stats. Call me crazy but this works better. Oh, and I also added an
average per year.
[Stephen Paulger]
2005-12-01 1.2e
* Rewrite due to HTML change, also I made the registration date match() less specific to allow the script to work
on pages of users who are subscribers, staff, moderators etc.
[David]
2005-09-28 1.2d
* I fixed the script to work with last.fm again. arvid seems unavailable available.
[arvid]
2005-08-26 1.2
* Due to a change in the HTML of last.fm which milk pointed out (thanks!), the script stopped working. Changed it to work again.
2005-08-17 1.1
* Some code clean up, removed unnecessary GM_logs etc
* Changed the code in accordance to milks suggestions (http://www.userscripts.org/people/327). Thanks for the suggestions!
The script works better now when you've got more than zero posts in the forum.
2005-08-14 1.0
* Initial version
*/
/*
BEGIN LICENSE BLOCK
Copyright (C) 2005 Arvid Jakobsson arvid.jakobsson@gmail.com
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 divList = document.getElementsByTagName("div");
var divHCard = null;
var child = null;
for(var i = 0; i < divList.length; i++) {
child = divList[i];
// luling @ last.fm crew :
//
//
// Old selector:
// if(child.getAttribute("id") != null && child.getAttribute("id").match(/hcard/)) {
if(child.getAttribute("id") != null && child.getAttribute("id") == "userBadge") {
divHCard = child;
break;
}
}
if(divHCard != null) {
var dataElement = null;
divList = divHCard.getElementsByTagName("span");
for(var i = 0; i < divList.length; i++) {
child = divList[i];
if(child.getAttribute("class") == "userPlays") {
dataElement = child;
break;
}
}
if(dataElement != null) {
var dateString = dataElement.innerHTML.match(/([0-9]+ [a-z]+ [0-9]+)[ ]?[(]?.*[)]?$/i)[1];
if(GM_getValue("use_reset_date", true) == true && dataElement.innerHTML.match(/\(reset on /)) {
dateString = dataElement.innerHTML.match(/([0-9]+ [a-z]+ [0-9]+)[)].*$/i)[1];
}
var tracksPlayedString = "";
child = dataElement.getElementsByTagName("span")[0].firstChild;
while(child != null) {
if(child.nodeName.toLowerCase() == "span") {
tracksPlayedString = tracksPlayedString + "" + child.innerHTML;
}
child = child.nextSibling;
}
// Old regexp: dataElement.innerHTML.match(/([0-9,]+)/)[1];
var date = Date.parse(dateString);
var tracksPlayed = tracksPlayedString.replace(/,/, "");
var diff = Math.round(new Date() - date) /1000;
var hours = diff / (60*60);
var days = diff / (60*60*24);
var weeks = diff / (60*60*24*7);
var months = diff / (60*60*24*31);
var years = diff / (60*60*24*365);
var precision = GM_getValue("precision", 2);
var div = document.createElement("div");
div.setAttribute("style", "float: right; color: #666666; font-size: 11px;");
div.innerHTML =
'
Stats:' +
'
' +
'Tracks per hour: | ' + (tracksPlayed / hours).toFixed(precision) + ' |
' +
'Tracks per day: | ' + (tracksPlayed / days).toFixed(precision) + ' |
' +
'Tracks per week: | ' + (tracksPlayed / weeks).toFixed(precision) + ' |
' +
'Tracks per month: | ' + (tracksPlayed / months).toFixed(precision) + ' |
' +
'Tracks per year: | ' + (tracksPlayed / years).toFixed(precision) + ' |
' +
'
';
divHCard.parentNode.insertBefore(div, divHCard.parentNode.firstChild);
}
}
// =========== Configuration ==================
function buildEntryInSettings() {
var settingsZone = getSettingsZone();
if(settingsZone == null) return;
var title = document.createElement("h3");
title.appendChild(document.createTextNode("Play statistics"));
settingsZone.appendChild(title);
var div = document.createElement("div");
div.setAttribute("class", "infoMessage messageBox");
var strong = document.createElement("strong");
strong.setAttribute("class", "messageWrapper");
strong.appendChild(document.createTextNode("Displays track played per day, week, month and year on the profile pages."));
div.appendChild(strong);
settingsZone.appendChild(div);
var text = document.createElement("p");
text.appendChild(document.createTextNode("Which date should be used:"));
settingsZone.appendChild(text);
var option = document.createElement("input");
option.setAttribute("type", "radio");
option.setAttribute("name", "playstatistics");
if(GM_getValue("use_reset_date", true) == true) {
option.setAttribute("checked", "checked");
}
option.addEventListener("click", function () {
GM_setValue("use_reset_date", true);
}, false);
settingsZone.appendChild(option);
settingsZone.appendChild(document.createTextNode("on reset date (if the user profile has been reset)"));
settingsZone.appendChild(document.createElement("br"));
var option = document.createElement("input");
option.setAttribute("type", "radio");
option.setAttribute("name", "playstatistics");
if(GM_getValue("use_reset_date", true) != true) {
option.setAttribute("checked", "checked");
}
option.addEventListener("click", function () {
GM_setValue("use_reset_date", false);
}, false);
settingsZone.appendChild(option);
settingsZone.appendChild(document.createTextNode("on profile registration date"));
settingsZone.appendChild(document.createElement("br"));
settingsZone.appendChild(document.createElement("br"));
settingsZone.appendChild(document.createTextNode("Number of decimals showed: "));
var span = document.createElement("span");
span.appendChild(document.createTextNode("-"));
span.setAttribute("style", "border: thin black solid; cursor: pointer; font-family: monospace;");
span.addEventListener("click", function () {
var value = GM_getValue("precision", 2);
if(value > 0) {
GM_setValue("precision", value - 1);
}
var element = document.getElementById("playstatisticsprecision");
if(element) element.innerHTML = GM_getValue("precision", 2);
}, false);
settingsZone.appendChild(span);
var span = document.createElement("span");
span.setAttribute("id", "playstatisticsprecision");
span.setAttribute("style", "border: thin black solid;");
span.innerHTML = GM_getValue("precision", 2);
settingsZone.appendChild(span);
var span = document.createElement("span");
span.appendChild(document.createTextNode("+"));
span.setAttribute("style", "border: thin black solid; cursor: pointer; font-family: monospace;");
span.addEventListener("click", function () {
var value = GM_getValue("precision", 2);
if(value < 5) {
GM_setValue("precision", value + 1);
}
var element = document.getElementById("playstatisticsprecision");
if(element) element.innerHTML = GM_getValue("precision", 2);
}, false);
settingsZone.appendChild(span);
settingsZone.appendChild(document.createElement("br"));
settingsZone.appendChild(document.createElement("hr"));
}
if(isOnSettingsPage()) {
addClickListenerToGreaseMonkeySettingsItem(buildEntryInSettings);
}