User:Siddhartha Ghai/TWG.js
Appearance
Code that you insert on this page could contain malicious content capable of compromising your account. If you import a script from another page with "importScript", "mw.loader.load", "iusc", or "lusc", take note that this causes you to dynamically load a remote script, which could be changed by others. Editors are responsible for all edits and actions they perform, including by scripts. User scripts are not centrally supported and may malfunction or become inoperable due to software changes. A guide to help you find broken scripts is available. If you are unsure whether code you are adding to this page is safe, you can ask at the appropriate village pump. This code will be executed when previewing this page. |
This user script seems to have a documentation page at User:Siddhartha Ghai/TWG. |
( function ( window, document, $, TWG, undefined ) { // Wrap with anonymous function
/**
* **************** twAddPortlet() ****************
*
* Adds a portlet menu to one of the navigation areas on the page.
* This is necessarily quite a hack since skins, navigation areas, and
* portlet menu types all work slightly different.
*
* Available navigation areas depend on the skin used.
* Monobook:
* "column-one", outer div class "portlet", inner div class "pBody". Existing portlets: "p-cactions", "p-personal", "p-logo", "p-navigation", "p-search", "p-interaction", "p-tb", "p-coll-print_export"
* Special layout of p-cactions and p-personal through specialized styles.
* Vector:
* "mw-panel", outer div class "portal", inner div class "body". Existing portlets/elements: "p-logo", "p-navigation", "p-interaction", "p-tb", "p-coll-print_export"
* "left-navigation", outer div class "vectorTabs" or "vectorMenu", inner div class "" or "menu". Existing portlets: "p-namespaces", "p-variants" (menu)
* "right-navigation", outer div class "vectorTabs" or "vectorMenu", inner div class "" or "menu". Existing portlets: "p-views", "p-cactions" (menu), "p-search"
* Special layout of p-personal portlet (part of "head") through specialized styles.
* Modern:
* "mw_contentwrapper" (top nav), outer div class "portlet", inner div class "pBody". Existing portlets or elements: "p-cactions", "mw_content"
* "mw_portlets" (sidebar), outer div class "portlet", inner div class "pBody". Existing portlets: "p-navigation", "p-search", "p-interaction", "p-tb", "p-coll-print_export"
*
* @param String navigation -- id of the target navigation area (skin dependant, on vector either of "left-navigation", "right-navigation", or "mw-panel")
* @param String id -- id of the portlet menu to create, preferably start with "p-".
* @param String text -- name of the portlet menu to create. Visibility depends on the class used.
* @param String type -- type of portlet. Currently only used for the vector non-sidebar portlets, pass "menu" to make this portlet a drop down menu.
* @param Node nextnodeid -- the id of the node before which the new item should be added, should be another item in the same list, or undefined to place it at the end.
*
* @return Node -- the DOM node of the new item (a DIV element) or null
*/
function twgAddPortlet( navigation, id, text, type, nextnodeid )
{
//sanity checks, and get required DOM nodes
var root = document.getElementById( navigation );
if ( !root ) {
return null;
}
var item = document.getElementById( id );
if (item) {
if (item.parentNode && item.parentNode === root) {
return item;
}
return null;
}
var nextnode;
if (nextnodeid) {
nextnode = document.getElementById(nextnodeid);
}
//verify/normalize input
type = (skin === "vector" && type === "menu" && (navigation === "left-navigation" || navigation === "right-navigation")) ? "menu" : "";
var outerDivClass;
var innerDivClass;
switch (skin)
{
case "vector":
if (navigation !== "portal" && navigation !== "left-navigation" && navigation !== "right-navigation") {
navigation = "mw-panel";
}
outerDivClass = (navigation === "mw-panel") ? "portal" : (type === "menu" ? "vectorMenu extraMenu" : "vectorTabs extraMenu");
innerDivClass = (navigation === "mw-panel") ? 'body' : (type === 'menu' ? 'menu':'');
break;
case "modern":
if (navigation !== "mw_portlets" && navigation !== "mw_contentwrapper") {
navigation = "mw_portlets";
}
outerDivClass = "portlet";
innerDivClass = "pBody";
break;
default:
navigation = "column-one";
outerDivClass = "portlet";
innerDivClass = "pBody";
break;
}
//Build the DOM elements.
var outerDiv = document.createElement( 'div' );
outerDiv.className = outerDivClass+" emptyPortlet";
outerDiv.id = id;
if (type === "menu") {
// fix drop-down arrow image in Vector skin
outerDiv.style.backgroundImage = 'url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABYAAAAQCAMAAAAlM38UAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAA9QTFRFsbGxmpqa3d3deXl58/n79CzHcQAAAAV0Uk5T/////wD7tg5TAAAAMklEQVR42mJgwQoYBkqYiZEZAhiZUFRDxWGicEPA4nBRhNlAcYQokpVMDEwD6kuAAAMAyGMFQVv5ldcAAAAASUVORK5CYII=")';
outerDiv.style.backgroundPosition = 'right 60%';
}
if ( nextnode && nextnode.parentNode === root ) {
root.insertBefore( outerDiv, nextnode );
} else {
root.appendChild( outerDiv );
}
var h5 = document.createElement( 'h3' );
if (type === 'menu') {
var span = document.createElement( 'span' );
span.appendChild( document.createTextNode( text ) );
h5.appendChild( span );
var a = document.createElement( 'a' );
a.href = "#";
span = document.createElement( 'span' );
span.appendChild( document.createTextNode( text ) );
a.appendChild( span );
h5.appendChild( a );
} else {
h5.appendChild( document.createTextNode( text ) );
}
outerDiv.appendChild( h5 );
var innerDiv = document.createElement( 'div' ); //not strictly necessary with type vectorTabs, or other skins.
innerDiv.className = innerDivClass;
outerDiv.appendChild(innerDiv);
var ul = document.createElement( 'ul' );
innerDiv.appendChild( ul );
return outerDiv;
}
/**
* **************** twAddPortletLink() ****************
* Builds a portlet menu if it doesn't exist yet, and add the portlet link.
* @param task: Either a URL for the portlet link or a function to execute.
*/
function twgAddPortletLink( task, text, id, tooltip )
{
var link = mw.util.addPortletLink( 'p-TWG', typeof task === "string" ? task : "#", text, id, tooltip );
if (jQuery.isFunction(task)) jQuery(link).click(function(ev){ task(); ev.preventDefault(); });
return link;
}
/*Here begins the common tagger code. This can be importscript()ed from anywhere and should work as long as the module messages are already defined before it.*/
TWG.tagger = {};
/*namespace is a number containing the namespace number to be tested.
Function returns true or false depending on whether or not its the current namespace.
Function's output will be used to decide whether to add the mod to the menu or not.*/
/*TWG.tagger.nsselect = function namespaceselector(namespace) {
var flag = 0;
$.each(namespace, function (k,v) {
if((mw.config.get('wgNamespaceNumber')) === v) {
flag++;
return false;
}
});
return false;
};
*/
/*creates the tab
*/
TWG.tagger.tab = function createtab(i) {
if(TWG.messages[i].namespace.indexOf(mw.config.get('wgNamespaceNumber'))!==-1) {
twgAddPortletLink( function(){ TWG.tagger.createform(TWG.messages[i]); }, TWG.messages[i].name, 'p-'+TWG.messages[i].name, TWG.messages[i].altname );
}
};
/*Loads the commonsets*/
TWG.tagger.loadcommonsets = function loadcommonsets(settype, mod, form) {
if (mod.commonsets !== undefined && mod.commonsets !== null && mod.commonsets !== []) {
$.each(mod.commonsets, function (k,v) {
if (v.type === settype) {
$.each(TWG.messages.commonsets[v.name], function(key, val) {
form.append(val);
});
}
});
}
};
/* Creates the form and renders it.
*/
//Fix this to call another function to edit another page with fixed input params.
TWG.tagger.createform = function createform(mod) {
TWG.thismod = mod;
var Window = new Morebits.simpleWindow(mod.size.width, mod.size.height);
Window.setScriptName( TWG.messages.scriptname );
Window.addFooterLink( mod.footer.text, mod.footer.link );
Window.setTitle( mod.title );
var i, form = (mod.submit) ? new Morebits.quickForm( TWG.tagger.evaluate ) : new Morebits.quickForm( TWG.tagger.evaluate, 'change' );
TWG.tagger.loadcommonsets('pre', mod, form);
$.each(mod.templates, function (k,v) {
form.append(v);
});
TWG.tagger.loadcommonsets('post', mod, form);
if (mod.submit) {
form.append( { type:'submit' } );
}
var result = form.render();
Window.setContent( result );
Window.display();
};
/*Does the actual work
Callback accepts the parameter input as an object with various properties representing various templates. The name property of the various properties is the templatename used, the other property names are the parameter names and their values are parameter values.
E.g:
{type:'append/prepend/replace',wrap:'',summary:'',text:'',tags:{{name:merge, 1:whateverpagename},{name:cleanup, reason:whateverreason}}}
*/
TWG.tagger.callback = function callback(pageobj, page) {
var mod = TWG.thismod;
var statelem, params, text;
if (typeof pageobj.type === 'string') {
statelem = page.getStatusElement();
params = pageobj;
}
else {
statelem = pageobj.getStatusElement();
text = pageobj.getPageText();
params = pageobj.getCallbackParameters();
}
var code = '';
$.each(params.tags, function (k,v) {
code+= '{{' + v.name;
$.each(v, function (key, val) {
if (key !== 'name') {
code+= '|' + key + '=' + val;
}
});
code+= '}}\n';
});
if (params.wrap !== null && params.wrap !== undefined) {
code = '<' + params.wrap + '>\n' + code + '</' + params.wrap + '>';
}
if (params.text !== undefined) {
if (params.text[0] === 'PRE' || params.text[0] === 'POST') {
code = params.text[0] === 'PRE' ? params.text[1] + '\n' + code : code + '\n' + params.text[1];
}
}
switch (params.type) {
case 'prepend':
page.setPrependText(code);
page.setEditSummary(params.summary);
page.prepend();
break;
case 'append':
page.setAppendText(code);
page.setEditSummary(params.summary);
page.append();
break;
case 'replace':
text = code;
pageobj.setPageText(text);
pageobj.setEditSummary(params.summary);
pageobj.save();
break;
default:
statelem.error(TWG.messages.typeerror);
return;
}
};
/*Function to evaluate params for altpages, and give an output object to be passed to callback.*/
TWG.tagger.alteval = function alteval (params, i, mod) {
var output = {};
output.tags = {};
var thispage = mw.config.get('wgPageName');
$.each(params.tags, function(j, val) {
if (typeof mod.page.alt[i][val.name] === 'object') {
output.tags[j] = {};
output.tags[j].name = mod.page.alt[i][val.name].NAME;
$.each(mod.page.alt[i][val.name], function(p, q) {
if (p!== 'NAME') {
if (q === 'THISPAGE') {
output.tags[j][p] = thispage;
}
else {
$.each(params.tags[j], function(x,y) {
if (q === x) {
output.tags[j][p] = y;
}
});
}
if (output.tags[j][p] === null || output.tags[j][p] === undefined) {
output.tags[j][p] = q;
}
}
});
}
});
return output;
};
/*Recursive function to analyze all templates and their parameters and return an object acceptable to callback.*/
TWG.tagger.evaluateinput = function evaluate(i, e, parent) {
var flag, m1, m2, outsub, param, outreg, subreg;
var form = e.target;
var input = form[i];
var output = {};
var l1 = (input.name.match(/IGNORE/g) === null) ? 0 : input.name.match(/IGNORE/g).length;
var l2 = (parent.match(/IGNORE/g) === null) ? 0 : parent.match(/IGNORE/g).length;
if (input.name.match(/PLAINTEXT/) !== null) {
output = [];
output[0] = input.name.match(/PRE/) !== null ? 'PRE' : 'POST';
output[1] = input.value;
return output;
}
if (l1 === l2) {
if (parent.replace(/(\.|IGNORE)/g,'') === '') {
if (input.name.match(/COMMONPARAM/) !== null) {
if (input.value !== null && input.value !== undefined && input.value !== '') {
param = input.name.replace(/COMMONPARAM/,'');
output[param] = input.value;
}
}
else {
output.name = input.value;
}
}
else if (input.value !== null && input.value !== undefined && input.value !== '') {
param = input.name;
outreg = new RegExp(parent, 'g');
param = param.replace(outreg,'');
param = param.replace(/\./g,'');
output[param] = input.value;
}
}
subreg = new RegExp(input.name);
$(form).find('input, textarea, select').each(function(k, v) {
if (v !== null && v.type !== undefined) {
if ((v.type === 'checkbox' && v.checked) || (v.type === 'radio' && v.checked) || v.type.match(/select/) !== null || v.type === 'text' || v.type === 'textarea') {
if (v.name.match(subreg) !== null) {
m1 = (v.name.match(/\./g) === null) ? [] : v.name.match(/\./g);
m2 = (input.name.match(/\./g) === null) ? [] : input.name.match(/\./g);
if (m1.length - m2.length === 1) {
outsub = TWG.tagger.evaluateinput(k, e, input.name);
}
}
else if (v.name.match(/COMMONPARAM/) !== null) {
outsub = TWG.tagger.evaluateinput(k, e, '');
}
$.extend(true, output, outsub);
}
}
});
return output;
};
/*Evaluates the input form subgroup elements of a particular element and returns an object of them.*/
//Fix this to evaluate checkbox and radio subgroups.
/*
TWG.tagger.subgroupevaluate = function subgroupevaluate(i, e) {
var form = e.target;
var flag, flagfixed;
var ir = new RegExp(form[i].name,'g');
var output = {};
for (flag in form) {
if (form[flag] !== null) {
if ((form[flag].type === 'checkbox' && form[flag].checked) || form[flag].type === 'radio' || form[flag].type === 'select' || form[flag].type === 'text') {
if (form[flag].name.match(/subgroup/gi) !== null && form[flag].name.match(ir) !== null) {
flagfixed = form[flag].name.replace(/(subgroup|\.)/gi,'');
flagfixed = flagfixed.replace(ir,'');
output[flagfixed] = $.extend(true, {}, form[flag]);
}
}
}
}
return output;
};
*/
/*Calculates the params per the form, load()s the page and calls callback
*/
TWG.tagger.evaluate = function evaluateform(e) {
var mod = TWG.thismod;
var form = e.target;
var page, pagename, subs, thispagename, thispage, altpage, altpagename, creatortalk, creatorname, redirect, namespaces, altparams;
var params = {};
thispagename = mw.config.get('wgPageName');
thispage = new Morebits.wiki.page(thispagename);
thispage.lookupCreator();
namespaces = mw.config.get('wgFormattedNamespaces');
//set all params here
params.type = mod.page.main.type;
params.wrap = mod.page.main.wrap;
params.summary = mod.page.main.summary;
params.tags = {};
//evaluate inputs
$(form).find('input, textarea, select').each(function(k, v) {
if (v !== null && v.type !== undefined) {
if ((v.type === 'checkbox' && v.checked) || (v.type === 'radio' && v.checked) || v.type.match(/select/) !== null || v.type === 'text' || v.type === 'textarea') {
if (v.name.match(/(\.|COMMONPARAM)/) === null) {
subs = TWG.tagger.evaluateinput(k, e, ''); //this evaluates all inputs and returns an object appropriate for callback.
if (subs[0] === 'PRE' || subs[0] === 'POST') {
params.text = $.extend(true, [], subs);
}
else {
params.tags[k] = $.extend({}, subs);
}
}
}
}
});
creatorname = thispage.getCreator();
creatortalk = namespaces['3'] + ':' + creatorname;
pagename = mod.page.main.name.replace(/THISPAGE/g, thispagename);
pagename.replace(/CREATORTALK/g, creatortalk);
Morebits.simpleWindow.setButtonsEnabled( false );
Morebits.status.init( e.target );
redirect = mod.redirect.replace(/THISPAGE/g, thispage);
redirect.replace(/CREATORTALK/g, creatortalk);
Morebits.wiki.actionCompleted.redirect = redirect;
Morebits.wiki.actionCompleted.notice = mod.completed;
page = new Morebits.wiki.page(pagename, mod.start);
switch (mod.page.main.type) {
case 'prepend':
case 'append':
TWG.tagger.callback(params, page);
break;
default:
page.setCallbackParameters(params);
page.load(TWG.tagger.callback);
break;
}
$.each(mod.page.alt, function(k, v) {
altpagename = v.name.replace(/THISPAGE/g, thispage);
altpagename.replace(/CREATORTALK/g, creatortalk);
altpage = new Morebits.wiki.page(altpagename);
altparams = TWG.tagger.alteval(params, k, mod);
altparams.type = v.type;
altparams.wrap = v.wrap;
altparams.summary = v.summary;
switch (v.type) {
case 'prepend':
case 'append':
TWG.tagger.callback(altparams, altpage);
break;
default:
altpage.setCallbackParameters(altparams);
altpage.load(TWG.tagger.callback);
break;
}
});
};
/*General initialization code. Initializes all modules one by one. */
$(document).ready(function initialize() {
twgAddPortlet('right-navigation', 'p-TWG', 'TWG', 'menu', 'p-search');
$.each(TWG.mods, function (k,v) {
TWG.tagger.tab(v);
});
});
} ( window, document, jQuery, window.TWG )); // End wrap with anonymous function