User:Zocky/foo.js
From Wikipedia
Note: After saving, you may have to bypass your browser's cache to see the changes. Mozilla / Firefox / Safari: hold down Shift while clicking Reload, or press Ctrl-Shift-R (Cmd-Shift-R on Apple Mac); IE: hold Ctrl while clicking Refresh, or press Ctrl-F5; Konqueror:: simply click the Reload button, or press F5; Opera users may need to completely clear their cache in Tools→Preferences.
document.write('<link rel="stylesheet" type="text/css" href="' + 'http://test.wikipedia.org/w/index.php?title=User:Zocky/foo.css' + '&action=raw&ctype=text/css"/>'); addLoadEvent (fooInit); var fooActions= { toggleDebug: function(fooElement) { if ($('foo-debug')) { if ($a(document.body,'fooDebug') == 'show') a$(document.body,'fooDebug', 'hide') else a$(document.body,'fooDebug', 'show') } return false; }, showId: function(fooElement) { fooDebug (fooElement.id); return false; }, evalScript: function(fooElement) { try { if ($(fooElement.fooParams.source).fooScript) { res=eval($$(fooElement.fooParams.source) || $(fooElement.fooParams.source).textContent); fooElement.fooParams.target && insertOver(fooElement.fooParams.target,res); } else fooDebug ("#" + fooElement.fooParams.source + " is not a script"); } catch (e) { fooDebugError (e); } return false; } }; function fooRegisterAction(name,fn) { fooActions[name]=fn; } function fooClick(fooElement) { var res=false; try { res = fooActions[fooElement.fooParams.action](fooElement); } catch(e){ fooDebugError(e)} return res; } function fooInit() { if ($('foo-application')) { $('foo-application').style.display='none'; insertTop('content', '<div style="border:green solid 1px;background:#dfd;margin:1em;padding:1em;" id="foo-run"><center><b>This page contains an embedded application. If you trust the maintainer(s) of the page, you can <a href="javascript:fooRun()">run it</a>.</b></center></div>'); } } function fooRun() { $('foo-run').style.display="none"; fooConvertTags ({ inTag: 'div', inClass: 'foo-place', outTag: 'div', inOutTag: 'tag', inOutAttr: {'$text$':'$html$',style:'style'}, finalAction: function (In,Out) { if ($(Out.fooParams.ref)) { fooPlace($(Out.fooParams.ref),Out,$(Out.fooParams.where) || 'bottom') In.innerHTML=''; } else over$(In,Out) } }); fooConvertTags ({ inTag: 'span', inClass: 'foo-input', outTag: 'input', outAttr: {type:'text'}, inOutAttr: {size:'size',value:'$text$',style:'style'}, finalAction: function (In,Out) { over$(In,Out) } }); fooConvertTags ({ inTag: 'span', inClass: 'foo-checkbox', outTag: 'input', outAttr: {type:'checkbox'}, inOutAttr: {size:'size', style:'style'}, finalAction: function (In,Out) { Out.fooParams.place=='after' && bottom$(In,Out) || top$(In,Out) } }); fooConvertTags ({ inTag: 'div', inClass: 'foo-textarea', outTag: 'textarea', inOutAttr: {cols:'cols',rows:'rows',$text$:'$text$',style:'style'}, finalAction: function (In,Out) { over$(In,Out) } }); fooConvertTags ({ inTag: 'span', inClass: 'foo-button', outTag: 'input', outAttr: {type:'button',onClick:'fooClick(this)'}, inOutAttr: {size:'size',value:'$text$',style:'style'}, finalAction: function (In,Out) { over$(In,Out) } }); fooConvertTags ({ inTag: 'span', inClass: 'foo-link', outTag: 'a', outAttr: {href:'javascript:return false', onClick:'fooClick(this)'}, inOutAttr: {'$text$':'$text$',style:'style'}, finalAction: function (In,Out) { over$(In,Out) } }); if ($('foo-debug')) fooConvertTags ({ inTag: 'div', inClass: 'foo-script', outTag: 'textarea', outAttr: {'style':'display:block'}, inOutAttr: {cols:'cols',rows:'rows',$text$:'$text$'}, finalAction: function (In,Out) { Out.fooScript=true; a$(In,'class','foo-debug-script'); over$(In,Out) } }); else fooConvertTags ({ inTag: 'div', inClass: 'foo-script', outTag: 'div', outAttr: {style:'display:none'}, inOutAttr: {$text$:'$text$'}, finalAction: function (In,Out) { Out.fooScript=true; over$(In,Out) } }); } function fooDebug(text) { if ($('foo-debug')) { insertBottom('foo-debug', '<div class="fooDebugPrint">' + text + '</div>'); } else alert(text); } function fooDebugError(err) { if ($('foo-debug')) { insertBottom('foo-debug', '<div class="fooDebugError">' + '<b>' + err.name + '</b>: ' + err.message + '</div>'); } else alert('<b>' + err.name + '</b>: ' + err.message); } function fooConvertTags(args) { try { // find tags with the appropriate class - will need xpath 2.0 to work 100% correctly var fooInTags=xNodes("//" + args.inTag + "[not (@foo) and contains(@class,'" + args.inClass +" ')]"); // iterate found tags for ( var j=0 ; j < fooInTags.snapshotLength; j++ ) { var fooInTag=fooInTags.snapshotItem(j); //extract params var params = fooExtractFromClass(fooInTag); //make new element var fooOutTag=c$(params[args.inOutTag] || args.outTag); fooOutTag.fooParams=params; fooOutTag.id=fooInTag.id; fooOutTag.name=fooInTag.id; fooInTag.id += '-container'; //set preset attributes for (i in (args.outAttr || [])) { var value=args.outAttr[i]; if (i=='$text$') fooOutTag.innerHTML = value else (value!=null) && a$(fooOutTag,i,value); } //extract attributes from params for (i in (args.inOutAttr || [])) { var value=args.inOutAttr[i]; switch (value) { case '$text$': value=fooInTag.textContent; break; case '$html$': value=fooInTag.innerHTML; break; default: value=(value in fooOutTag.fooParams) ? fooOutTag.fooParams[value] : null; } if (i=='$text$') fooOutTag.innerHTML = value else (value!=null) && a$(fooOutTag,i,value); } a$(fooInTag,'foo','bar'); // if (!$('foo-debug')) { while($a(fooInTag,'class')!='foo-wrapper') fooInTag=fooInTag.parentNode; a$(fooInTag,'style',''); } args.finalAction(fooInTag, fooOutTag); } } catch (e) {fooDebugError(e)}; } function fooPlace(into,what,where) { switch(where) { case 'top': top$(into,what); break; case 'before': before$(into,what); break; case 'after': after$(into,what); break; case 'bottom': bottom$(into,what); break; case 'over': default: over$(into,what); break; } } function fooExtractFromClass(el) { var text; if(text=$a(el,'class')) { var p=text.replace(/^.* foo:\{/,'{'); a$(el,'class',text.replace(/ foo:.*?$/,'')); return p.parseJSON(); } else return []; } var top$ = function (ref,el) {ref.insertBefore(el,ref.firstChild)} var bottom$ = function (ref,el) {ref.appendChild(el)} var over$ = function (ref,el) {ref.innerHTML = '';ref.appendChild(el)} var before$ = function (ref,el) {ref.parentNode.insertBefore(el,ref)} var after$ = function (ref,el) { if (ref.nextSibling) ref.parentNode.insertBefore(el,ref.nextSibling); else ref.parentNode.appendChild(el) } var $ = function (id) { return document.getElementById(id)} var $$ = function (id) { return document.getElementById(id).value} var c$ = function(tag) {return document.createElement(tag); el.id=id; return el} var $a = function (element,name) {return element.getAttribute(name)} var a$ = function (element,name,value) {return element.setAttribute(name,value)} var insertTop = function (id,what) {$(id).innerHTML = what + $(id).innerHTML} var insertBottom = function (id,what) {$(id).innerHTML += what} var insertOver = function (id,what) {$(id).innerHTML = what} var xNodes=function(x,n) { return document.evaluate(x, n||document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); }; var xNode=function(x,n) { return document.evaluate(x, n||document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue; }; var xString=function(x,n) { return document.evaluate(x, n||document, null, XPathResult.STRING_TYPE, null).stringValue; }; String.prototype.parseJSON = function () { try { return !(/[^,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]/.test( this.replace(/"(\\.|[^"\\])*"/g, ''))) && eval('(' + this + ')'); } catch (e) { return false; } };