User:John Vandenberg/delsort.js
// Wikipedia:WikiProject Deletion sorting
// This is a development version of Wikipedia:WikiProject Deletion sorting/delsort.js
if( typeof( DelsortConfig ) == 'undefined' ) {
DelsortConfig = function() {};
}
DelsortConfig.compactPage = 'Wikipedia:WikiProject_Deletion_sorting/Compact';
var Delsort = function() {};
// Used to emulate CSS columns in Opera
function add_opera_delsort_compact_css() {
if ( wgNamespaceNumber == 4 && wgPageName == DelsortConfig.compactPage ) {
if( navigator.userAgent.indexOf("Opera") != -1 ) {
importStylesheet('Wikipedia:WikiProject Deletion sorting/compact opera.css');
}
}
}
// adds 'delsort' tab to p-cactions
function add_delsort_tab()
{
if ( DelsortConfig['debugLevel'] > 0 ) {
Delsort.displayPopup( '', "Setting up buttons.." );
Status.init( window['delsortWindow'].content );
Delsort.debug ('Adding delsort button ...');
}
var tabs = document.getElementById('p-cactions').getElementsByTagName('ul')[0];
var ul = addlimenu(tabs, 'delsort', 'delsort');
if ( DelsortConfig['debugLevel'] > 0 ) Delsort.debug ('ul = ' + ul.tagName);
var menuitem = ul.previousSibling;
menuitem.setAttribute('href','javascript:showDelsortFrame()');
// when the user is in edit mode, save a reference to it
Delsort.afdForm = document.getElementById( 'editform' );
// support deprecated shortcut list
if ( window['delsortPages'] )
DelsortConfig.shortcuts = window['delsortPages'];
// add each shortcut
if ( DelsortConfig['shortcuts'] &&
DelsortConfig['shortcuts']['length'] ) {
for (i = 0; i < DelsortConfig.shortcuts.length; i++) {
if ( DelsortConfig['debugLevel'] > 0 ) Delsort.debug ('adding shortcut "' +
DelsortConfig.shortcuts[i] + '"');
mw.util.addPortletLink('delsort',
'javascript:delsortArticle("' + DelsortConfig.shortcuts[i] + '")',
DelsortConfig.shortcuts[i],
'');
}
}
if ( DelsortConfig['debugLevel'] > 0 ) {
Delsort.debug ('done');
}
}
Delsort.add_inline_ui = function() {
if ( DelsortConfig['debugLevel'] > 0 ) {
Delsort.displayPopup( '', "Setting up inline delsort buttons.." );
Status.init( window['delsortWindow'].content );
Delsort.debug ('Adding delsort to ...');
}
var spans = document.getElementsByTagName('SPAN');
for (i = 0; i < spans.length; i++) {
if (spans[i].className == 'editsection') {
// spans[i] is a section, which is usually the start of a transclude.
// It could be a section within the transcluded page
var sectionEditAnchor = spans[i].getElementsByTagName('A');
if ( sectionEditAnchor ) sectionEditAnchor = sectionEditAnchor[0];
Delsort.debug ('-- Found section "' + sectionEditAnchor.title + '"');
if ( sectionEditAnchor && /Wikipedia:Articles for deletion/.exec ( sectionEditAnchor.title ) ) {
window['wgAfdPage'] = sectionEditAnchor.title;
Delsort.debug ('Looking for more signs that "' + sectionEditAnchor.title + '" is an Afd...');
}
else {
window['wgAfdPage'] = '';
}
}
if (window['wgAfdPage'] && spans[i].className == 'mw-headline') {
// span[i] is the beginning of the transcluded Afd content
if ( window['wgAfdPage'].indexOf ( spans[i].textContent ) > -1 ) {
window['wgNominatedArticle'] = spans[i].textContent;
Delsort.debug (' ' + window['wgAfdPage'] + ': ' + window['wgNominatedArticle']);
parentNode = spans[i].parentNode;
var laNode = null;
// try looking for {{la|...}} directly after
if (parentNode.nextSibling.nodeValue == '\n' &&
parentNode.nextSibling.nextSibling.tagName == 'DL' ) {
// looks like we have found {{la|...}}
laNode = parentNode.nextSibling.nextSibling;
}
// try looking for {{la|...}} by skipping a "AfDs for this article" DIV
if (parentNode.nextSibling.nodeValue == '\n' &&
parentNode.nextSibling.nextSibling.tagName == 'DIV' &&
parentNode.nextSibling.nextSibling.nextSibling.nodeValue == '\n' &&
parentNode.nextSibling.nextSibling.nextSibling.nextSibling.tagName == 'DL' ) {
// looks like we have found {{la|...}}
laNode = parentNode.nextSibling.nextSibling.nextSibling.nextSibling;
}
if (laNode) {
if (laNode.childNodes[1].tagName == 'DD') {
var viewAfdNode = laNode.childNodes[1].lastChild.previousSibling;
if (viewAfdNode) {
if (viewAfdNode.textContent == 'View AfD' &&
viewAfdNode.previousSibling) {
viewAfdNode.previousSibling.nodeValue = ' — (Afd: ';
viewAfdNode.firstChild.nodeValue = 'View';
var delsortAfdNode = viewAfdNode.cloneNode(true);
delsortAfdNode.firstChild.nodeValue = 'Delsort';
delsortAfdNode.setAttribute('href', 'javascript:showDelsortFrame("' + wgAfdPage + '")');
delsortAfdNode = viewAfdNode.parentNode.insertBefore( delsortAfdNode, viewAfdNode.parentNode.lastChild );
viewAfdNode.parentNode.insertBefore( document.createTextNode ( ' | ' ), delsortAfdNode );
}
else {
var delsortAfdNode = document.createElement('A');
delsortAfdNode.setAttribute('href', 'javascript:showDelsortFrame("' + wgAfdPage + '")');
delsortAfdNode.innerHTML = 'Delsort';
laNode.appendChild ( document.createTextNode ( ' - ' ) );
laNode.appendChild ( delsortAfdNode );
}
}
}
}
else {
// Delsort.debug ('Skipping nomination "' + window['wgAfdPage'] + '"; expected preamble not present.');
var delsortAfdNode = document.createElement('A');
delsortAfdNode.setAttribute('href', 'javascript:showDelsortFrame("' + wgAfdPage + '")');
delsortAfdNode.innerHTML = 'Delsort';
parentNode.parentNode.insertBefore ( document.createTextNode ( ' - ' ), parentNode.nextSibling );
parentNode.parentNode.insertBefore ( delsortAfdNode , parentNode.nextSibling );
}
}
else {
Delsort.debug ('Skipping headline "' + spans[i].textContent + '"');
}
}
}
}
Delsort.status = function( text ) {
return new Status( text, 'Status', 'status' );
}
Delsort.info = function( text ) {
return new Status( text, 'Info', 'info' );
}
Delsort.warn = function( text ) {
return new Status( text, 'Warning', 'error' );
}
Delsort.error = function( text ) {
return new Status( text, 'Error', 'error' );
}
Delsort.progress = function( text ) {
// disable the "....." until I can work out how to
// achieve that again using the new TW framework
if ( text == '.' ) return;
return new Status( text, 'Progress', 'info' );
}
Delsort.debug = function( text ) {
if ( DelsortConfig['debugLevel'] > 0 ) {
return new Status( text, 'Debug', 'info' );
}
}
Delsort.init = function() {
add_opera_delsort_compact_css();
if ( typeof DelsortConfig.transcludeRE == 'undefined' )
DelsortConfig.transcludeRE = new RegExp('Wikipedia:Deletion today|Wikipedia:Articles for deletion\/Log\/');
if ( typeof ( WikiPage ) == 'function' ) {
// create wgWikiPage for the current page if it doesnt already exist
if (! window['wgWikiPage'] )
wgWikiPage = new WikiPage(null,wgPageName);
if ( DelsortConfig.transcludeRE.test ( wgWikiPage.page ) )
Delsort.add_inline_ui();
if ( wgWikiPage.superarticle == 'Articles for deletion' &&
wgWikiPage.subarticle.substr(0,3) != 'Log' ) {
window['wgAfdPage'] = wgPageName;
add_delsort_tab();
}
return;
}
if ( wgNamespaceNumber == 4 ) {
var subTitleRE = /^([^/]+)\/(.+)/;
if ( subTitleRE.exec ( wgTitle ) ) {
window['wgDirname'] = RegExp.$1;
window['wgSubTitle'] = RegExp.$2;
}
if (!window['wgDirname'] || !window['wgSubTitle'] || wgDirname != 'Articles for deletion') return;
window['wgAfdPage'] = wgPageName;
add_delsort_tab();
}
}
$(Delsort.init);
function showDelsortFrame(pAfdPage) {
if (pAfdPage)
window['wgAfdPage'] = pAfdPage;
// The frame contents are cached
if ( Delsort['PopupContents'] )
Delsort.displayPopup( Delsort.PopupContents, "Select deletion sorting criteria" );
else
Delsort.loadFrameContents();
}
Delsort.loadFrameContents = function () {
try {
delsortCompatList = sajax_init_object();
delsortCompatList.overrideMimeType('text/xml');
var query = {
'title': DelsortConfig.compactPage
};
delsortCompatList.onreadystatechange = showDelsortFrameCallback;
delsortCompatList.open( 'GET' , mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/index.php?' + QueryString.create( query ), true );
delsortCompatList.send( null );
} catch(e) {
if( e instanceof Exception ) {
Delsort.error( 'Error: ' + e.what() );
} else {
Delsort.error( 'Error: ' + e );
}
}
}
function showDelsortFrameCallback() {
if ( delsortCompatList.readyState != 4 ){
return;
}
if( delsortCompatList.status != 200 ){
Delsort.error('Bad status , bailing out; status = ' + delsortCompatList.status );
return;
}
var doc = delsortCompatList.responseXML;
var list = doc.getElementById('bodyContent').cloneNode(true);
if(! list ) {
Delsort.error( 'Unable to get the list, aborting.');
return;
}
var currentNode = list.firstChild;
var node;
// remove the heading
do {
node = currentNode;
currentNode = node.nextSibling;
list.removeChild ( node );
} while (node.id != 'toc');
// remove the edit links
var spans = list.getElementsByTagName('span');
var i = 0;
for (i = 0; i < spans.length; i++) {
if (spans[i].className == 'editsection') {
spans[i].parentNode.removeChild ( spans[i] );
}
}
var delsortLinkRE = new RegExp ('\/wiki\/Wikipedia:WikiProject_Deletion_sorting\/(.*)');
// remove the edit links
var anchors = list.getElementsByTagName('a');
var i = 0;
for (i = 0; i < anchors.length; i++) {
if ( anchors[i].href && delsortLinkRE.exec(anchors[i].href) ) {
pType = RegExp.$1;
pType = pType.replace(/_/g,' ');
if( navigator.userAgent.indexOf("Opera") != -1 ) {
anchors[i].href = "#";
anchors[i].onclick = new Function("delsortArticle('" + pType + "')");
}
else {
anchors[i].href = "javascript:delsortArticle('" + pType + "')";
}
}
}
Delsort.PopupContents = list;
Delsort.displayPopup( list, "Select deletion sorting criteria" );
}
Delsort.displayPopup = function(pContent, pTitle) {
if ( DelsortConfig['debugLevel'] > 0 )
Status.debugLevel = DelsortConfig.debugLevel;
if (!window['delsortWindow']) {
delsortWindow = new SimpleWindow( 800, 400 );
}
if (pTitle)
delsortWindow.setTitle( pTitle )
if (pContent)
delsortWindow.setContent( pContent );
delsortWindow.display();
}
function delsortArticle( pType ) {
pType = unescape(pType);
window['twDelsortType'] = pType;
wgAfdPage = unescape(wgAfdPage).replace('_',' ','g');
Delsort.displayPopup ( null, "Performing deletion sorting" );
Status.init( window['delsortWindow'].content );
var subpageRE = new RegExp('Wikipedia:Articles for deletion\/(.*)');
if ( subpageRE.exec( wgAfdPage ) ) {
wgNominatedArticle = RegExp.$1;
}
else {
Delsort.error( 'Can not determine article name for "' + wgAfdPage + '", aborting');
return;
}
var additionalNominationRE = new RegExp(' ([(]([0-9]+..|[a-z]+) [Nn]omination[)])');
var pRegexResults = additionalNominationRE.exec( wgNominatedArticle );
wgNominationIndex = '';
if ( pRegexResults ) {
wgNominationIndex = pRegexResults[1];
wgNominatedArticle = wgNominatedArticle.substr(0, pRegexResults.index);
}
Delsort.status( 'Nominated article name: ' + wgNominatedArticle );
if (wgNominationIndex)
Delsort.status( 'Nomination index: ' + wgNominationIndex );
// check the article exists
try {
delsortXML = sajax_init_object();
Delsort.debug( 'delsortXML' + delsortXML );
delsortXML.overrideMimeType('text/xml');
var query = {
'action': 'query',
'titles': wgNominatedArticle,
'prop': 'info',
'format': 'xml'
};
Delsort.status( 'Check the article "' + wgNominatedArticle + '" exists ...');
delsortXML.onreadystatechange = Delsort.verifyArticleExistsCallback;
if (typeof (query.toSource) == 'undefined') {
Delsort.debug( 'query:' + query );
}
else {
Delsort.debug( 'query:' + query.toSource() );
}
var url = mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/api.php?' + QueryString.create( query );
Delsort.debug( 'url:' + url );
delsortXML.open( 'GET' , url, true );
delsortXML.send( null );
} catch(e) {
if( e instanceof Exception ) {
Delsort.error( 'Error: ' + e.what() );
} else {
Delsort.error( 'Error: ' + e );
}
}
}
Delsort.verifyArticleExistsCallback = function() {
var doc = Delsort.getAJAXResponse();
if (typeof doc != 'object') return;
Delsort.debug( ' Article test responseXML = ' + delsortXML.responseText );
var pageNode = doc.getElementsByTagName('page');
if (!pageNode || !pageNode[0] || !pageNode[0].getAttribute('lastrevid')) {
Delsort.status( 'Article not found' );
return;
}
Delsort.status( ' OK ' );
try {
delsortXML = sajax_init_object();
Delsort.debug( 'delsortXML' + delsortXML );
delsortXML.overrideMimeType('text/xml');
var query = {
'action': 'submit',
'title': 'Wikipedia:WikiProject Deletion sorting/' + window['twDelsortType'],
'section': 1
};
Delsort.status( 'Grabbing edit form for ' + query.title);
delsortXML.onreadystatechange = delsortCallback;
Delsort.debug( 'query:' + query.toSource() );
delsortXML.open( 'GET' , mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/index.php?' + QueryString.create( query ), true );
delsortXML.send( null );
} catch(e) {
if( e instanceof Exception ) {
Delsort.error( 'Error: ' + e.what() );
} else {
Delsort.error( 'Error: ' + e );
}
}
}
function delsortCallback() {
var delsortForm = Delsort.getAJAXEditForm();
if (typeof delsortForm != 'object') return;
var doc = delsortForm.ownerDocument;
var textbox = doc.getElementById( 'wpTextbox1' );
Delsort.status( 'Checking contents of ' + window['twDelsortType'] + ' list');
Delsort.debug( 'Looking for ' + wgNominatedArticle + ' in ' + textbox.value);
if ( (textbox.value.indexOf( wgNominatedArticle + '}}' ) != -1) ||
(textbox.value.indexOf( wgNominatedArticle.replace(/ /g,'_') + '}}' ) != -1) )
{
Delsort.error( wgNominatedArticle + ' already listed on ' + window['twDelsortType']);
return;
}
Delsort.progress( ': ok' );
// remove (U.S. State) and (country) after Georgia
var sectionHeaderTitle = window['twDelsortType'].replace(/ [(].*[)]/,'');
var sectionHeaderRE = new RegExp('(==+ *(.*[^=\n]*) *==+)\n(\n*<[^>]*>)*(\n)*');
if ( ! sectionHeaderRE.test( textbox.value ) ) {
Delsort.error( 'Unable to locate where to place the new listing; aborting.' );
return;
}
var sectionHeader = RegExp.$1;
Delsort.debug( 'Found section ' + sectionHeader );
var sectionHeaderAcceptRE = new RegExp('(List of deletion discussions|Articles for deletion|General|Other|' + sectionHeaderTitle + ')');
if ( ! sectionHeaderAcceptRE.test( sectionHeader ) ) {
Delsort.error( 'The section header title "' + sectionHeader + '" looks a bit odd; aborting.' );
return;
}
var newval = textbox.value.replace(sectionHeaderRE,'$&{{' + wgAfdPage + '}}\n');
if (textbox.value == newval) {
Delsort.error( 'Unable to add Afd, will abort.' );
return;
}
textbox.value = newval;
Delsort.debug('contents = ' + textbox.value);
Delsort.status( 'Updating the summary...' );
var summary = "Listing " + wgNominatedArticle + "";
if ( wgNominationIndex )
summary += wgNominationIndex;
Delsort.progress( summary );
// safety valve to prevent bad edit summaries
if ( summary.indexOf ( 'Log' ) > -1 ) {
Delsort.error ( 'incorrect summary, aborting' );
return;
}
doc.getElementById( 'wpSummary' ).value = summary; // + TwinkleConfig.summaryAd;
// Mark adding an article to a delsort list as a major edit
// to ensure it appears on Watchlists
doc.getElementById( 'wpMinoredit' ).checked = false;
if ( DelsortConfig['watchDelsortedLists'] > 0 ) {
Delsort.debug( ' (Watching the Delsort list) ' );
doc.getElementById( 'wpWatchthis' ).checked = true;
}
if ( DelsortConfig['watchDelsortedLists'] == 0 ) {
Delsort.debug( ' (Not watching the Delsort list) ' );
doc.getElementById( 'wpWatchthis' ).checked = false;
}
// debugging interrupt to prevent damage
// return;
if (! Delsort.submitHiddenForm ( delsortForm ) )
return;
Delsort.progress( 'done' );
// if the user was in edit mode, use the current form
if (typeof Delsort.afdForm == 'object' && Delsort.afdForm &&
Delsort.afdForm['tagName'] && Delsort.afdForm['tagName'] == 'FORM') {
Delsort.debug( ' Found that the Afd is already in edit mode... ' );
Delsort.markAfdDelsorted( Delsort.afdForm );
return;
}
Delsort.debug( ' Calling markDelsortedArticle()... ' );
markDelsortedArticle();
}
function markDelsortedArticle( pType ) {
if ( pType && !window['twDelsortType'])
window['twDelsortType'] = pType;
Delsort.debug( ' In markDelsortedArticle... ' );
try {
delsortXML = sajax_init_object();
Delsort.debug( 'delsortXML' + delsortXML );
delsortXML.overrideMimeType('text/xml');
var query = {
'action': 'submit',
'title': wgAfdPage
};
Delsort.status( 'Grabbing edit form for ' + query.title);
delsortXML.onreadystatechange = markDelsortedCallback;
Delsort.debug( 'query:' + query.toSource() );
delsortXML.open( 'GET' , mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/index.php?' + QueryString.create( query ), true );
delsortXML.send( null );
} catch(e) {
if( e instanceof Exception ) {
Delsort.error( 'Error: ' + e.what() );
} else {
Delsort.error( 'Error: ' + e );
}
}
}
function markDelsortedCallback() {
var afdForm = Delsort.getAJAXEditForm ();
if (typeof afdForm != 'object') return;
Delsort.markAfdDelsorted ( afdForm );
}
// returns 0 when still in progress
// -1 if there was an error
// or the edit form when successfully obtained
Delsort.getAJAXResponse = function() {
if ( delsortXML.readyState != 4 ){
Delsort.progress('.');
return 0;
}
if( delsortXML.status != 200 ){
Delsort.error('Bad status , bailing out; status = ' + delsortXML.status);
return -1;
}
var doc = delsortXML.responseXML;
if( !doc ) {
Delsort.error( 'Possible failure in receiving document, will abort.' );
return -1;
}
Delsort.progress( 'done' );
return doc;
}
Delsort.getAJAXEditForm = function() {
var doc = Delsort.getAJAXResponse();
if (typeof doc != 'object') return doc;
var editForm = doc.getElementById( 'editform' );
if(! editForm ) {
Delsort.error( 'Possible failure in receiving document, aborting.' + doc);
return -1;
}
return editForm;
}
Delsort.markAfdDelsorted = function( pAfdForm ) {
var textbox = pAfdForm['wpTextbox1'];
var modified = ( textbox.value == textbox.defaultValue ) ? 0 : 1;
// if the last character in the box is a sig, add a new link character
if (/[~]$/.test ( textbox.value ) )
textbox.value += "\n";
textbox.value += "{{subst:" + "delsort|" + window['twDelsortType'] + "}} -- ~~" + "~~";
Delsort.debug('contents = ' + textbox.value);
Delsort.status( 'Updating the summary...' );
// TODO: the " (xth nom)" needs to be stripped
var summary = "Listing on WP:DELSORT under " + window['twDelsortType'];
// preserve any manual comments in the edit summary
var wpSummaryNode = pAfdForm['wpSummary'];
if ( wpSummaryNode.value != wpSummaryNode.defaultValue )
wpSummaryNode.value += '; ' + summary;
else
wpSummaryNode.value = summary;
Delsort.progress( summary );
wpPreviewMode = document.getElementById("wikiPreview") ? 1 : 0;
// Marking article as delsorted is a minor edit
// unless the the Afd form is in preview mode or the user
// has manually changed the textbox
var wpMinoreditNode = pAfdForm['wpMinoredit'];
if ( wpMinoreditNode.checked == false &&
!wpPreviewMode && !modified )
wpMinoreditNode.checked = true;
if ( DelsortConfig['watchDelsortedAfd'] > 0 ) {
Delsort.debug( ' (Watching the Afd) ' );
pAfdForm['wpWatchthis'].checked = true;
}
if ( DelsortConfig['watchDelsortedAfd'] == 0 ) {
Delsort.debug( ' (Not watching the Afd) ' );
pAfdForm['wpWatchthis'].checked = false;
}
// when the Afd has been trancluded onto the currently displayed
// page (i.e. the logs), the form submission happens in the background
if ( unescape(wgPageName).replace('_',' ','g') != wgAfdPage ) {
Delsort.submitHiddenForm(pAfdForm);
if (window['delsortWindow'] && window['delsortWindow']['frame'] ) {
try {
document.body.removeChild( window['delsortWindow'].frame );
} catch (x) {}
}
return;
}
// if the form was in edit mode, there is no need to add the from to
// the document before submission.
if (! Delsort.afdForm ) {
Delsort.debug( ' appending the form to the document ' );
document.body.appendChild( pAfdForm );
}
Delsort.status( 'Submitting the form...' );
pAfdForm.submit();
}
Delsort.getIFrame = function() {
var iFrameID = 'delsortFrame';
var iFrame = document.getElementById('delsortFrame');
if (iFrame) {
iFrame.setAttribute('src', 'about:blank');
return iFrame;
}
iFrame = document.createElement('IFRAME');
if(! iFrame ) {
Delsort.error( 'Unable to create an IFRAME, aborting.');
return;
}
iFrame.setAttribute('src', 'about:blank');
iFrame.setAttribute('id', iFrameID);
iFrame.setAttribute('NAME', iFrameID);
iFrame.style.display = 'none';
iFrame.style.width = 0;
iFrame.style.height = 0;
document.body.appendChild( iFrame );
return iFrame;
}
Delsort.submitHiddenForm = function(pForm) {
iFrame = Delsort.getIFrame();
pForm.target = iFrame.id;
iFrame.appendChild( pForm);
Delsort.status( 'Submitting the form...' );
try {
pForm.submit();
} catch(e) {
if( e instanceof Exception ) {
Delsort.error( 'Error: ' + e.what() );
} else {
Delsort.error( 'Error: ' + e );
}
return false;
}
return true;
}
//