User:SMcCandlish/common.js/sandbox

// Highlight admin names – style tweaked in common.css // It's sad that we'd need to do this, but too many admins violate WP:INVOLVED. importScript('User:Theopolisme/Scripts/adminhighlighter.js');

// Cleanup links to disambiguation pages (run it at the DAB page in question) importScript('User:Qwertyytrewqqwerty/DisamAssist.js'); // Backlink: User:Qwertyytrewqqwerty/DisamAssist.js

// Selectively roll back all of a vandal's edits importScript('User:Writ Keeper/Scripts/massRollback.js');

// Get slightly more informative details about WikiData in watchlist entries: importScript('User:Evad37/WikidataWatchlistLabels.js'); // User:Evad37/WikidataWatchlistLabels

// do some markup to edits by blocked users var markblocked_contributions = 'Special:Contributions'; mw.loader.load('//en.wikipedia.org/w/index.php?title=MediaWiki:Gadget-markblocked.js&bcache=1&maxage=259200&action=raw&ctype=text/javascript');

// remove ugly styles from buttons: $(".oo-ui-buttonInputWidget").removeClass("oo-ui-buttonInputWidget"); $(".oo-ui-buttonElement-button").removeClass("oo-ui-buttonElement-button"); // and checkboxes: $(".oo-ui-checkboxInputWidget").removeClass("oo-ui-checkboxInputWidget"); // remove inflated field margins: $(".oo-ui-fieldLayout-header").removeClass("oo-ui-fieldLayout-header");

//Automatically tick the "Move subpages" option when moving pages. var moveSubpagesBox = document.getElementsByName("wpMovesubpages")[0]; if (null !== moveSubpagesBox) { moveSubpagesBox.checked = true; } // MoveToDraft tool, for unsourced but potentially salvageable articles var m2d_portlet = "p-personal"; importScript( 'User:Evad37/MoveToDraft.js' ); // Backlink: User:Evad37/MoveToDraft

// Add WP:Reflinks launcher in the toolbox on left $.when( mw.loader.using( ['mediawiki.util'] ), $.ready ).then(function { mw.util.addPortletLink( "p-tb",    // toolbox portlet "http://dispenser.homenet.org/~dispenser/cgi-bin/webreflinks.py/" + mw.config.get('wgPageName') + "?client=script&citeweb=on&overwrite=&limit=20&lang=" + mw.config.get('wgContentLanguage'), "Reflinks" // link label )});

// Add a portlet to open user subpages to the personal toolbar, placed before the Preferences portlet: mw.util.addPortletLink( 'p-personal', '/wiki/Special:PrefixIndex/User:SMcCandlish', 'subpages', 'pt-subpages', 'Your subpages', null, '#pt-preferences' );

// Install WP:AutoEd tools in "More" menu: importScript('Wikipedia:AutoEd/complete.js'); // That didn't work; my "More" menu is empty due to another gadget/script moving stuff around to a new Page menu.

// Add link to watchlist template's /doc files: importScript('User:Frietjes/watchdoc.js');

// Add to Contributions page's tabs a hide/show feature for pages of which the user is the top contributor. Useful for weeding out user's own user page and talk, essays, drafts, etc. importScript('User:Markhurd/hidetopcontrib.js'); // // Inserts WikiWidgets in the articles with the Template:WikiWidget // WikiWidgets serve to illustrate and explain interactively the concepts treated within articles // THIS CAN BE REMOVED AFTER ADDED TO Mediawiki:common.js var WikiWidgetLogo = $( ' ' ).attr({	'class': 'WikiWidgetLogo',	'title': 'Click to load the WikiWidget',	'src': 'https://upload.wikimedia.org/wikipedia/commons/thumb/5/57/WikiWidget_Logo.svg/200px-WikiWidget_Logo.svg.png', });

WikiWidgetLogo.click( function ( event ) {	var wikiwidget = $( event.target ).parent.data( 'wikiwidget' );	importScript( 'MediaWiki:WikiWidget-' + wikiwidget + '.js' );	importStylesheet( 'MediaWiki:WikiWidget-' + wikiwidget + '.css' ); });

