All pastes #151058 Raw Edit

Mine

public javascript v1 · immutable
#151058 ·published 2006-08-27 16:59 UTC
rendered paste body
// ==UserScript==// @name          Homestar Subtitles Pre-Alpha// @namespace     http://www.hrwiki.org/// @description	  Subtitles for Homestar Runner// @include       http://homestarrunner.com/*// @include       http://www.homestarrunner.com/*// @include       http://podstar.homestarrunner.com/*// @include       http://videlectrix.com/*// @include       http://www.videlectrix.com/*// @include       http://hrwiki.org/mirror/*// @include       http://www.hrwiki.org/mirror/*// @include       https://secure.homestarrunner.com/heythanks.html*// ==/UserScript==var subtitleOptions = {	"colors": true, // distinguish characters by colors	"captions": true, // include sound effects	"lang": "en",	"debug": false}var characters = {	"sfx": {		"color": "#FFF",		"name": {"en": ""}	}};var transcript = new Array()var flash = false;var subtitleholder = false;var currentsubtitles = false;var nosubtitles = document.createComment("");var currentsubtitles = nosubtitles;var filename = location.pathname.toLowerCase();var i = filename.lastIndexOf('/');if (i >= 0)	filename = filename.substr(i + 1);i = filename.lastIndexOf('.');if (i >= 0)	filename = filename.substr(0,i);GM_log("Loading character list...");GM_xmlhttpRequest({	method: "GET",	url: "http://www.hrwiki.org/index.php/HRWiki:Subtitles/Characters?action=raw",	onload: charactersLoaded});function charactersLoaded(results){	var parser = new unsafeWindow.DOMParser();	var text = results.responseText;	GM_log(text);	text = text.replace(/^\s+/g, "");	var doc = parser.parseFromString(text, "application/xml");	var speakers = doc.getElementsByTagName("speaker");	for (var i = 0; i < speakers.length; i++)	{		var speakername = speakers[i].getAttribute("id");		characters[speakername] = {"color": speakers[i].getAttribute("color"), "name": {"en": ""}};		var names = speakers[i].getElementsByTagName("name");		for (var j = 0; j < names.length; j++)		{			var lang = names[j].getAttribute("xml:lang");			characters[speakername].name[lang] = names[j].firstChild.nodeValue;		}	}	if (subtitleOptions["debug"])	{		for (i in characters)		{			var p = document.createElement('p');			p.style.color = characters[i].color;			p.appendChild(document.createTextNode(characters[i].name.en));			document.body.appendChild(p);		}	}	GM_log("Loading transcript...");	GM_xmlhttpRequest({		method: "GET",		url: "http://www.hrwiki.org/index.php?title=HRWiki:Subtitles/" + subtitleOptions["lang"] + "/" + escape(filename) + "&action=raw",		onload: function(x) { transcriptLoaded(x, false); }	});}function transcriptLoaded(results, redirected){	GM_log("All loaded.");	var parser = new unsafeWindow.DOMParser();	var text = results.responseText;	GM_log(text);	text = text.replace(/^\s+/g, "");	// check for redirects	var matches = text.match(/^#REDIRECT\s*\[\[(.*)\]\]/i);	if (matches)	{		if (redirected) // trap double-redirects			return;		text = matches[1];		if (matches = text.match(/^(.*)\|/))			text = matches[1];		if (matches = text.match(/^(.*)\#/))			text = matches[1];		text = text.replace(/^\s+|\s+$/g, '');		text = text.replace(/ /, '_');		GM_xmlhttpRequest({			method: "GET",			url: "http://www.hrwiki.org/index.php?title=" + escape(text) + "&action=raw",			onload: function(x) { transcriptLoaded(x, true); }		});		return;	}	if (text == "")		// text = "<?xml version=\"1.0\" encoding=\"utf-8\"?><transcript><line start=\"0\" end=\"1000000000\">No transcript found</line></transcript>";		return;	var doc = parser.parseFromString(text, "application/xml");	// set some defaults	if (!doc.documentElement.getAttribute("xml:lang")) doc.documentElement.setAttribute("xml:lang", "en");	if (!doc.documentElement.getAttribute("dir"))      doc.documentElement.setAttribute("dir",      "ltr");	// inherit languages to all subnodes	inheritLanguages(doc.documentElement);	// now parse the lines into divs and get start and end frames	var lines = doc.getElementsByTagName("line");	for (var i = 0; i < lines.length; i++)	{		var line = new Object();		line.start = lines[i].getAttribute("start");		line.end = lines[i].getAttribute("end");		line.text = importNodes(lines[i]);		transcript.push(line);				if (subtitleOptions["debug"])		{			document.body.appendChild(document.createTextNode("\xA0\xA0\xA0\xA0Start: " + line.start + " End: " + line.end));			document.body.appendChild(line.text);		}	}	if (subtitleOptions["debug"])		document.body.style.color="white";		GM_log("Setting up subtitles...");	setupSubtitles();}function inheritLanguages(node){	for (var i = node.firstChild; i; i = i.nextSibling)	{		if (i.nodeType == i.ELEMENT_NODE)		{			if (!i.getAttribute("xml:lang")) i.setAttribute("xml:lang", node.getAttribute("xml:lang"));			if (!i.getAttribute("dir"))      i.setAttribute("dir",      node.getAttribute("dir"));			inheritLanguages(i);		}	}}// replacement for document.importNode() that actually works properly// turning eg <span> into an HTML span element, rather than an unknown element// that happens to be called "span".function importNodes(node){	var name = node.nodeName.toLowerCase();	if (characters[name])	{		node.setAttribute("speaker", name);		name = "speaker";	}	if (name == "line" || name == "speaker")	{		// format the speaker appropriately as a div		var speaker = node.getAttribute("speaker");		if (!subtitleOptions["captions"] && speaker == "sfx")			return document.createComment(""); // return nothing		newNode = document.createElement("div");		var char = characters[speaker];		if (!char)			char = {"color": "#FFF", "name": {"en": ""}};		if (subtitleOptions["colors"])			newNode.style.color = char.color;		if (node.getAttribute("voiceover"))			newNode.style.fontStyle = "italic";		if (node.getAttribute("volume"))			newNode.style.fontSize = (node.getAttribute("volume") * 100) + "%";		newNode.lang = node.getAttribute("xml:lang");		newNode.dir = node.getAttribute("dir");		var hasSpeakerChildren = false;		for (var i = node.firstChild; i; i = i.nextSibling)		{			if (i.nodeType == i.ELEMENT_NODE)			{				newNode.appendChild(importNodes(i));				var a = i.nodeName.toLowerCase();				if (i == "line" || i == "speaker" || characters[i])					hasSpeakerChildren = true;			}			else if (i.nodeType == i.TEXT_NODE || i.nodeType == i.CDATA_SECTION_NODE)				newNode.appendChild(document.importNode(i, true));		}		if (!hasSpeakerChildren)		{			// this is a normal text node - do some extra text stuff			if (speaker == 'sfx' || speaker == 'thecheat' || speaker == 'pompom')			{				newNode.insertBefore(document.createTextNode('('), newNode.firstChild);				newNode.appendChild(document.createTextNode(')'))				newNode.style.fontStyle = "italic";			}			if (!subtitleOptions["colors"])			{				// find the language with the longest prefix match				// fall back to "en" if none found				var bestmatch = "en";				var langbits = node.getAttribute("xml:lang").split("-");				for (i = langbits.length; i >= 1; i--)				{					var lang = langbits.slice(0, i).join("-");					if (char.name[lang])					{						bestmatch = lang;						break;					}				}				if (char.name[bestmatch] != '')					newNode.insertBefore(document.createTextNode(char.name[bestmatch] + ": "), newNode.firstChild);			}		}		return newNode;	}	else	{		// check element blacklist		if (name == "script" ||		    name == "style"  ||		    name == "object" ||		    name == "param"  ||		    name == "embed"  ||		    name == "a"      ||		    name == "img"    ||		    name == "applet" ||		    name == "map"    ||		    name == "frame"  ||		    name == "iframe" ||		    name == "meta"   ||		    name == "link"   ||		    name == "form"   ||		    name == "input")			return document.createComment(""); // return nothing		var newNode = document.createElement(name);		// copy across attributes		for (var i = 0; i < node.attributes.length; i++)		{			name = node.attributes[i].nodeName.toLowerCase();			// check attribute blacklist			// javascript, and anything that might load stuff from offsite			if (name != "href" && name != "src" && name.substring(0, 2) != "on")			{				if (name == "style")				{					// regex taken from MediaWiki Sanitizer.php					if (!node.attributes[i].nodeValue.match(/(expression|tps*:\/\/|url\\s*\().*/i))						newNode.setAttribute("style", node.attributes[i].nodeValue);				}				else					newNode.setAttribute(node.attributes[i].nodeName, node.attributes[i].nodeValue);			}		}		// copy across children		for (var i = node.firstChild; i; i = i.nextSibling)		{			if (i.nodeType == i.ELEMENT_NODE)				newNode.appendChild(importNodes(i));			else if (i.nodeType == i.TEXT_NODE || i.nodeType == i.CDATA_SECTION_NODE)				newNode.appendChild(document.importNode(i, true));		}		return newNode;	}	document.createComment(""); // fallthrough}function setupSubtitles(){	subtitleholder = document.createElement('div');	subtitleholder.style.fontSize = "25px";	subtitleholder.style.lineHeight = "25px";	subtitleholder.style.color = "white";	subtitleholder.style.backgroundColor = "black";	subtitleholder.style.height = "100px";	subtitleholder.style.marginTop = "10px";	subtitleholder.style.textAlign = "center";	document.body.appendChild(subtitleholder);	subtitleholder.appendChild(nosubtitles);	flash = document.getElementsByTagName("embed")[0].wrappedJSObject;		var oldopen = unsafeWindow.open;	unsafeWindow.open = function(a,b,c)	{		c = c.split(/,/);		var opts = {};		for (var i = 0; i < c.length; i++)		{			var d = c[i].split(/=/);			opts[d[0]] = d[1];		}		opts["width"] = window.screen.width * 0.8;		opts["height"] = window.screen.height * 0.8;		opts["resizeable"] = "yes";		c = "";		for (var i in opts)		{			c += i + "=" + opts[i] + ",";		}		return oldopen(a,b,c);	}		GM_log("Starting refresh loop...");	setTimeout(refreshSubtitles, 100);}function setSubtitles(node){	if (!node)		node = nosubtitles;	if (currentsubtitles != node)	{		subtitleholder.replaceChild(node, subtitleholder.firstChild);		currentsubtitles = node;	}}function refreshSubtitles(){	var frame = false;	if (flash)		frame = flash.CurrentFrame;	if (typeof(frame) == "function")		frame = frame();	if (typeof(frame) == "number" && frame >= 0)	{		// change from native 0-based to more friendly 1-based		frame++;		// binary search to find the right transcript line		var first = 0;		var last = transcript.length;		while(first < (last - 1))		{			var mid = (first + last) >> 1;			if (frame >= transcript[mid].start)				first = mid;			else				last = mid;		}		// should we actually show the line?		if(transcript[first].start <= frame && transcript[first].end >= frame)			setSubtitles(transcript[first].text);		else			setSubtitles(false);	}	setTimeout(refreshSubtitles, 100);}