Source for "YouTube Lyrics"

By Aquilax
Has 11 other scripts.


// ==UserScript==
// @name           YouTube Lyrics
// @namespace      http://userscripts.org/users/28612
// @version        2.10.00
// @description   Adds a lyrics box to the YouTube sidebar under the video informations box. It can search in nine different lyrics sites and it shows also all the results in a drop down.
// @include        http://*youtube.com/watch?*
// ==/UserScript==

var ScriptInfos={
	name: "Youtue Lyrics",
	version: "2.10.00",
	newVersionDays: 1,
	newVersionHandler: null,
	newVersionValueName: "NewVersionLastCheck",
	newVersionXPath: "//div[@id='lyricLinkDiv']",
	newVersionStyle: "",
	newVersionHtmlId: "ScriptInfosNewVersion",
	homepageUrl: "http://userscripts.org/scripts/show/22569",
	sourceUrl: "http://userscripts.org/scripts/review/22569",
	installUrl: "http://userscripts.org/scripts/source/22569.user.js"};

addLyricPanel();

function addLyricPanel()
{
	GM_registerMenuCommand(ScriptInfos.name+" - Update",function(){sendGetRequest(ScriptInfos.sourceUrl,dialogNewVersion)});
	
	try{
	
		var div0=document.getElementById("more-from-panel").parentNode;
		var div1=div0.cloneNode(true);
		div1.id="lyricPanel";
		if (div1.className.indexOf("expanded")!=-1) div1.className=div1.className.replace("expanded","");

		var div3=div1.getElementsByTagName("DIV")[0];
		div3.id="lyricLinkDiv";
		if (div3.className.indexOf("expanded")!=-1) div3.className=div3.className.replace("expanded","");
		
		var link1=div3.getElementsByTagName("A")[0];
		link1.setAttribute("title",ScriptInfos.name+" v. "+ScriptInfos.version);
		link1.addEventListener("click",function(e){if (!e.target.onlyOnce) {e.target.onlyOnce=true; loadLyrics();}},false);
		
		var img1=div3.getElementsByTagName("IMG")[0];
		img1.setAttribute("src","http://s.ytimg.com/yt/img/pixel-vfl73.gif");
		img1.nextSibling.data="Lyrics";
		
		var div4=div3.getElementsByTagName("DIV")[0];
		div4.id="lyricContentDiv";
		div4.innerHTML="";
		div4.setAttribute("style","overflow: scroll; height: 200px;");

		var div5=document.createElement("DIV");
		div5.id="lyricToggle";
		div5.className="expand-content";
		div5.setAttribute("style","float: right");
		div3.insertBefore(div5,div3.firstChild);

		var link2=document.createElement("A");
		link2.setAttribute("href","javascript:void(0);");
		link2.addEventListener("click",savePrefSite,false);
		link2.appendChild(document.createTextNode("save"));
		div5.appendChild(link2);

		/*
		var 
base64="data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAAA0AAAANCAYAAABy6+R8AAAABHNCSVQICAgIfAhkiAAAAHxJREFUKJGNktENxCAMQ1+7E
t1/AjOT76P0DkJyqqV8RCaynYALCCrKKSOwhV0MnlRo0CsutzVKWLBZvbuHeEqjxvDMCczXv/fHS6+f8tls+lUmCzlNm9cTs6T24vaaDUchoD/bW/IFRWVKM/oB
cGdN864HyH9BzLTbe4EPsoGHzJJeDZ0AAAAASUVORK5CYII=";

		var image1=document.createElement("IMAGE");
		image1.setAttribute("alt","Set site as prefered");
		image1.setAttribute("src",base64);
		image1.setAttribute("width","150");
		image1.setAttribute("height","150");

		link1.appendChild(image1);
		*/
		
		var select1=document.createElement("SELECT");
		select1.name="lyricSites";
		select1.id="lyricSites";
		select1.addEventListener("change",function(e){loadLyrics();},false);
		div5.appendChild(select1);

		var prefLyricSite=GM_getValue("prefLyricSite");
		
		var array1=["lyricwiki.org","lyrics.astraweb.com","metrolyrics.com","musica.com","get-lyric.net","lyricsdownload.com","lyricsondemand.com","sweetslyrics.com","songmeanings.net","lyrics.com"];
		for(var num1=0;num1<array1.length;num1++)
		{
			var option1=document.createElement("OPTION");
			option1.innerHTML=array1[num1];
			option1.value=array1[num1];
			option1.selected=option1.value==prefLyricSite;
			select1.appendChild(option1);
		}
		
		div0.parentNode.insertBefore(div1,div0);
		
		if (checkElapsedTime()) sendGetRequest(ScriptInfos.sourceUrl,htmlNewVersion);
	}
	catch(ex){sendGetRequest(ScriptInfos.sourceUrl,htmlNewVersion);}
}

