User:Tyrok1/monobook.js: Difference between revisions

From Rosetta Code
Content added Content deleted
(Testing the per-code example buttonbar)
(Testing a new script)
Line 1:
/*========================================
This comparison script was written by
Tyrok1, and has been tested on IEFx 7,3.6.6
IE 8, Fx 3.6.3, and Fe 5.0.380.
========================================*/
 
var gadgetsAvailable = [
//define the relationship between the CSS classes and the language names
{ 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" },
var buttonBarCodepadLanguages = [
{ 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" }
{ cssClass: "c", padName: "C" },
{ cssClass: "cpp", padName: "C++" },
{ cssClass: "d", padName: "D" },
{ cssClass: "haskell", padName: "Haskell" },
{ cssClass: "lua", padName: "Lua" },
{ cssClass: "ocaml", padName: "OCaml" },
{ cssClass: "php", padName: "PHP" },
{ cssClass: "perl", padName: "Perl" },
{ cssClass: "python", padName: "Python" },
{ cssClass: "ruby", padName: "Ruby" },
{ cssClass: "scheme", padName: "Scheme" },
{ cssClass: "tcl", padName: "Tcl" }
];
 
function AddHandlerGadgetsAddHandler(el, handlerType, func)
{
//add an event handler in a more cross-browser way
Line 38 ⟶ 26:
}
 
function IsChildGadgetsScriptLoad(parent, childg)
{
//check to see if anwe elementneed is a child ofto anotherload elementit
//if we don't, there's not much point in loading it again
while(child && child != parent)
if(!document.getElementById("GadgetScript" + g))
{
var scriptEl = document.createElement("script");
child = child.parentNode;
scriptEl.setAttribute("id", "GadgetScript" + g);
scriptEl.setAttribute("type", "text/javascript");
scriptEl.setAttribute("src", gadgetsAvailable[g].url);
document.documentElement.appendChild(scriptEl);
}
return (child == parent);
}
 
function ButtonBarSelectAllGadgetsScriptActivate(preElg)
{
//check to see if the script's finished loading
//select all code within a given <pre> element
if(eval("typeof " + gadgetsAvailable[g].prefix + "Activate") == "undefined")
var range = null;
var menuEl = preEl.getElementsByTagName("ul")[0];
if(((document.createRange && (range = document.createRange())) || (document.selection.createRange && (range = document.selection.createRange()))) && range.selectNodeContents)
{
//not finished yet - try reactivating in another 0.5s
//for Fx, Fe, and other more standards-compliant browsers
setTimeout(function() { GadgetsScriptActivate(g); }, 500);
range.selectNodeContents(preEl);
range.setEndBefore(menuEl);
var sel = window.getSelection();
if(sel.setBaseAndExtent)
{
//odd variant of a few of the WebKit browsers
sel.setBaseAndExtent(preEl, 0, menuEl, 0);
}
else
{
sel.removeAllRanges();
sel.addRange(range);
}
}
else
{
//run the activation function
//for IE
eval(gadgetsAvailable[g].prefix + "Activate();");
range = document.body.createTextRange();
range.moveToElementText(preEl);
var menuRange = document.body.createTextRange();
menuRange.moveToElementText(menuEl);
//deselect the popup menu
while(range.compareEndPoints("EndToStart", menuRange) > 0)
{
range.moveEnd("word", -1);
}
range.select();
}
//return the range so other functions can use it
return range;
}
 
function ButtonBarCreateSelectAllGadgetsScriptDeactivate(preElg)
{
//check to see if the specified script has a deactivation function
return function() {
if(eval("typeof " + gadgetsAvailable[g].prefix + "Deactivate") != "undefined")
//select all of the text in the pre element
ButtonBarSelectAll(preEl);
};
}
 
function ButtonBarCreateCopy(preEl)
{
return function() {
//copy all of the text in the pre element
//IE-only at this point
var range = ButtonBarSelectAll(preEl);
range.execCommand("Copy");
};
}
 
function ButtonBarGetText(preEl)
{
//get the code from inside of a <pre> element
var outText = "";
for(var c = 0; c < preEl.childNodes.length; ++c)
{
//it does - run it
switch(preEl.childNodes[c].tagName ? preEl.childNodes[c].tagName.toLowerCase() : "")
eval(gadgetsAvailable[g].prefix + "Deactivate();");
{
}
case "br":
else
{
{
outText += "\n";
//pop up a warning to the user to let them know the plugin will be disabled when they reload
} break;
alert("This script will be disabled on next page load");
case "ul":
{
//get rid of &nbsp;s
outText = outText.replace(/\xA0/g, " ");
//return the cleaned text
return outText;
} break;
default:
{
outText += (preEl.childNodes[c].textContent ? preEl.childNodes[c].textContent : (preEl.childNodes[c].innerText ? preEl.childNodes[c].innerText : preEl.childNodes[c].data));
}
}
}
//get rid of &nbsp;s
outText = outText.replace(/\xA0/g, " ");
//return the cleaned text
return outText;
}
 
function ButtonBarAddSpacerGadgetsCreateCheckboxClosure(ulElel)
{
//addcreate aan spaceronclick bullethandler item tofor the menuscript listcheckboxes
var spacerEl = ulEl.appendChild(document.createElement("li"));
spacerEl.appendChild(document.createTextNode("\u2022"));
spacerEl.style.display = "inline";
spacerEl.style.marginLeft = "0.5em";
spacerEl.style.marginRight = "0.5em";
}
 
function ButtonBarCreateMouseOver(preEl)
{
//the mouseover event handler for <pre> elements
return function() {
//ifsave there'sthe alreadycheckboxes ato menu,the don'tcookie addfor anothernext page load
GadgetsSaveCheckboxes();
if(preEl.getElementsByTagName("ul").length > 0)
{
return false;
}
//check to see if we need to activate or deactivate
//style the <pre> and add the menu
if(el.checked)
preEl.style.position = "relative";
var ulEl = preEl.appendChild(document.createElement("ul"));
ulEl.className = "ButtonBar";
ulEl.style.position = "absolute";
ulEl.style.right = 0;
ulEl.style.top = 0;
ulEl.style.whitespace = "nowrap";
ulEl.style.marginRight = "0.5em";
//define actions we want to add
var listItems = [
{title:"Select All",code:ButtonBarCreateSelectAll(preEl)}
];
if(window.clipboardData)
{
//load and activate the script
listItems[listItems.length] = {title:"Copy to Clipboard",code:ButtonBarCreateCopy(preEl)};
GadgetsScriptLoad(el.value);
GadgetsScriptActivate(el.value);
}
else
//add the standard menu items
for(var i = 0; i < listItems.length; ++i)
{
//if it's not the first one, add a spacer
if(i > 0)
{
ButtonBarAddSpacer(ulEl);
}
var liEl = ulEl.appendChild(document.createElement("li"));
liEl.appendChild(document.createTextNode(listItems[i].title));
liEl.style.cursor = "pointer";
liEl.style.display = "inline";
liEl.style.fontFamily = "sans-serif";
liEl.style.textDecoration = "underline";
AddHandler(liEl, "click", listItems[i].code);
}
//check for a codepad-supported language
var langClass = preEl.className.split(" ")[0];
for(var l = 0; l < buttonBarCodepadLanguages.length; ++l)
{
//deactivate the script
if(langClass == buttonBarCodepadLanguages[l].cssClass)
GadgetsScriptDeactivate(el.value);
{
//found the language
//add <li>s
ButtonBarAddSpacer(ulEl);
var liEl = ulEl.appendChild(document.createElement("li"));
liEl.style.display = "inline";
//build a form to submit to codepad
var formEl = liEl.appendChild(document.createElement("form"));
formEl.target = "_blank";
formEl.method = "post";
formEl.action = "http://codepad.org";
formEl.style.display = "inline";
var inputValues = [
{ name: "lang", value: buttonBarCodepadLanguages[l].padName },
{ name: "code", value: ButtonBarGetText(preEl) },
{ name: "run", value: "True" },
{ name: "private", value: "True" }
];
for(var i = 0; i < inputValues.length; ++i)
{
var inputEl = document.createElement("input");
inputEl.setAttribute("type", "hidden");
inputEl.setAttribute("name", inputValues[i].name);
inputEl.setAttribute("value", inputValues[i].value);
formEl.appendChild(inputEl);
}
//add and style the submit button to look like the other items
var inputEl = document.createElement("input");
inputEl.setAttribute("type", "submit");
inputEl.setAttribute("name", "submit");
inputEl.setAttribute("value", "Try on Codepad");
inputEl.style.border = "none";
inputEl.style.background = "transparent";
inputEl.style.cursor = "pointer";
inputEl.style.textDecoration = "underline";
inputEl.style.display = "inline-block";
inputEl.style.padding = 0;
formEl.appendChild(inputEl);
break;
}
}
return false;
};
}
 
function ButtonBarCreateMouseOutGadgetsMouseOver(preEl)
{
//show the scripts dropdown
//mouseout handler
document.getElementById("pt-jsgadgets-list").style.display = "block";
return function(e) {
//if we're moving to another element inside of the same <pre>, add a mouseout handler and return
if(!e) e = window.event;
var target = e.relatedTarget || e.toElement;
if(IsChild(preEl, target))
{
AddHandler(target, "mouseout", ButtonBarCreateMouseOut);
return false;
}
//we're moving away from the container <pre>, so we need to remove all menu lists
var ulEls = preEl.getElementsByTagName("ul");
for(var u = 0; u < ulEls.length; ++u)
{
ulEls[u].parentNode.removeChild(ulEls[u]);
}
return false;
};
}
 
function ButtonBarActivateGadgetsMouseOut()
{
//hide the scripts dropdown
//check to see if we're looking at a task page
var catLinksEl = document.getElementById("catlinkspt-jsgadgets-list").style.display = "none";
}
var isTask = 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)
{
checkedBoxes += (checkboxEl.checked ? (checkedBoxes != "" ? "," : "") + gadgetsAvailable[c].id : "");
var aEls = catLinksEl.getElementsByTagName("a");
}
for(var a = 0; a < aEls.length; ++a)
//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 checkIDs = fullCookie.substring(gadgetsPos + ("jsGadgets=").length, (endPos > 0 ? endPos : fullCookie.length)).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])
if(aEls[a].getAttribute("title") == "Category:Programming Tasks")
{
checkIndices[checkIndices.length] = g;
//it's a task
isTask = true;
break;
}
}
}
return checkIndices;
if(!isTask)
}
 
