Source for "Last.fm - Highlight Same Artists - May 2008 beta2"

By snyde
Has 9 other scripts.


// ==UserScript==
// @name Last.fm - Highlight Same Artists - May 2008 beta2
// @namespace
// @description Highlights artists that you listen to on other users' profiles.
// @include http://www.last.fm/user/*/charts*
// @include http://www.lastfm.*/user/*/charts*
// @include http://www.last.fm/group/*/charts*
// @include http://www.lastfm.*/group/*/charts*
// @include http://www.last.fm/music/+charts/*
// @include http://www.last.fm/music/*/+similar
// ==/UserScript==

// splitD[x] is location of start of the range highlighted with the appropriate styles[x] element
var splitD = new Array();
var styles = new Array();
var sColour = new Array();
splitD[0] = 1 ;  sColour[0] = "magenta"; styles[0] = "color: magenta;"; // "font-weight: bold;"; //
splitD[1] = 11 ; sColour[1] = "red";     styles[1] = "color: red;"; // "font-weight: bold; text-decoration: underline;"; //
splitD[2] = 26 ; sColour[2] = "orange";  styles[2] = "color: orange;"; // "font-style: italic; font-weight: bold;"; //
splitD[3] = 51 ; sColour[3] = "green";   styles[3] = "color: green;"; // "font-style: italic; font-weight: bold; text-decoration: underline;"; //
splitD[4] = 101 ;sColour[4] = "blue";    styles[4] = "color: blue;"; // "font-style: italic;";  //
splitD[5] = 251 ;sColour[5] = "purple";  styles[5] = "color: purple;"; // "font-style: italic; text-decoration: underline;"; //
var nullStyle = "color: #666; font-weight: normal; text-decoration: none; font-style: none;";

var cutoffCountDefault = 1001;  // Maximum match count
var miniCount = 1;	// Minimum tracks played to use artist
var hideOthers = 0;	// Hide artists not on your list (1=yes, 0=no)
var useColours = 2;	// use the colour settings (1) or the style settings (2) or both (3)
var wantUpdShwn = 1;	// show updates on panel

// chartType:		Which chart to use for data. Options: "overall" "3month" "6month" "12month"
var chartType = "3month";