$( '.WikiWidget' ).html( WikiWidgetLogo ); // More-readable diffs, from de:Benutzer:TMg/cleanDiff.js ( function( $, mw ) {	// Quit as fast as possible if there is nothing to do. Doesn't use jQuery for performance reasons	if ( !document.getElementsByClassName ) {		return;	}

var action = mw.config.get( 'wgAction' ), live = mw.user.options.get( 'uselivepreview' ) && ( action == 'edit' || action == 'submit' ); if ( !live && !document.getElementsByClassName( 'diff' ).length ) { return; }

// Borders around single characters and sequences of whitespace, punctuation and other non-letters var wsRegex = /[\wÀ-ÖØ-öø-\u02AF\u0370-\u1FFE\u2C00-\uFEFC]/, wsClass = 'diffchange-extra'; if ( mw.user.options.get( 'gadget-old-diff-style' ) ) { mw.util.addCSS(			'td.diff-deletedline .diffchange.' + wsClass + ','				+ 'td.diff-addedline .diffchange.' + wsClass				+ '{ background: rgba(255, 0, 0, .1); border: 1px solid red;'				+ 'border-color: rgba(255, 0, 0, .5); border-radius: 2px; padding: 0 1px; }'		); } else { mw.util.addCSS(			'.' + wsClass + '{ border: 0 solid #FFD366; border-width: 0 2px; }'				+ '.diff-addedline .' + wsClass + ' { border-color: #99CFFF; }'		); }

if ( live ) { $( mw ).on( 'LivePreviewDone', cleanDiff ); }	cleanDiff;

function cleanDiff { var diffs = document.getElementsByClassName( 'diff' ); if ( !diffs || !diffs.length ) { return; }

var lines = diffs[0].getElementsByTagName( 'TR' ); if ( !lines || lines.length < 3 ) { return; }

cleanDisconnectedLines( lines ); cleanChangedLines( lines ); createLinks( lines ); }

