User:Tyrok1/monobook.js: Difference between revisions

From Rosetta Code
Content added Content deleted
(Let's try a cookie instead of an HTML5 data store)
(Trying new link)
 
(7 intermediate revisions by the same user not shown)
Line 1: Line 1:
//<lang javascript>
/*========================================
/*========================================
This comparison script was written by
This comparison script was written by
Tyrok1, and has been tested on IE 5.5,
Tyrok1, and has been tested on Fx 3.6.6,
Cr 5.0.375.99, Epiphany 2.30.2,
IE 6, IE 7, IE 8, Fx 3.6.2, and
Fe 4.0.280.
Midori 0.2.2
========================================*/
========================================*/


var gadgetsAvailable = [
function SectionLinkLoad()
{
id: "LanguageComparison",
name: "Language comparison",
url: "http://rosettacode.org/mw/index.php" +
"?title=Rosetta_Code:Language_comparison_script" +
"&action=raw&ctype=text/javascript",
prefix: "Compare"
},
{
id: "Highlight",
name: "Syntax Highlight Color Picker",
url: "http://rosettacode.org/mw/index.php" +
"?title=Rosetta_Code:Syntax_Highlight_Color_Picker" +
"&action=raw&ctype=text/javascript",
prefix: "Highlight"
},
{
id: "UtilityButtonBar",
name: "Utility button bar",
url: "http://rosettacode.org/mw/index.php" +
"?title=Rosetta_Code:Per-Code_Example_Buttonbar" +
"&action=raw&ctype=text/javascript",
prefix: "ButtonBar"
}
];

function GadgetsAddHandler(el, handlerType, func)
{
{
//add an event handler in a more cross-browser way
//load cached language link info from the cookie
if(el.addEventListener)
if((typeof JSON != "undefined") && (typeof JSON.parse != "undefined"))
{
{
el.addEventListener(handlerType, func, false);
var cookieStart = document.cookie.indexOf("languageLinks=");
}
window.languageLinks = new Object();
else if(el.attachEvent)
if(cookieStart >= 0)
{
{
el.attachEvent("on" + handlerType, func);
var cookieEnd = document.cookie.indexOf(";", cookieStart);
}
cookieStart += ("languageLinks=").length;
else
cookieEnd = (cookieEnd >= 0 ? cookieEnd : document.cookie.length);
{
var cookieVal = document.cookie.substring(cookieStart, cookieEnd);
eval("el.on" + handlerType + " = func;");
window.languageLinks = JSON.parse(decodeURIComponent(cookieVal));
}
}
}
}
}


function SectionLinkSave()
function GadgetsScriptLoad(g)
{
{
//see if we need to load it
//save language link info to the cookie for later use
//if we don't, there's not much point in loading it again
if((typeof JSON != "undefined") && (typeof JSON.stringify != "undefined"))
if(!document.getElementById("GadgetScript" + g))
{
{
var scriptEl = document.createElement("script");
var data = encodeURIComponent(JSON.stringify(window.languageLinks));
scriptEl.setAttribute("id", "GadgetScript" + g);
document.cookie = "languageLinks=" + data;
scriptEl.setAttribute("type", "text/javascript");
scriptEl.setAttribute("src", gadgetsAvailable[g].url);
document.documentElement.appendChild(scriptEl);
}
}
}
}


function SectionLinkCreateLoadClosure(request)
function GadgetsScriptActivate(g)
{
{
//check to see if the script's finished loading
if(eval("typeof " + gadgetsAvailable[g].prefix + "Activate") == "undefined")
{
//not finished yet - try reactivating in another 0.5s
setTimeout(function() { GadgetsScriptActivate(g); }, 500);
}
else
{
//run the activation function
eval(gadgetsAvailable[g].prefix + "Activate();");
}
}

function GadgetsScriptDeactivate(g)
{
//check to see if the specified script has a deactivation function
if(eval("typeof " + gadgetsAvailable[g].prefix + "Deactivate") != "undefined")
{
//it does - run it
eval(gadgetsAvailable[g].prefix + "Deactivate();");
}
else
{
//pop up a warning to the user to let them know
//the plugin will be disabled when they reload
alert("This script will be disabled on next page load");
}
}

function GadgetsCreateCheckboxClosure(el)
{
//create an onclick handler for the script checkboxes
return function() {
return function() {
//save the checkboxes to the cookie for next page load
if(request.readyState == 4)
GadgetsSaveCheckboxes();
//check to see if we need to activate or deactivate
if(el.checked)
{
{
//done loading
//load and activate the script
GadgetsScriptLoad(el.value);
//initialize the "languages with link information" array
GadgetsScriptActivate(el.value);
if(typeof window.languageLinks == "undefined" || !window.languageLinks || !window.languageLinks.length)
{
}
else
window.languageLinks = new Object();
}
{
//deactivate the script
GadgetsScriptDeactivate(el.value);
//skip the toc
var text = request.responseText;
var curPos = text.indexOf(" id=\"toctitle\"");
var catLinksStart = text.indexOf("catlinks");
curPos = text.indexOf("</table>", curPos);
//start looking for anchor tags with name attributes
while((curPos = text.indexOf("a name=\"", curPos)) >= 0)
{
//isolate the name attribute
curPos += ("a name=\"").length;
var endPos = text.indexOf("\"", curPos);
var curAName = text.substring(curPos, endPos);
//find the next anchor with a name attribute so we know where the next section is
var nextA = text.indexOf("a name=\"", endPos);
//look for a language header
var headlinePos = text.indexOf("mw-headline", endPos);
if(nextA < headlinePos || text.substring(endPos, headlinePos).indexOf("h3") >= 0)
{
//no <h2> header
//not a full language section
continue;
}
//look for the end of the header and isolate the content of the header
var headlineEnd = text.indexOf("</h2>", headlinePos);
var headline = text.substring(headlinePos, headlineEnd);
//isolate the language category page it links to
var hrefStart = headline.indexOf(" href=\"") + (" href=\"").length;
var hrefEnd = headline.indexOf("\"", hrefStart);
var curHREF = headline.substring(hrefStart, hrefEnd);
//isolate the displayed text name of the language
var titleStart = headline.indexOf(" title=\"Category:") + (" title=\"Category:").length;
var titleEnd = headline.indexOf("\"", titleStart);
var curTitle = headline.substring(titleStart, titleEnd);
//check to make sure we have all the information we need about this language
if(curAName == "" || curHREF == "" || curTitle == "")
{
//something's missing
continue;
}
//add the language to our array for later use
window.languageLinks[curTitle] = { aName: curAName, href: curHREF, title: curTitle };
}
//save the link data, if possible,
//to reduce the number of requests
SectionLinkSave();
//and if we've got a function to call when we're done, call it
if(request.callback)
{
request.callback();
}
}
}
};
};
}
}


function SectionLinkFetchFrom(url, callback)
function GadgetsMouseOver()
{
{
//show the scripts dropdown
//fetch the given page and store all <a name>/language pairs on the page to the cookie for later
document.getElementById("pt-jsgadgets-list").style.display = "block";
var request = new XMLHttpRequest();
request.onreadystatechange = SectionLinkCreateLoadClosure(request);
request.callback = callback;
request.open("GET", url, true);
request.send("");
}
}


function SectionLinkActivate()
function GadgetsMouseOut()
{
{
//hide the scripts dropdown
//check to see if we're looking at a language page
var catLinksEl = document.getElementById("catlinks");
document.getElementById("pt-jsgadgets-list").style.display = "none";
}
var isLanguage = false;

if(catLinksEl)
function GadgetsSaveCheckboxes()
{
var checkedBoxes = "", checkboxEl = null;
//build a string representation of all of the checked boxes to save to the cookie
for(var c = 0; checkboxEl = document.getElementById("pt-jsgadgets-gadget" + c); ++c)
{
{
if(checkboxEl.checked)
var aEls = catLinksEl.getElementsByTagName("a");
for(var a = 0; a < aEls.length; ++a)
{
{
if(checkedBoxes != "")
if(aEls[a].getAttribute("title") == "Category:Programming Languages")
{
{
//it's a language
checkedBoxes += ",";
isLanguage = true;
break;
}
}
checkedBoxes += gadgetsAvailable[c].id;
}
}
}
if(!isLanguage)
{
//we're not on a language page
//this script does not apply
return;
}
}
//set an expiry date 1000 years into the future
//load stored data to reduce requests
var expireDate = new Date();
SectionLinkLoad();
expireDate.setFullYear(expireDate.getFullYear() + 1000);
//store the cookie
//check this page's "firstHeading" ID content for a category name
document.cookie = "jsGadgets=" + escape(checkedBoxes) +
var firstHeadingEl = document.getElementById("firstHeading");
"; expires=" + expireDate.toUTCString();
var langName = (firstHeadingEl.textContent ? firstHeadingEl.textContent : firstHeadingEl.innerText);
}
langName = langName.substring(("Category:").length, langName.length);

function GadgetsGetCheckboxes()
{
//pull in the cookie and look for the jsGadgets key
var fullCookie = document.cookie;
var gadgetsPos = fullCookie.indexOf("jsGadgets=");
if(gadgetsPos < 0)
{
//no gadgets in the cookie
return new Array();
}
var endPos = fullCookie.indexOf(";", gadgetsPos);
//split the gadget IDs by comma
//get a list of all task pages on this page for later use
var jsGadgets = fullCookie.substring(gadgetsPos + ("jsGadgets=").length,
var tasksEl = document.getElementById("mw-pages");
(endPos > 0 ? endPos : fullCookie.length));
var aEls = tasksEl.getElementsByTagName("a");
var checkIDs = unescape(jsGadgets).split(",");
//translate the list of IDs to a list of array indices,
//check to see if we already have link information about the current language
//in keeping with the way the rest of this module works
if(window.languageLinks && window.languageLinks[langName])
var checkIndices = new Array();
for(var g = 0; g < gadgetsAvailable.length; ++g)
{
{
for(var c = 0; c < checkIDs.length; ++c)
//we do
//modify all of the links on the page to link directly to the current language's section
for(var i = 0; i < aEls.length; ++i)
{
{
if(aEls[i].href.indexOf("#") < 0)
if(gadgetsAvailable[g].id == checkIDs[c])
{
{
checkIndices[checkIndices.length] = g;
aEls[i].href += "#" + encodeURIComponent(window.languageLinks[langName].aName);
break;
}
}
}
}
}
}
return checkIndices;
else
}

function GadgetsActivate()
{
//find the user preferences button and add a new list item to the right of it
var prefsEl = document.getElementById("pt-preferences");
if(!prefsEl)
{
{
var personalEl = document.getElementById("p-personal");
//we do not have link information on the current language
if(!personalEl)
//start fetching task pages and searching through them, starting with the first task link on the page
if(typeof SectionLinkActivate.linkNum == "undefined")
{
{
return;
SectionLinkActivate.linkNum = 0;
}
}
var liEls = personalEl.getElementsByTagName("li");
if(!liEls || liEls.length < 2)
//only check the first five task links
if(SectionLinkActivate.linkNum >= 5)
{
{
return;
return;
}
}
prefsEl = liEls[liEls.length - 2];
}
var jsMenuEl = prefsEl.parentNode.insertBefore(
document.createElement("li"), prefsEl.nextSibling);
jsMenuEl.setAttribute("id", "pt-jsgadgets");
//add a new link named "My scripts" in the new list item
//from a semantics point of view, this is not great,
//but this way the styling kicks in to keep it consistent with its siblings
var jsLinkEl = jsMenuEl.appendChild(document.createElement("a"));
jsLinkEl.appendChild(document.createTextNode("My scripts"));
jsLinkEl.setAttribute("href", "javascript: void(0);");
jsLinkEl.style.position = "relative";
//add handlers for showing on mouseover and hiding on mouseout
GadgetsAddHandler(jsLinkEl, "mouseover", GadgetsMouseOver);
GadgetsAddHandler(jsLinkEl, "mouseout", GadgetsMouseOut);
//build a list for showing available JS gadgets
var modulesListEl = jsLinkEl.appendChild(document.createElement("ol"));
modulesListEl.setAttribute("id", "pt-jsgadgets-list");
modulesListEl.style.listStyle = "none";
modulesListEl.style.margin = 0;
modulesListEl.style.padding = 0;
modulesListEl.style.position = "absolute";
modulesListEl.style.top = "100%";
modulesListEl.style.left = 0;
modulesListEl.style.backgroundColor = "#fff";
modulesListEl.style.border = "1px solid #69c";
modulesListEl.style.padding = "0.5em";
modulesListEl.style.display = "none";
//raise the zIndex of the new button (as well as
//a few parents) so the menu overlaps the page
var zEl = modulesListEl;
for(var z = 0; z < 6 && zEl && zEl.style; ++z, zEl = zEl.parentNode)
{
zEl.style.zIndex = 100;
}
//add each of the gadgets to the list
for(var m = 0; m < gadgetsAvailable.length; ++m)
{
//add the list item element
var liEl = modulesListEl.appendChild(document.createElement("li"));
liEl.style.display = "block";
liEl.style.cssFloat = "none";
liEl.style.right = "auto";
liEl.style.left = 0;
liEl.style.textAlign = "left";
liEl.style.margin = 0;
liEl.style.padding = 0;
//add the checkbox
//fetch and process the task, and rerun this activation function when done
var inputEl = document.createElement("input");
SectionLinkFetchFrom(aEls[SectionLinkActivate.linkNum].href, SectionLinkActivate);
var checkboxId = "pt-jsgadgets-gadget" + m;
inputEl.setAttribute("type", "checkbox");
inputEl.setAttribute("id", checkboxId);
inputEl.setAttribute("value", m);
GadgetsAddHandler(inputEl, "click", GadgetsCreateCheckboxClosure(inputEl));
liEl.appendChild(inputEl);
//add the label
//update the link number so we move on to the next link if the current one doesn't have this language
var labelEl = document.createElement("label");
++SectionLinkActivate.linkNum;
labelEl.setAttribute("for", checkboxId);
labelEl.appendChild(document.createTextNode(gadgetsAvailable[m].name));
labelEl.style.paddingLeft = "1em";
liEl.appendChild(labelEl);
}
//fetch the saved checkboxes from the cookie
var checks = GadgetsGetCheckboxes();
for(var c = 0; c < checks.length; ++c)
{
//for each one that should be checked on page load,
//check the box, load, and activate it
document.getElementById("pt-jsgadgets-gadget" + checks[c]).checked = true;
GadgetsScriptLoad(checks[c]);
GadgetsScriptActivate(checks[c]);
}
}
}
}


//register the link correcting script with the window's load event
//register the comparison script with the window's load event
GadgetsAddHandler(window, "load", GadgetsActivate);
if(window.addEventListener)
//</lang>
{
window.addEventListener("load", SectionLinkActivate, false);
}
else if(window.attachEvent)
{
window.attachEvent("onload", SectionLinkActivate);
}
else if(document.addEventListener)
{
document.addEventListener("load", SectionLinkActivate, false);
}
else
{
window.onload = SectionLinkActivate;
}

Latest revision as of 19:34, 3 July 2011

//<lang javascript>
/*========================================
This comparison script was written by
Tyrok1, and has been tested on Fx 3.6.6,
Cr 5.0.375.99, Epiphany 2.30.2,
Midori 0.2.2
========================================*/

var gadgetsAvailable = [
					{
						id: "LanguageComparison",
						name: "Language comparison",
						url: "http://rosettacode.org/mw/index.php" +
							"?title=Rosetta_Code:Language_comparison_script" + 
							"&action=raw&ctype=text/javascript",
						prefix: "Compare"
					},
					{
						id: "Highlight",
						name: "Syntax Highlight Color Picker",
						url: "http://rosettacode.org/mw/index.php" +
							"?title=Rosetta_Code:Syntax_Highlight_Color_Picker" +
							"&action=raw&ctype=text/javascript",
						prefix: "Highlight"
					},
					{
						id: "UtilityButtonBar",
						name: "Utility button bar",
						url: "http://rosettacode.org/mw/index.php" +
							"?title=Rosetta_Code:Per-Code_Example_Buttonbar" +
							"&action=raw&ctype=text/javascript",
						prefix: "ButtonBar"
					}
				];

function GadgetsAddHandler(el, handlerType, func)
{
	//add an event handler in a more cross-browser way
	if(el.addEventListener)
	{
		el.addEventListener(handlerType, func, false);
	}
	else if(el.attachEvent)
	{
		el.attachEvent("on" + handlerType, func);
	}
	else
	{
		eval("el.on" + handlerType + " = func;");
	}
}

function GadgetsScriptLoad(g)
{
	//see if we need to load it
	//if we don't, there's not much point in loading it again
	if(!document.getElementById("GadgetScript" + g))
	{
		var scriptEl = document.createElement("script");
		scriptEl.setAttribute("id", "GadgetScript" + g);
		scriptEl.setAttribute("type", "text/javascript");
		scriptEl.setAttribute("src", gadgetsAvailable[g].url);
		document.documentElement.appendChild(scriptEl);
	}
}

function GadgetsScriptActivate(g)
{
	//check to see if the script's finished loading
	if(eval("typeof " + gadgetsAvailable[g].prefix + "Activate") == "undefined")
	{
		//not finished yet - try reactivating in another 0.5s
		setTimeout(function() { GadgetsScriptActivate(g); }, 500);
	}
	else
	{
		//run the activation function
		eval(gadgetsAvailable[g].prefix + "Activate();");
	}
}

function GadgetsScriptDeactivate(g)
{
	//check to see if the specified script has a deactivation function
	if(eval("typeof " + gadgetsAvailable[g].prefix + "Deactivate") != "undefined")
	{
		//it does - run it
		eval(gadgetsAvailable[g].prefix + "Deactivate();");
	}
	else
	{
		//pop up a warning to the user to let them know
		//the plugin will be disabled when they reload
		alert("This script will be disabled on next page load");
	}
}

function GadgetsCreateCheckboxClosure(el)
{
	//create an onclick handler for the script checkboxes
	return function() {
				//save the checkboxes to the cookie for next page load
				GadgetsSaveCheckboxes();
				
				//check to see if we need to activate or deactivate
				if(el.checked)
				{
					//load and activate the script
					GadgetsScriptLoad(el.value);
					GadgetsScriptActivate(el.value);
				}
				else
				{
					//deactivate the script
					GadgetsScriptDeactivate(el.value);
				}
			};
}

function GadgetsMouseOver()
{
	//show the scripts dropdown
	document.getElementById("pt-jsgadgets-list").style.display = "block";
}

function GadgetsMouseOut()
{
	//hide the scripts dropdown
	document.getElementById("pt-jsgadgets-list").style.display = "none";
}

function GadgetsSaveCheckboxes()
{
	var checkedBoxes = "", checkboxEl = null;
	
	//build a string representation of all of the checked boxes to save to the cookie
	for(var c = 0; checkboxEl = document.getElementById("pt-jsgadgets-gadget" + c); ++c)
	{
		if(checkboxEl.checked)
		{
			if(checkedBoxes != "")
			{
				checkedBoxes += ",";
			}
			checkedBoxes += gadgetsAvailable[c].id;
		}
	}
	
	//set an expiry date 1000 years into the future
	var expireDate = new Date();
	expireDate.setFullYear(expireDate.getFullYear() + 1000);
	
	//store the cookie
	document.cookie = "jsGadgets=" + escape(checkedBoxes) +
			"; expires=" + expireDate.toUTCString();
}

function GadgetsGetCheckboxes()
{
	//pull in the cookie and look for the jsGadgets key
	var fullCookie = document.cookie;
	var gadgetsPos = fullCookie.indexOf("jsGadgets=");
	if(gadgetsPos < 0)
	{
		//no gadgets in the cookie
		return new Array();
	}
	var endPos = fullCookie.indexOf(";", gadgetsPos);
	
	//split the gadget IDs by comma
	var jsGadgets = fullCookie.substring(gadgetsPos + ("jsGadgets=").length,
					(endPos > 0 ? endPos : fullCookie.length));
	var checkIDs = unescape(jsGadgets).split(",");
	
	//translate the list of IDs to a list of array indices,
	//in keeping with the way the rest of this module works
	var checkIndices = new Array();
	for(var g = 0; g < gadgetsAvailable.length; ++g)
	{
		for(var c = 0; c < checkIDs.length; ++c)
		{
			if(gadgetsAvailable[g].id == checkIDs[c])
			{
				checkIndices[checkIndices.length] = g;
				break;
			}
		}
	}
	return checkIndices;
}

function GadgetsActivate()
{
	//find the user preferences button and add a new list item to the right of it
	var prefsEl = document.getElementById("pt-preferences");
	if(!prefsEl)
	{
		var personalEl = document.getElementById("p-personal");
		if(!personalEl)
		{
			return;
		}
		var liEls = personalEl.getElementsByTagName("li");
		if(!liEls || liEls.length < 2)
		{
			return;
		}
		prefsEl = liEls[liEls.length - 2];
	}
	var jsMenuEl = prefsEl.parentNode.insertBefore(
				document.createElement("li"), prefsEl.nextSibling);
	jsMenuEl.setAttribute("id", "pt-jsgadgets");
	
	//add a new link named "My scripts" in the new list item
	//from a semantics point of view, this is not great,
	//but this way the styling kicks in to keep it consistent with its siblings
	var jsLinkEl = jsMenuEl.appendChild(document.createElement("a"));
	jsLinkEl.appendChild(document.createTextNode("My scripts"));
	jsLinkEl.setAttribute("href", "javascript: void(0);");
	jsLinkEl.style.position = "relative";
	
	//add handlers for showing on mouseover and hiding on mouseout
	GadgetsAddHandler(jsLinkEl, "mouseover", GadgetsMouseOver);
	GadgetsAddHandler(jsLinkEl, "mouseout", GadgetsMouseOut);
	
	//build a list for showing available JS gadgets
	var modulesListEl = jsLinkEl.appendChild(document.createElement("ol"));
	modulesListEl.setAttribute("id", "pt-jsgadgets-list");
	modulesListEl.style.listStyle = "none";
	modulesListEl.style.margin = 0;
	modulesListEl.style.padding = 0;
	modulesListEl.style.position = "absolute";
	modulesListEl.style.top = "100%";
	modulesListEl.style.left = 0;
	modulesListEl.style.backgroundColor = "#fff";
	modulesListEl.style.border = "1px solid #69c";
	modulesListEl.style.padding = "0.5em";
	modulesListEl.style.display = "none";
	
	//raise the zIndex of the new button (as well as
	//a few parents) so the menu overlaps the page
	var zEl = modulesListEl;
	for(var z = 0; z < 6 && zEl && zEl.style; ++z, zEl = zEl.parentNode)
	{
		zEl.style.zIndex = 100;
	}
	
	//add each of the gadgets to the list
	for(var m = 0; m < gadgetsAvailable.length; ++m)
	{
		//add the list item element
		var liEl = modulesListEl.appendChild(document.createElement("li"));
		liEl.style.display = "block";
		liEl.style.cssFloat = "none";
		liEl.style.right = "auto";
		liEl.style.left = 0;
		liEl.style.textAlign = "left";
		liEl.style.margin = 0;
		liEl.style.padding = 0;
		
		//add the checkbox
		var inputEl = document.createElement("input");
		var checkboxId = "pt-jsgadgets-gadget" + m;
		inputEl.setAttribute("type", "checkbox");
		inputEl.setAttribute("id", checkboxId);
		inputEl.setAttribute("value", m);
		GadgetsAddHandler(inputEl, "click", GadgetsCreateCheckboxClosure(inputEl));
		liEl.appendChild(inputEl);
		
		//add the label
		var labelEl = document.createElement("label");
		labelEl.setAttribute("for", checkboxId);
		labelEl.appendChild(document.createTextNode(gadgetsAvailable[m].name));
		labelEl.style.paddingLeft = "1em";
		liEl.appendChild(labelEl);
	}
	
	//fetch the saved checkboxes from the cookie
	var checks = GadgetsGetCheckboxes();
	for(var c = 0; c < checks.length; ++c)
	{
		//for each one that should be checked on page load,
		//check the box, load, and activate it
		document.getElementById("pt-jsgadgets-gadget" + checks[c]).checked = true;
		GadgetsScriptLoad(checks[c]);
		GadgetsScriptActivate(checks[c]);
	}
}

//register the comparison script with the window's load event
GadgetsAddHandler(window, "load", GadgetsActivate);
//</lang>