MediaWiki:Gadget-AGprefs.js

/** per-browser preferences page **/

/*jshint undef:true, boss:true, latedef:true, shadow:true */ /*global mw, jQuery, OO */

'use strict';

var gadgetList = { '': {} }; var prefs; try { prefs = window.localStorage.getItem('AGprefs'); } catch (e) { prefs = jQuery.cookie('AGprefs'); } prefs = prefs ? JSON.parse(prefs) : { gadgets: {}, modules: {}, sheets: {}, scripts: {} };

var uiContent = document.getElementById('mw-content-text');

var api = new mw.Api; api.get({	action: 'query',	titles: 'MediaWiki:Gadgets-definition',	prop: 'revisions',	rvprop: 'content',	rvlimit: 1 }).then(function (result) {	var m, mm, wikitext;	for (var pageid in result.query.pages) {		wikitext = result.query.pages[pageid].revisions[0]['*'];	}	var lines = wikitext.split('\n'), msgQueue = {}, curGroup = '';	for (var i = 0; i < lines.length; ++i) {		if (m = /^==\s*(.*?)\s*==$/.exec(lines[i])) {			msgQueue['Gadget-section-' + m[1]] = true;			gadgetList[curGroup = m[1]] = {};		} else if (m = /^\*\s*([A-Za-z][A-Za-z0-9_\-]*)\s*(?:\[(.*?)\])?\|(.*)\s*$/.exec(lines[i])) {			msgQueue['Gadget-' + m[1]] = true;			var gadget = gadgetList[curGroup][m[1]] = {				options: {},				css: [],				js: []			};

if (m[2]) { var opts = m[2].split('|'); for (var j = 0; j < opts.length; ++j) { if (mm = /^(.*)=(.*)$/.exec(opts[j])) gadget.options[mm[1]] = mm[2]; else gadget.options[opts[j]] = true; }			}			var files = m[3].split('|'); for (var j = 0; j < files.length; ++j) { if (/\.css$/.test(files[j])) gadget.css.push(files[j]); else gadget.js.push(files[j]); }		}	}

var validGadgets = {}, validModules = {}, validJS = {}, validCSS = {}; for (var group in gadgetList) { for (var name in gadgetList[group]) { var gadget = gadgetList[group][name]; validGadgets[name] = true; if (gadget.options.ResourceLoader || (gadget.js.length === 0)) { validModules['ext.gadget.' + name] = true; } else { for (var i = 0; i < gadget.css.length; ++i) validJS[gadget.css[i]] = true; for (var i = 0; i < gadget.js.length; ++i) validCSS[gadget.js[i]] = true; }		}	}	for (var key in prefs.gadgets) if (!(key in validGadgets)) delete prefs.gadgets[key]; for (var key in prefs.modules) if (!(key in validModules)) delete prefs.modules[key]; for (var key in prefs.sheets) if (!(key in validCSS)) delete prefs.sheets[key]; for (var key in prefs.scripts) if (!(key in validJS)) delete prefs.scripts[key];

var msgs = {}; jQuery.Deferred(function (self) {		/*jshint loopfunc:true */		var promises = [], queue = Object.keys(msgQueue);		for (var i = 0; i < queue.length; i += 50) {			promises.push(api.get({				action: 'query',				meta: 'allmessages',				amenableparser: '1',				ammessages: queue.slice(i, i + 50).join("|")			}).then(function (result) {				for (var i = 0; i < result.query.allmessages.length; ++i) {					var mesg = result.query.allmessages[i];					if ('missing' in mesg)						msgs[mesg.name] = '&lt;' + mesg.name + '>';					else						msgs[mesg.name] = mesg['*'];				}			}));		}

jQuery.when.apply(jQuery, promises).then(function {			self.resolveWith(msgQueue);		}, function (data) {			self.rejectWith(data);		}); }).then(function (msgQueue) { function makeListItem(name, gadget) { var button = new OO.ui.CheckboxInputWidget({				selected: name in prefs.gadgets ? prefs.gadgets[name] : !!gadget.options['default']			}); button.on('change', function(e) {				var checked = button.isSelected;				prefs.gadgets[name] = checked;				if (gadget.options.ResourceLoader || (gadget.js.length === 0)) {					prefs.modules['ext.gadget.' + name] = checked;				} else {					for (var i = 0; i < gadget.css.length; ++i)						prefs.sheets[gadget.css[i]] = checked;					for (var i = 0; i < gadget.js.length; ++i)						prefs.scripts[gadget.js[i]] = checked;				}			}); var html = (msgs['Gadget-' + name] || ("&lt;Gadget-" + name + "&gt;")).replace(/\[\[(?:(.*?)\|)?(.*?)\]\]/g, function (whole, page, label) {				return ']/g, function (c) { return '&#' + c.charCodeAt(0) + ';'; }) + '">' + label + '';			});			var field = new OO.ui.FieldLayout( button, { label: jQuery(' ' + html + ' '), align: 'inline' } );			// styling fix			field.$element.children.css('max-width', 'none');			return field.$element[0];		}		var uiPrefs = document.createElement('div');

for (var group in gadgetList) { var uiHeader = document.createElement('h2'); var uiList = document.createElement('div'); uiHeader.textContent = msgs['Gadget-section-' + group]; for (var name in gadgetList[group]) { var gadget = gadgetList[group][name];

if ('rights' in gadget.options || gadget.options['hidden']) continue; // XXX: we just assume we do not have the necessary rights (or the gadget is hidden, don't show those)

if ('skins' in gadget.options) if (gadget.options.skins.split(',').indexOf(mw.config.get('skin')) === -1) continue;

var uiItem = makeListItem(name, gadget); uiList.appendChild(uiItem); }			if (uiList.hasChildNodes) { if (group !== '') uiPrefs.appendChild(uiHeader); uiPrefs.appendChild(uiList); }		}		var uiSave = new OO.ui.ButtonWidget({			label: 'Apply and reload',			flags: ['primary', 'progressive']		}); var uiReset = new OO.ui.ButtonWidget({			label: 'Reset to defaults',			flags: 'destructive'		}); uiSave.on('click', function {			var value = JSON.stringify(prefs);			try {				window.localStorage.setItem('AGprefs', value);			} catch (e) {				jQuery.cookie('AGprefs', value, { expire: 90 });			}			location.reload;		}); uiReset.on('click', function {			try {				window.localStorage.removeItem('AGprefs');			} catch (e) {				/* ignore */			}			jQuery.cookie('AGprefs', null);			location.reload;		});

var uiButtonContainer = document.createElement('div'); uiButtonContainer.style.marginTop = '1em'; uiButtonContainer.appendChild(uiSave.$element[0]); uiButtonContainer.appendChild(document.createTextNode(" ")); uiButtonContainer.appendChild(uiReset.$element[0]);

uiPrefs.appendChild(uiButtonContainer); uiContent.appendChild(uiPrefs); }, function { console.error('getting gadget names failed', arguments); }); }, function {	console.error('getting Gadgets-definition failed', arguments); });