// Don't change variables below here
// ---------------------------------
var chartDescrip = new Object();
chartDescrip["overall"] = "overall";
chartDescrip["12month"] = "1 year";
chartDescrip["6month"] = "6 month";
chartDescrip["3month"] = "3 month";
chartDescrip["weekly"] = "1 week";
var myPan;
var panelHead = "<div class=\"h\"><h2>Highlight Same Artists</h2><a href=\"javascript:;\" class=\"tog collapseTog\" title=\"Collapse Panel\" onclick=\"return collapseBox('hiLightPan', this);\" onfocus=\"blur();\"></a></div><div class=\"c\"><div id=myPanCont>";
var panelTail = "</div></div><div class=\"f\"><div id=myPanTailer></div><span class=\"iesucks\">&nbsp;</span></div>";
var currentChart;
var username;
var artiststr;
var sepstr = "@!#!@";
var lastHide = 0;
var numStyles, cutoffCount, numArtists;
var staticText, theURL;
var splitE;
/* History */
// snyde1: 27-Apr-2007 Modified for new Last.fm
// snyde1:	03-Apr-2007 Modified Greasemonkey script and TopTrax to create this version
// 	09-Apr-2007 Modified to remove hardcoded number of splits
//	06-Jul-2007 Add panel; hide/show toggle support for group charts
//	PROBLEM: with special characters, but do we want to escape them?
//	15-Nov-2007 Fix problem with quilts thanks to Kuge and teganblue
//	07-May-2008 joint version; colour and style
//	11-May-2008 modify method of updates for GM after changing chart
/* SCRIPT */
function xpath(query) {
	return document.evaluate(query, document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
}

function toggleHideArtist () {
	if (hideOthers == 0) { hideOthers = 1; } else { hideOthers  = 0; }
	if (! navigator.userAgent.match(/Opera/)) {GM_setValue("hideOthers",hideOthers); }
	doTheChart();
}

function fixstring(str) {
	str = str.replace(/&quot;/g,'"');
	return(str);
}

function initPanel () {
	if (location.href.match(/http:\/\/[^\/]*\/user/i)) {
		var oldPanel = document.getElementById("shoutboxPanel");
		if (!oldPanel) {
			oldPanel = document.getElementById("userfriends");
			if (!oldPanel) {
				oldPanel = document.getElementById("userneighbours");
			}
		}
	} else if (location.href.match(/http:\/\/[^\/]*\/group/i)) {
		var oldPanel = document.getElementById("avatarPanel");
	} else if (location.href.match(/http:\/\/[^\/]*\/music/i)) {
		var oldPanel = document.getElementById("simpanel");
	}
	if (oldPanel){
		var newPanel = document.createElement("div");
		newPanel.setAttribute("class", "lastPanel");
		newPanel.setAttribute("id", "hiLightPan");
		newPanel.setAttribute("style", "width: 100%;");
		if (location.href.match(/http:\/\/[^\/]*\/group/i)) {
			oldPanel.parentNode.insertBefore(newPanel,oldPanel.nextSibling);
		} else {
			oldPanel.parentNode.insertBefore(newPanel,oldPanel);
		}
		myPan = document.getElementById("hiLightPan");
	}
	if (myPan){
		theStuff = panelHead;
		theStuff += "Loading information.";
		theStuff += panelTail;
		myPan.innerHTML = theStuff;
	}
}

function updatePanel(thisIsTheText) {
	var tempPanelText = document.getElementById("myPanCont");
	if (tempPanelText) { tempPanelText.innerHTML = thisIsTheText; }
}
function updateTail(thisIsTheText) {
	var tempPanelText = document.getElementById("myPanTailer");
	if (tempPanelText) { tempPanelText.innerHTML = thisIsTheText; }
}

function getArt(chartUsed){
	chartType = chartUsed;
	doGetArt();
}

function doGetArt() {
	updateTail("<div align=center>In progress ...</div>");
	updatePanel("Loading artists from your "+chartDescrip[chartType]+" chart.");
	currentChart = chartType;
	cutoffCount = cutoffCountDefault; var newCutoff = -1;
	splitE = new Array();
	for(var i=0; i<splitD.length; i++) { splitE[i]=splitD[i]; }
	var xmlhttp=new XMLHttpRequest();
	theURL = "/user/" + username + "/charts/?charttype="+chartType+"&subtype=artist";
	xmlhttp.open("GET", theURL, false);
	xmlhttp.send(null);
	if (xmlhttp.readyState!=4) { return; }
	var xmlText = xmlhttp.responseText;
	var regexp = /\s&\s/g;
	xmlText = xmlText.replace(regexp, "foo");
	regexp = /(<td[^>]*class="subject")[^>]*>/g;
	xmlText = xmlText.replace(regexp, "$1>");
	if (!xmlText) {
		return;
	}
	if (xmlText.match(/class="barChart artistChart"/)) {
		xmlText = xmlText.split(/class="barChart artistChart"/)[1];
	} else {
		xmlText = xmlText.split(/class="barChart chartWithQuilt artistChart"/)[1];
	}
	var XMLartists = xmlText.split("<tr>");
	var regxp = /<A HREF=[^>]*>([^<]*)<\/A>/i;
	var cntxp = /<td class="quantifier">[^<]*<div[^<]*<span>([^<]*)<\/span>/i;
	artiststr = new Array();
	var artists = new Array(); numArtists = XMLartists.length;
	if (cutoffCount > numArtists) { cutoffCount = numArtists; }
	staticText = "Using "+(cutoffCount-1)+" artists from your "+chartDescrip[chartType]+" chart. (Total number available "+(numArtists-1)+")";
	updatePanel(staticText);
	for(var kount=1; kount < splitE.length; kount++) {
		if (splitE[kount] > cutoffCount) { splitE[kount] = cutoffCount; }
	}
	kount=splitE.length;
	splitE[kount] = cutoffCount;
	numStyles =  styles.length;
	for(var kount=0; kount < styles.length; kount++) {
		if (splitE[kount] >= cutoffCount) {
			numStyles = kount; break;
		}
	}
	for(var kount=0; kount < styles.length; kount++) {
		artiststr[kount] = sepstr;
		for (i=splitE[kount]; i<splitE[kount+1]; i++) {
			var matches = regxp.exec(XMLartists[i]);
			var playCount = cntxp.exec(XMLartists[i])[1];
			if (playCount < miniCount) {
				if (newCutoff < 0) { newCutoff = i; cutoffCount = i; }
			}
			if ((matches != null) && (newCutoff < 0)) {
				  artists[i] = fixstring(matches[1]);
					artiststr[kount] = artiststr[kount] + artists[i] + sepstr;
			}
		}
	}
	doTheChart();
}

function doTheChart() {
		updateTail("<div align=center>In progress ...</div>");
		var testString = "";
		var countRange = new Array();
		if (location.href.match(/music\/\+charts\/.*artist/)) {
			var artLinks = xpath("//table[@class=\"barChart\"][1]//td[@class='subject']/span/a");
		} else {
			var quiltTest = xpath("//table[@class=\"barChart chartWithQuilt artistChart\"]");
			if (quiltTest.snapshotLength < 1) {
				var artLinks = xpath("//table[@class=\"barChart artistChart\"][1]//td[@class='subject']/span/a");
			} else {
				var artLinks = xpath("//table[@class=\"barChart chartWithQuilt artistChart\"][1]//td[@class='subject']/span/a");
			}
		}
//		var artLinks = xpath("//table[@class=\"barChart artistChart\"][1]//td[@class='subject']/span/a");
		for(var kount=0; kount < splitE.length; kount++) { countRange[kount] = 0;}
		for (var i = 0; i < artLinks.snapshotLength; i++) {
			var thisChange = 0;
			var cur = artLinks.snapshotItem(i);
			var curArtist = cur.innerHTML;
			curArtist = curArtist.replace(/<font color=[^>]*>/ig,"");
			curArtist = curArtist.replace(/<\/font>/ig,"");
			if (hideOthers == 0) {
				if (lastHide == 1) {
					cur.parentNode.parentNode.parentNode.setAttribute("style","display:table-row;");
				}
				cur.setAttribute("style", nullStyle);
				cur.innerHTML = curArtist;
			}
			testString = sepstr + curArtist + sepstr;
			for(var kount=0; kount < numStyles; kount++) {
				if (artiststr[kount].indexOf(testString) != -1) {
					if (hideOthers == 1) {
						cur.parentNode.parentNode.parentNode.setAttribute("style","display:table-row;");
					}
					if ((useColours & 2) != 0) {
						cur.setAttribute("style", styles[kount]);
					}
					if ((useColours & 1) != 0) {
						cur.innerHTML = "<font color="+sColour[kount]+">"+curArtist+"</font>";
					}
					(countRange[kount])++;
					thisChange = 1;
					break;
				}
			}
			if (thisChange == 1) {
//	do updates during scan
				if (wantUpdShwn == 1) {
					var mytext = staticText+"<br>Current counts: ";
					for (var j=0; j<styles.length; j++) {
						if (j != 0) {mytext += " / ";}
						if ((useColours & 2) != 0) {mytext += "<span style=\""+styles[j]+" font-size: 12;\">";}
						if ((useColours & 1) != 0) {mytext += "<font color=\""+sColour[j]+"\">";}
						mytext += countRange[j]+"";
						if ((useColours & 1) != 0) {mytext += "</font>";}
						if ((useColours & 2) != 0) {mytext += "</span>";}
					}
					updatePanel(mytext);
				}
			} else {
				if (hideOthers == 1) {
					cur.parentNode.parentNode.parentNode.setAttribute("style","display:none;");
				}
			}
		}
	var textToEnter = "This summary used "+(cutoffCount-1)+" artists from";
	if (cutoffCount < numArtists){ textToEnter += " the "+(numArtists-1)+" on "; }
	textToEnter += " your <a href="+theURL+">"+chartDescrip[currentChart]+"</a> chart, and "+artLinks.snapshotLength+" artists on this page. ";
	if (miniCount > 1) { textToEnter += "(Minimum playcount used for your artists is "+miniCount+".)"; }
	if (navigator.userAgent.match(/Opera/)) {
		textToEnter += "<br> You can redo the comparison with one of the following charts: <br><div align=center><div align=center> <a name=1wk onclick=\"getArt(\'weekly\')\">week</a> <a name=3mo onclick=\"getArt(\'3month\')\">3 months</a> <a name=6mo onclick=\"getArt(\'6month\')\">6 months</a> <a name=yr1 onclick=\"getArt(\'12month\')\">1 year</a> <a name=overall onclick=\"getArt(\'overall\')\">overall</a></div></p>";
		if (hideOthers == 0) {
			textToEnter += "<div align=center><a name=ToggleHide onclick=\"toggleHideArtist()\">Hide non-matching artists</a></div><p>";
		} else {
			textToEnter += "<div align=center><a name=ToggleHide onclick=\"toggleHideArtist()\">Show non-matching artists</a></div><p>";
		}
	} else {
		textToEnter += "<br> See the GreaseMonkey menu for options.<p>";
	}
	textToEnter += "<hr><p>The styles used and matches counted on this page are as follows:";
	textToEnter += "<p><table class=\"barChart artistChart\" width=\"100%\"><tr><td align=left>Artist style</td><td align=right>Count</td></tr>";

	var allFound = 0;
	for (var i=0; i<styles.length; i++){
		allFound = allFound+countRange[i];
		var theWord = " next ";
		if (i == 0) {theWord = " top ";}
		var thePref = ""; var theSuff ="";
		if ((useColours & 2) != 0) {
			thePref = "<span style=\""+styles[i]+"\">"; theSuff = "</span>";
		}
		if ((useColours & 1) != 0) {
			thePref = thePref + "<font color=\""+sColour[i]+"\">"; theSuff = "</font>"+theSuff;
		}
		if (splitE[i+1] < cutoffCount) {
			textToEnter += "<tr><td align=left>"+thePref+"Your"+theWord+(splitE[i+1]-splitE[i])+theSuff;
			textToEnter += "</td><td align=right>"+countRange[i]+"</td></tr>";
		} else {
			textToEnter += "<tr><td align=left>"+thePref+"Your"+theWord+(cutoffCount-splitE[i])+theSuff;
			textToEnter += "</td><td align=right>"+countRange[i]+"</td></tr>";
			break;
		}
	}
	var hdnTxt = ""; if (hideOthers == 1) { hdnTxt="  (hidden)"; }
	textToEnter += "<tr><td align=left><span style=\""+nullStyle+"\">Not yours"+hdnTxt+"</span></td><td align=right> "+(artLinks.snapshotLength-allFound)+"</td></tr></table><p>";
	updatePanel(textToEnter);
	if (location.href.match(/http:\/\/[^\/]*\/user/i)) {
		var userRegexp = /\/user\/([^\/]*)[$\/]/i;
		var thisUser = userRegexp.exec(location.href)[1];
		var xmlhttp=new XMLHttpRequest();
		var theURL = "/user/" + thisUser + "/tasteomatic/";
		xmlhttp.open("GET", theURL, false);
		xmlhttp.send(null);
		var textName = xmlhttp.responseText;
		var tomRegexp = /<div class="Reading">([^<]*)<\/div>/i;
		textName = textName.match(tomRegexp)[1];
		textToEnter += "<hr><div align=center>Taste-O-Meter rating:<br>\""+textName+"\"</div>";
	}
	updatePanel(textToEnter);
	updateTail("<div align=center>You have "+allFound+" matches.</div>");
	lastHide = hideOthers;
}

(function() {
	var usernameLink = xpath("//a[@id='profileImage']");
	if (usernameLink.snapshotLength > 0) {
		username = usernameLink.snapshotItem(0).href;
		username = username.match(/user\/([^\/]*)\//)[1];
	} else {
		return;
	}
	if (location.href.match(/music\/\+charts\/.*artist/)) {
		var links = xpath("//table[@class=\"barChart\"][1]//td[@class='subject']/span/a");
	} else {
		var quiltTest = xpath("//table[@class=\"barChart chartWithQuilt artistChart\"]");
		if (quiltTest.snapshotLength < 1) {
			var links = xpath("//table[@class=\"barChart artistChart\"][1]//td[@class='subject']/span/a");
		} else {
			var links = xpath("//table[@class=\"barChart chartWithQuilt artistChart\"][1]//td[@class='subject']/span/a");
		}
	}
	if (links.snapshotLength < 1) { return; }
//	var re2 = new RegExp(username, "i");	// Is it my page or non-artist?
//	if (location.href.match(re2)) { return; }
	if (location.href.match(/subtype=(?:album|track)/)) { return; }
	if (location.href.match(/charttype=recenttracks/)) { return; }

	if (!navigator.userAgent.match(/Opera/)) {
		chartType = GM_getValue("chartType", chartType);
		GM_registerMenuCommand("Highlight Artist: Select chart", promptForChart);
//		miniCount = GM_getValue("miniCount", miniCount);
//		GM_registerMenuCommand("Highlight Artist: Minimum count", promptForMiniCount);
		hideOthers = GM_getValue("hideOthers", hideOthers);
		GM_registerMenuCommand("Highlight Artist: Toggle hide", toggleHideArtist);
	}
	initPanel();
	if (!chartType) {chartType= "overall";}
	doGetArt();
})();

// Greasemonkey support
function getMiniCount() { 
	return GM_getValue("miniCount", 1); 
}
function promptForMiniCount() {
	GM_setValue("miniCount", prompt("What is the minimum number of plays to consider?", getMiniCount()));
	document.location.reload();
}
function getForChart() {
	return GM_getValue("chartType", "overall");
}
function promptForChart() {
	GM_setValue("chartType", prompt("What chart do you want to use? (overall, weekly, 12month, 6month, 3month)", getForChart()));
	if (!chartDescrip[GM_getValue("chartType")]){
		GM_setValue("chartType", "overall");
		chartType = "overall";
	}
	chartType=GM_getValue("chartType");
	doGetArt();
	chartType=GM_getValue("chartType");
}