function sendGetRequest(url,handler,mimeType)
{	
	//GM_log("Requested url: "+url);
	GM_xmlhttpRequest({
   		method: "GET",
		url: url,
		headers: {"User-agent": "Mozilla/4.0 (compatible) Greasemonkey", "Accept": "text/html"},
		overrideMimeType: mimeType,
		onload: handler });
}

function checkElapsedTime()
{
	try
	{
		var date1=GM_getValue(ScriptInfos.newVersionValueName);
		if (date1)
		{
			var num1=Date.parse(date1);
			var num2=new Date().getTime();
			var num3=1000*60*60*24*ScriptInfos.newVersionDays;
			return num2-num1>num3;
		}
	}
	catch(ex){}

	return true;
}

function $X(xpath,doc,xpathResult)
{
	if (doc==null) doc=document;
	if (xpathResult==null) xpathResult==XPathResult.ORDERED_NODE_ITERATOR_TYPE;
	return doc.evaluate(xpath,doc,null,xpathResult,null);
}

function $X1(xpath,doc){return $X(xpath,doc,XPathResult.FIRST_ORDERED_NODE_TYPE).singleNodeValue;}

function htmlNewVersion(response)
{	
	setLastCheckDate();
	if (newVersionAvailable(response.responseText))
	{
		if (ScriptInfos.newVersionHandler!=null) ScriptInfos.newVersionHandler();
		else
		{
			var element1=$X1(ScriptInfos.newVersionXPath);
			if (element1==null)
			{
				element1=$X1("//body");
				if (element1==null) {dialogNewVersion(response); return;}
			}
			
			var div1=document.createElement("DIV");
			div1.id=ScriptInfos.newVersionHtmlId;
			div1.setAttribute("style",ScriptInfos.newVersionStyle);
			element1.insertBefore(div1,element1.firstChild);
			
			var link1=document.createElement("A");
			link1.setAttribute("href","javascript:void(0);");
			link1.setAttribute("title","Close");
			link1.setAttribute("style","float:right");
			link1.addEventListener("click",function(){setLastCheckDate();hideHtmlNewVersion();},false);
			link1.appendChild(document.createTextNode("[Close]"));
			div1.appendChild(link1);
			
			div1.appendChild(document.createTextNode("A "));
			
			var link2=document.createElement("A");
			link2.setAttribute("href",ScriptInfos.installUrl);
			link2.setAttribute("title","Install new version ("+ScriptInfos.newVersion+")");
			link2.addEventListener("click",function(){setLastCheckDate();hideHtmlNewVersion();},false);
			link2.appendChild(document.createTextNode("new version ("+ScriptInfos.newVersion+")"));
			div1.appendChild(link2);
			
			div1.appendChild(document.createTextNode(" of "));
			
			var link3=document.createElement("A");
			link3.setAttribute("href",ScriptInfos.homepageUrl);
			link3.setAttribute("target","_blank");
			link3.setAttribute("title","Navigate to the homepage");
			link3.appendChild(document.createTextNode(ScriptInfos.name));
			div1.appendChild(link3);
			
			div1.appendChild(document.createTextNode(" is available!"));
		}
	}
}

function dialogNewVersion(response)
{
	if (!newVersionAvailable(response.responseText)) alert(ScriptInfos.name+" ("+ScriptInfos.version+") is up to date.");
	else if (confirm("A new version ("+ScriptInfos.newVersion+") of "+ScriptInfos.name+" is available.\nDo you want to install it?")) document.location=ScriptInfos.installUrl;
	setLastCheckDate();
}

function newVersionAvailable(responseText)
{
	ScriptInfos.newVersion=/version.*?((?:\.|\d)+)/gmi.test(responseText)?RegExp.$1:"99.99.99";
	return compareVersions(ScriptInfos.version,ScriptInfos.newVersion)==-1;
}

