User:BrandonXLF/sandbox.js

(function {	function loadScripts {		var requests = [null, null], // Force $.when to return arrays			enabledScripts = [],			js = '',			scripts = JSON.parse(mw.user.options.get('userjs-scriptmanager-scripts') || '[]'),			i;

for (i = 0; i < scripts.length; i++) { var script = scripts[i]; if (script.enabled && (script.conds ? eval(script.conds) : true) && script.name !== 'User:BrandonXLF/sandbox.js') { enabledScripts.push(script.name); js += script.vars + '\n'; }		}

for (i = 0; i < enabledScripts.length; i += 50) { requests.push(new mw.Api.get({ action: 'query', prop: 'revisions', titles: enabledScripts.slice(i, i + 50).join('|'), rvprop: 'content', rvslots: 'main', formatversion: 2 }));		}

$.when.apply(null, requests).then(function {			for (i = 2; i < arguments.length; i++) {				arguments[i][0].query.pages.forEach(function(page) { if (page.revisions) { js += '/* ' + page.title + ' */\n' + page.revisions[0].slots.main.content; } else { console.warn('Failed to load revision for script ' + page.title); }				});			}

var script = document.createElement('script'); script.text = js; document.head.appendChild(script); });	}

function manageScripts(e) { e.preventDefault;

function ScriptGroup(items) { ScriptGroup.super.call(this);

OO.ui.mixin.DraggableGroupElement.call(this, {				$group: this.$element,				items: items			}); }

OO.inheritClass(ScriptGroup, OO.ui.Widget); OO.mixinClass(ScriptGroup, OO.ui.mixin.DraggableGroupElement);

function ScriptWidget(data, dialog) { var widget = this;

ScriptWidget.super.call(this, {data: data}); OO.ui.mixin.IconElement.call(this, {icon: 'draggable'}); OO.ui.mixin.LabelElement.call(this, {label: data.name}); OO.ui.mixin.DraggableElement.call(this, {$handle: this.$icon});

this.toggle = new OO.ui.ButtonWidget({				framed: false,				label: widget.data.enabled ? 'Disable' : 'Enable'			});

this.toggle.on('click', function {				widget.data.enabled = !widget.data.enabled;				widget.toggle.setLabel(widget.data.enabled ? 'Disable' : 'Enable');				widget.$label.toggleClass('userscript-disabled', !widget.data.enabled);			});

this.remove = new OO.ui.ButtonWidget({				framed: false,				flags: 'destructive',				label: 'Remove'			});

this.remove.on('click', function {				widget.getElementGroup.removeItems([widget]);				dialog.updateSize;			});

this.$label.toggleClass('userscript-disabled', !this.data.enabled);

this.$element.append(				this.$icon,				this.$label,				new OO.ui.ButtonGroupWidget({ items: [this.toggle, this.remove] }).$element			);

this.$element.addClass('userscript-listing'); this.$label.addClass('userscript-label'); }

OO.inheritClass(ScriptWidget, OO.ui.Widget); OO.mixinClass(ScriptWidget, OO.ui.mixin.IconElement); OO.mixinClass(ScriptWidget, OO.ui.mixin.LabelElement); OO.mixinClass(ScriptWidget, OO.ui.mixin.DraggableElement);

function ManagerDialog(config) { ManagerDialog.super.call(this, config); }

OO.inheritClass(ManagerDialog, OO.ui.ProcessDialog);

ManagerDialog.static.name = 'manageuserscripts'; ManagerDialog.static.title = 'Manage user scripts'; ManagerDialog.static.actions = [ {				label: 'Close', flags: ['safe', 'close'], modes: ['list'] },			{				label: 'Save', flags: ['primary', 'progressive'], modes: ['list'], action: 'save' },			{				label: 'Add new script', flags: ['safe'], modes: ['list'], action: 'add' },			{				label: 'Import scripts', flags: ['safe'], modes: ['list'], action: 'import' },			{				label: 'Back', flags: ['safe', 'back'], modes: ['add'], action: 'add-back' },			{				label: 'Continue', flags: ['primary', 'progressive'], modes: ['add'], action: 'add-continue' },		];

ManagerDialog.prototype.initialize = function { ManagerDialog.super.prototype.initialize.apply(this, arguments);

var widgets = [], scripts = JSON.parse(mw.user.options.get('userjs-scriptmanager-scripts') || '[]');

for (var i = 0; i < scripts.length; i++) { widgets.push(new ScriptWidget(scripts[i], this)); }

this.listPanel = new OO.ui.PanelLayout({				padded: true,				expanded: false			}); this.addNewPanel = new OO.ui.PanelLayout({				padded: true,				expanded: false			}); this.group = new ScriptGroup(widgets); this.panels = new OO.ui.StackLayout; this.addNewInput = new OO.ui.TextInputWidget; this.addNewLayout = new OO.ui.FieldLayout(this.addNewInput, {				align: 'top',				label: 'Enter script title'			});

this.listPanel.$element.append(this.group.$element); this.addNewPanel.$element.append(this.addNewLayout.$element); this.panels.addItems([this.listPanel, this.addNewPanel]); this.$body.append(this.panels.$element); };

ManagerDialog.prototype.getSetupProcess = function(data) { return ManagerDialog.super.prototype.getSetupProcess.call(this, data).next(function {				this.panels.setItem(this.listPanel);				this.actions.setMode('list');			}, this); };

ManagerDialog.prototype.showErrors = function(errors) { ManagerDialog.super.prototype.showErrors.call(this, errors);

this.actions.setAbilities({				'add-continue': true			});

this.updateSize; };

ManagerDialog.prototype.showAddNewError = function(error) { this.addNewLayout.setErrors(error ? [error] : []); this.updateSize; };

ManagerDialog.prototype.getActionProcess = function(action) { var dialog = this;

return new OO.ui.Process(function {				if (!action) return dialog.close;

if (action == 'add') { dialog.panels.setItem(dialog.addNewPanel); dialog.actions.setMode('add'); dialog.addNewInput.setValue(''); dialog.showAddNewError; } else if (action == 'add-back') { dialog.panels.setItem(dialog.listPanel); dialog.actions.setMode('list'); } else if (action == 'add-continue') { var name = dialog.addNewInput.getValue;

if (!name) return dialog.showAddNewError('Name is required.');

return new mw.Api.get({						action: 'query',						titles: name,						prop: 'info',						formatversion: 2					}).then(function(res) {						var info = res.query.pages[0];						if (info.missing) return dialog.showAddNewError('Script does not exist.');						if (info.ns !== 2 && info.ns !== 8) return dialog.showAddNewError('Script must be in the User or MediaWiki namespaces.');						if (info.contentmodel !== 'javascript') return dialog.showAddNewError('Script must have the JavaScript content model.');

var items = dialog.group.getItems; for (var i = 0; i < items.length; i++) { if (items[i].getData.name == info.title) return dialog.showAddNewError('A script with the name is already added.'); }

dialog.showAddNewError; dialog.group.addItems([							new ScriptWidget({name: info.title, enabled: true}, dialog)						]); dialog.panels.setItem(dialog.listPanel); dialog.actions.setMode('list'); });				} else if (action == 'save') {					var items = dialog.group.getItems,						scripts = [];

for (var i = 0; i < items.length; i++) { scripts.push(items[i].getData); }

return new mw.Api.saveOption('userjs-scriptmanager-scripts', JSON.stringify(scripts)).then(function {						mw.user.options.set('userjs-scriptmanager-scripts', JSON.stringify(scripts));						dialog.close;					}); } else if (action == 'import') { var skins = ['common', 'monobook', 'minerva', 'vector', 'cologneblue', 'timeless'], skinScripts = [];

for (var i = 0; i < skins.length; i++) { skinScripts.push('User:' + mw.config.get('wgUserName') + '/' + skins[i] + '.js'); }

return new mw.Api.get({						action: 'query',						prop: 'revisions',						titles: skinScripts.join('|'),						rvprop: 'content',						rvslots: 'main',						formatversion: 2					}).then(function(res) {						for (var i = 0; i < res.query.pages.length; i++) {							var re = /(\/\/|)importScript\('(.*)'\)/g,								match,								page = res.query.pages[i];

if (!page.revisions) continue;

while (true) { match = re.exec(page.revisions[0].slots.main.content); if (!match) break;

// Normalize title var title = new mw.Title(match[2]).getPrefixedText, items = dialog.group.getItems, duplicate = false;

for (var j = 0; j < items.length; j++) { // Script is already added, skip if (items[j].getData.name == title) { duplicate = true; break; }								}

if (duplicate) continue;

dialog.group.addItems([new ScriptWidget({ name: title, enabled: !match[1] }, dialog)]); }						}					});				}			});		};

var windowManager = new OO.ui.WindowManager, dialog = new ManagerDialog({				size: 'large'			});

$(document.body).append(windowManager.$element); windowManager.addWindows([dialog]); windowManager.openWindow(dialog);

mw.loader.addStyleTag(			'.userscript-listing { display: block; position: relative; }' +			'.userscript-listing.oo-ui-iconElement { padding-left: 2.5em; }' +			'.userscript-listing.oo-ui-iconElement .oo-ui-iconElement-icon { position: absolute; left: 0.6em; }' +			'.userscript-listing > * { vertical-align: middle; }' +			'.userscript-disabled { text-decoration: line-through; }' +			'.userscript-label { margin-right: 1em; }'		); }

mw.loader.using('mediawiki.api').then(function {		loadScripts;	});

['', '-sticky-header'].forEach(suffix => {		var portletLink = mw.util.addPortletLink( 'p-personal' + suffix, '#',			'Scripts', 'scriptmanager', 'Manage user scripts', '',			'#pt-watchlist' + suffix );

if (portletLink) portletLink.addEventListener('click', manageScripts); }); });