function cleanDisconnectedLines( lines ) { var moveUps = [], moveDowns = [], lastDels = [];

// Warning, don't pre-calculate the length. It changes due to deleted nodes for ( var i = 0; i < lines.length; i++ ) { var tr = lines[i], tds, dels = tr.getElementsByClassName( 'diff-deletedline' ), adds = tr.getElementsByClassName( 'diff-addedline' ), emps = tr.getElementsByClassName( 'diff-empty' ), isDel = dels.length == 1 && !adds.length && emps.length == 1, isAdd = !dels.length && adds.length == 1 && emps.length == 1, isChange = dels.length == 1 && adds.length == 1 && !emps.length;

// Sonderfall, wenn angeblich eine Leerzeile durch eine gefüllte ersetzt //  und danach eine gefüllte Zeile gelöscht wurde if ( moveUps.length > 0 && isDel && dels[0].firstChild ) { // Markierung der Löschung nachholen, die Ersetzung ist schon markiert markAllChanged( dels[0] ); var moveUp = moveUps.shift ; tds = moveUp.getElementsByTagName( 'TD' ); tr.appendChild( tds[2] ); tr.appendChild( tds[2] ); moveUp.appendChild( emps[0] ); continue; } else if ( isChange && dels[0].firstChild.nodeType == 1 && !dels[0].firstChild.firstChild ) { // Angebliche Änderungen sammeln, wenn die linke Seite leer ist moveUps.push( tr ); } else if ( !isDel ) { moveUps = []; }

// Sonderfall, wenn angeblich eine gefüllte durch eine Leerzeile ersetzt // und danach eine gefüllte Zeile eingefügt wurde if ( moveDowns.length > 0 && isAdd && adds[0].firstChild ) { // Markierung der Einfügung nachholen, die Ersetzung ist schon markiert markAllChanged( adds[0] ); var moveDown = moveDowns.shift; tds = moveDown.getElementsByTagName( 'TD' ); tr.insertBefore( tds[1], tr.firstChild ); tr.insertBefore( tds[0], tr.firstChild ); moveDown.insertBefore( emps[0], moveDown.firstChild ); continue; } else if ( isChange && adds[0].firstChild.nodeType == 1 && !adds[0].firstChild.firstChild ) { // Angebliche Änderungen sammeln, wenn die rechte Seite leer ist moveDowns.push( tr ); } else if ( !isAdd ) { moveDowns = []; }

var cons = tr.getElementsByClassName( 'diff-context' ); // Einfügungen sowie leere Kontextzeilen nach oben schieben, // wenn zuvor passende Löschungen gefunden wurden if ( lastDels.length > 0 && ( isAdd || ( cons.length == 2 && !cons[0].firstChild && !cons[1].firstChild ) ) ) { var lastDel = lastDels.shift;

// Leere rechte Seite der Löschung wegwerfen tds = lastDel.getElementsByTagName( 'TD' ); while ( tds.length > 2 ) { lastDel.removeChild( tds[2] ); }

tds = tr.getElementsByTagName( 'TD' ); if ( tds.length == 4 ) { // Die beiden Hälften der Kontextzeile als Löschung und Einfügung markieren tds[0].firstChild.data = '−'; tds[1].className = 'diff-deletedline'; tds[2].firstChild.data = '+'; tds[3].className = 'diff-addedline'; // Rechte Hälfte der Kontextzeile nach oben zur vorher gefundenen Löschung schieben lastDel.appendChild( tds[2] ); lastDel.appendChild( tds[2] ); // Die unten verbliebene linke Hälfte der Kontextzeile vervollständigen var td = document.createElement( 'TD' ); td.colSpan = 2; td.className = 'diff-empty'; tr.appendChild( td ); } else { // Einfügung nach oben zur Löschung schieben lastDel.appendChild( tds[1] ); lastDel.appendChild( tds[1] ); // Leeren Rest der Einfügung wegwerfen tr.parentNode.removeChild( tr ); // Korrektur, weil die iterierte NodeList soeben ihre Länge verändert hat i--; }				markAllChanged( lastDel ); } else if ( isDel ) { lastDels.push( tr ); } else { lastDels = []; }		}	}

function markAllChanged( e ) { // Alles als Änderung markieren. Schrumpfung der Markierung passiert losgelöst davon sowieso noch var divs = e.getElementsByTagName( 'DIV' ); for ( var i = divs.length; i--; ) { var div = divs[i]; if ( div.getElementsByTagName( 'SPAN' ).length > 0 ) { continue; }

var span = document.createElement( 'SPAN' ); span.className = 'diffchange diffchange-inline'; span.appendChild( div.firstChild ); div.appendChild( span ); }	}

function cleanChangedLines( lines ) { for ( var i = 0, length = lines.length; i < length; i++ ) { var del = lines[i].getElementsByClassName( 'diff-deletedline' ), add = lines[i].getElementsByClassName( 'diff-addedline' );

if ( del && add && del.length > 0 && add.length > 0 ) { var dels = del[0].getElementsByClassName( 'diffchange' ), adds = add[0].getElementsByClassName( 'diffchange' ); // Vor der Fehlerbehebung vom 20. Januar 2012 wurden solche // Phantom-Änderungen durch Leerzeichen am Zeilenende ausgelöst. if ( !dels.length && !adds.length ) { cleanChangedLineEnding( del[0], add[0] ); } else { cleanChangedLine( dels, adds ); }				cleanWhitespaceChanges( dels ); cleanWhitespaceChanges( adds ); }		}	}

function cleanChangedLine( dels, adds ) { var l1 = Math.min( dels.length, adds.length ), l2 = l1 + 1;

for ( var i = 0; i < l1; i++ ) { if ( cleanChange( dels[i], adds[i] ) ) { l2 = l1 - i;			} }		// Zweite Suche nach zueinander passenden Änderungen vom Zeilenende for ( i = 1; i < l2; i++ ) { cleanChange( dels[dels.length - i], adds[adds.length - i] ); }	}

function cleanChange( d, a ) { var p1 = 0, p2 = 0, t1, t2, l;

// Keine Optimierung, wenn sich der Text davor/dahinter geändert hat, dann ist es eine Verschiebung if ( d.previousSibling && d.previousSibling.nodeType == 3 && a.previousSibling && a.previousSibling.nodeType == 3 ) { t1 = d.previousSibling.data; t2 = a.previousSibling.data; l = Math.min( t1.length, t2.length ); if ( t1.slice( t1.length - l ) != t2.slice( t2.length - l ) ) { return false; }		}		if ( d.nextSibling && d.nextSibling.nodeType == 3 && a.nextSibling && a.nextSibling.nodeType == 3 ) { t1 = d.nextSibling.data; t2 = a.nextSibling.data; l = Math.min( t1.length, t2.length ); if ( t1.slice( 0, l ) != t2.slice( 0, l ) ) { return false; }		}

t1 = d.firstChild.data; t2 = a.firstChild.data; // Keine Optimierung versuchen, wenn beides gleich ist und nichts mehr übrig bleiben würde if ( t1 == t2 ) { return true; }

l = Math.min( t1.length, t2.length ); while ( p1 < l && t1.charAt( p1 ) == t2.charAt( p1 ) ) { p1++; }		l -= p1; while ( p2 < l && t1.charAt( t1.length - 1 - p2 ) == t2.charAt( t2.length - 1 - p2 ) ) { p2++; }		// Vorzeitig abbrechen, wenn keine Übereinstimmung gefunden wurde if ( !p1 && !p2 ) { return false; }

if ( p1 > 0 ) { d.parentNode.insertBefore( document.createTextNode( t1.substr( 0, p1 ) ), d ); a.parentNode.insertBefore( document.createTextNode( t2.substr( 0, p1 ) ), a ); }		if ( p2 > 0 ) { d.parentNode.insertBefore( document.createTextNode( t1.substr( t1.length - p2 ) ), d.nextSibling ); a.parentNode.insertBefore( document.createTextNode( t2.substr( t2.length - p2 ) ), a.nextSibling ); }		d.firstChild.data = t1.substring( p1, t1.length - p2 ); a.firstChild.data = t2.substring( p1, t2.length - p2 ); return true; }

function cleanWhitespaceChanges( a ) { for ( var i = 0, length = a.length; i < length; i++ ) { if ( a[i].firstChild.data.length < 2 || !wsRegex.test( a[i].firstChild.data ) ) { a[i].className += ' ' + wsClass; }		}	}

function cleanChangedLineEnding( del, add ) { while ( del && del.nodeType == 1 ) { del = del.lastChild; }		while ( add && add.nodeType == 1 ) { add = add.lastChild; }		if ( !del || !add || del.nodeType != 3 || add.nodeType != 3 || del.data == add.data ) { return; }

var p = 0, t1 = del.data, t2 = add.data, l = Math.min( t1.length, t2.length ); while ( p < l && t1.charAt( p ) == t2.charAt( p ) ) { p++; }		if ( p > 0 ) { del.data = t1.substr( 0, p ); add.data = t2.substr( 0, p ); var span = document.createElement( 'SPAN' ); span.className = 'diffchange diffchange-inline ' + wsClass; span.appendChild( document.createTextNode( t1.substr( p ).replace( / /g, '\xA0' ) ) ); if ( span.firstChild.data.length > 0 ) { del.parentNode.appendChild( span ); }			span = span.cloneNode( true ); span.firstChild.data = t2.substr( p ).replace( / /g, '\xA0' ); if ( span.firstChild.data.length > 0 ) { add.parentNode.appendChild( span ); }		}	}

function createLinks( lines ) { // Off by default because of a Firefox bug var limit = typeof window.cleanDiffLinkLimit !== 'undefined' ? window.cleanDiffLinkLimit : -1; if ( lines.length > limit ) { return; }

for ( var i = lines.length; --i; ) { $( 'DIV', lines[i] ).html( function( i, html ) {				return html.replace( /<[^>]*|(\[\[(?:<\/span>)?)((?:[:\w\xC0-\uD7FF]|]*>[:\w\xC0-\uD7FF][^&<=>[\]{|}]*<\/span>)(?:[^&<=>[\]{|}]+|]*>[^&<=>[\]{|}]*<\/span>)*)(?=(?:]*>)?[\]|])/g, function( $0, $1, $2 ) { return $2 ? $1 + ']*>*/g, '' ) )							+ '">' + $2 + '<\/a>' : $0;					} );			} );		}	} } )( jQuery, mediaWiki );