function compareVersions(version1,version2)
{
	var array1=version1.toString().split(".");
	var array2=version2.toString().split(".");
	for (var num1=0;num1<array1.length || num1<array2.length;num1++)
	{
		var num2=num1<array1.length?parseInt(array1[num1]):0;
		var num3=num1<array2.length?parseInt(array2[num1]):0;
		if (num2<num3) return -1;
		else if (num2>num3) return 1;
	}
	return 0;
}

function setLastCheckDate()
{
	GM_setValue(ScriptInfos.newVersionValueName,new Date().toString());
}

function hideHtmlNewVersion()
{
	var div1=document.getElementById(ScriptInfos.newVersionDivId.newVersionHtmlId);
	if (div1!=null) div1.parentNode.removeChild(div1);
}

function debugRegexp(exp,text)
{
	do
	{
		var match1="";
		try{match1=new RegExp(exp,"gmi").exec(text);}
		catch(exception){match1=exception.message;}
		exp=prompt(match1?match1:"<null>",exp);
	} while(exp)
}

function sendRequest(url,handler)
{
	var text1=null;
	switch(ScriptInfos.site)
	{
		case "musica.com":
		case "lyrics.astraweb.com":
		case "lyricsondemand.com":
			text1="text/html; charset=ISO-8859-1;";
			break;
	}
	
	sendGetRequest(url,handler,text1);
}

function savePrefSite()
{
	var select1=document.getElementById("lyricSites");
	var text1=select1.options[select1.selectedIndex].value;
	GM_setValue("prefLyricSite",text1);
	alert(text1+" has been saved as prefered");
}

function setLyricDivContent(html,addLyricsTextBox,addResultsDropDown,addLinkToOriginalPage)
{
	var div1=document.getElementById("lyricContentDiv");
	div1.innerHTML="";
	
	if (addLyricsTextBox)
	{
		var input1=document.createElement("INPUT");
		input1.type="text";
		input1.name="words";
		input1.size="50";
		input1.value=ScriptInfos.words;
		input1.addEventListener("keypress",function(e){if (e.which==13){loadLyrics(this.value); return false;}},false);
		div1.appendChild(input1);
	}
	if (addResultsDropDown)
	{
		var select1=document.createElement("SELECT");
		select1.name="results";
		select1.addEventListener("change",function(e){loadLyricPage(e.target.selectedIndex);},false);
		for(var num1=0;num1<ScriptInfos.links.length;num1++) 
		{
			var option1=new Option(ScriptInfos.links[num1][1]);
			if (ScriptInfos.index==num1) option1.selected=true;
			select1.options[num1]=option1;
		}
		div1.appendChild(select1);
	}
	if (addLinkToOriginalPage)
	{
		div1.appendChild(document.createElement("BR"));
		div1.appendChild(document.createElement("BR"));
		
		var link1=document.createElement("A");
		link1.href=ScriptInfos.links[ScriptInfos.index][0];
		link1.target="_blank";
		link1.textContent="Original Page";
		div1.appendChild(link1);
		
		div1.appendChild(document.createElement("BR"));
		div1.appendChild(document.createElement("BR"));
	}

	var span1=document.createElement("SPAN");
	span1.innerHTML=html;
	div1.appendChild(span1);
}