function GadgetsActivate()
{
//find the user preferences button and add a new list item to the right of it
var prefsEl = document.getElementById("pt-preferences");
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;
return;
}
//add each of the gadgets to the list
//look for language examples
for(var m = 0; m < gadgetsAvailable.length; ++m)
var allPres = document.getElementsByTagName("pre");
for(var p = 0; p < allPres.length; ++p)
{
//add the list item element
if(allPres[p].className && allPres[p].className.indexOf("highlighted_source") >= 0)
var liEl = modulesListEl.appendChild(document.createElement("li"));
{
liEl.style.display = "block";
//set up the onmouseover, onmousleave events to show/hide the button bar
liEl.style.cssFloat = "none";
AddHandler(allPres[p], "mouseover", ButtonBarCreateMouseOver(allPres[p]));
liEl.style.right = "auto";
AddHandler(allPres[p], "mouseout", ButtonBarCreateMouseOut(allPres[p]));
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
AddHandlerGadgetsAddHandler(window, "load", ButtonBarActivateGadgetsActivate);

Revision as of 22:21, 18 July 2010

/*========================================
This comparison script was written by
Tyrok1, and has been tested on Fx 3.6.6
========================================*/

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: "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)
	{
		checkedBoxes += (checkboxEl.checked ? (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 checkIDs = fullCookie.substring(gadgetsPos + ("jsGadgets=").length, (endPos > 0 ? endPos : fullCookie.length)).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");
	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);