function loadLyrics(words)
{	
	var select1=document.getElementById("lyricSites");
	ScriptInfos.site=select1.options[select1.selectedIndex].value;
	
	if (words) ScriptInfos.words=words;
	if (ScriptInfos.words==null)
	{
		var text1=document.title.replace(/youtube/gmi,"");
		
		/*
		var array1=document.getElementsByTagName("TITLE");
		if (array1.length!=0) text1=array1[0].textContent.replace(/youtube/gmi,"");
		else
		{
			var div1=document.getElementById("vidTitle");
			if (div1!=null) text1=div1.textContent;
			else
			{
				var array2=document.getElementsByTagName("META");
				for (var num1=0;num1<array2.lenght;num1++)
				{
					var meta1=array2[num1];
					if (meta1.getAttribute("name")=="title") {text1=meta1.getAttribute("content"); break;}
				}
			}
		}
		*/
		ScriptInfos.words=text1.replace(/-/gmi," ").replace(/"/gmi," ").replace(/video/gmi," ").replace(/ +/gmi," ").replace(/^\s+/gmi,"").replace(/\s+$/gmi,"");
	}
	
	var text2=encodeURIComponent(ScriptInfos.words).replace(/%20/gmi,"+");
	var text3=null;
	switch(ScriptInfos.site)
	{
		case "lyricwiki.org":
		case "musica.com":
		case "lyricsdownload.com":
		case "lyricsondemand.com":
		case "sweetslyrics.com":
		case "songmeanings.net":
		case "lyrics.com":
			text3="http://www.google.com/search?num=20&q=site%3A"+encodeURIComponent(ScriptInfos.site)+"+"+text2;
			break;
		case "lyrics.astraweb.com":
			text3="http://search.lyrics.astraweb.com/?word="+text2;
			break;
		case "metrolyrics.com":
			text3="http://www.metrolyrics.com/search.php?category=artisttitle&search="+text2;
			break;
		case "get-lyric.net":
			text3="http://www.get-lyric.net/lyrics/"+text2.replace(/\+/gmi,"-")+"-all.html";
			break;
		default:
			setLyricDivContent("No implementation found for "+ScriptInfos.site);
			return;
	}
	
	setLyricDivContent("Searching "+ScriptInfos.site+" for \""+ScriptInfos.words+"\"");
	sendRequest(text3,parseSearchResponse);
}

function parseSearchResponse(response)
{
	var text1="";
	var text2="";
	ScriptInfos.links=new Array();

	switch(ScriptInfos.site)
	{
		case "lyricwiki.org":
			text1="<a.*?href=\"(http://"+ScriptInfos.site+".*?)\".*?>(.*?) - lyrics from lyricWiki</a>";
			break;
		case "lyrics.astraweb.com":
			text1="<a.*?href=\"(/display/.*?)\".*?>(.*?)</a>";
			text2="http://"+ScriptInfos.site;
			break;
		case "metrolyrics.com":
			text1="<td class=\"First\"><a href=\"(.*?)\">(.*?) Lyrics</a></td>";
			break;
		case "musica.com":
			text1="<a.*?href=\"(http://www."+ScriptInfos.site+".*?)\".*?>(?:MUSICA\.COM(?:,|:) )?(?:letra de )?(.*?)(?: - MUSICA\.COM)?</a>";
			break;
		case "get-lyric.net":
			text1="<a href=\"(/lyrics-\\d+/.*\\.html)\".*?>\\s*(.*?)\\s*</a>";
			text2="http://www."+ScriptInfos.site;
			break;
		case "lyricsdownload.com":
			text1="<a.*?href=\"(http://www."+ScriptInfos.site+".*?)\".*?>(.*?)(?: LYRICS)?</a>";
			break;
		case "lyricsondemand.com":
			text1="<a.*?href=\"(http://www."+ScriptInfos.site+".*?)\".*?>(.*?)(?: - (?:Letras|Lyrics) On Demand)?</a>";
			break;
		case "sweetslyrics.com":
			text1="<a.*?href=\"(http://www."+ScriptInfos.site+".*?)\".*?>(.*?)(?: Lyrics)?</a>";
			break;
		case "songmeanings.net":
			text1="<a.*?href=\"(http://www."+ScriptInfos.site+".*?)\".*?>(?:SongMeanings . lyrics . )(.*?)</a>";
			break;
		case "lyrics.com":
			text1="<a.*?href=\"(http://www."+ScriptInfos.site+".*?)\".*?>"+ScriptInfos.site+" - (.*?)</a>";
			break;
		default:
			setLyricDivContent("No implementation found for "+ScriptInfos.site);
			return;
	}
	
	//debugRegexp(text1,response.responseText);
	
	var regexp1=new RegExp(text1,"gmi");
	var match1=regexp1.exec(response.responseText);
	while(match1)
	{
		//GM_log(match1[1]+" "+match1[2]);
		ScriptInfos.links.push([text2+match1[1],match1[2].replace(/<\/?b>/gmi,"")]);
		match1=regexp1.exec(response.responseText);
	}
	
	if (ScriptInfos.links.length!=0) loadLyricPage(0);
	else setLyricDivContent("Found nothing on "+ScriptInfos.site,true);
}

function loadLyricPage(index)
{
	ScriptInfos.index=index;
	setLyricDivContent("Loading from "+ScriptInfos.site+" \""+ScriptInfos.links[index][1]+"\"");
	sendRequest(ScriptInfos.links[index][0],parseLyricPage);
}

function parseLyricPage(response)
{	
	var text1=null;
	
	switch(ScriptInfos.site)
	{
		case "lyricwiki.org":
			text1="<h1 class=\"firstHeading\">(.*?)</h1>(?:.|\n)*?<div class='lyricbox' >(.*?)</div>";
			break;
		case "lyrics.astraweb.com":
			text1="<b>Title:</b>(?:.|\n)*?<b>(.*?)</b>(?:.|\n)*?<font face=arial size=2>((?:.|\n)*?)</font>";
			break;
		case "metrolyrics.com":
			text1="<div id=\"SongTextIntro\">(?:.|\n|\r)*?<strong>(.*?) Lyrics</strong>(?:.|\n|\r)*?</div>(?:.|\n|\r)*?</div>((?:.|\n|\r)*?)</div>";
			break;
		case "musica.com":
			text1="<b>LETRA ' (.*?) '</b>(?:.|\n|\r)*?<font style=line-height:18px;font-size:10pt;font-family:arial,tahoma,verdana>((?:.|\n|\r)*?)</font>";
			break;
		case "get-lyric.net":
			text1="More:</td>(?:.|\n|\r)*?<a.*?>(.*?)</a>(?:.|\n|\r)*?<div style=\"font-size:12px;text-align:center;\">\\s*((?:.|\n|\r)*?)</div>";
			break;
		case "lyricsdownload.com":
			text1="<b> GET (.*?) ringtones </b>(?:.|\n|\r)*?<center><font class=\"txt_1\">((?:.|\n|\r)*?)</font> </center>";
			break;
		case "lyricsondemand.com":
			text1="class=\"NoUnderPlain\"(?:.|\n|\r)*?>(?:Letras de )?(.*?)(?: Lyrics)?</a>(?:.|\n|\r)*?<font size=\"2\" face=\"Verdana\">((?:.|\n|\r)*?)<BR><BR>";
			break;
		case "sweetslyrics.com":
			text1="<title>(.*?) Lyrics</title>(?:.|\n|\r)*?trans_right\.gif(?:.|\n|\r)*?</div>((?:.|\n|\r)*?)<div";
			break;
		case "songmeanings.net":
			text1="<td class=\"greybackgr\"><strong>(.*?)</strong></td>(?:.|\n|\r)*?Ringtone</a>(?:.|\n|\r)*?<td.*?>((?:.|\n|\r)*?)</td>";
			break;
		case "lyrics.com":
			text1="<title>"+ScriptInfos.site+"  - (.*?)</title>(?:.|\n|\r)*?document\\.write\\(\"<br><lyrics>(.*?)\"\\);";
			break;
		default:
			setLyricDivContent("No implementation found for "+ScriptInfos.site);
			return;
	}
	
	var text2="";
	var text3="";
	var text4=null;
	
	if (response.status!=200) text4=response.statusText;
	else
	{
		try
		{
			//debugRegexp(text1,response.responseText);
			var regexp1=new RegExp(text1,"gmi");
			var match1=regexp1.exec(response.responseText);
			text2=match1[1];
			text3=match1[2];
		}
		catch(exception){text4="Lyric parsing error: the page doesn't contains lyrics!";}
	}

	text2=text2.replace(/<br ?\/?>/gmi,"");
	if (response.responseText.match(/<pre>/gmi)) text3=text3.replace(/\n/gmi,"<br/>").replace(/\r/gmi,"");
	text3=text3.replace(/<br ?\/?>/gmi,"<br/>").replace(/<br\/>(?:\s*<br\/>)+/gmi,"<br/>").replace(/^\s*(?:<br\/>\s*)+/gmi,"");
	
	var text5="";
	if (text4) text5="<div style=\"color: red;\">"+text4+"</div>";
	else text5="<div style=\"font-size: 18px;\"><u><b>"+text2+"</b></u></div><div>"+text3+"</div>";		

	setLyricDivContent(text5,true,true,true);
}