User:Saftzie/app.phsl.js

/* * Description: * Use row marking on the local "master" penguin locations list *  to generate updates to the DnD Locations article. * Extends and depends upon MediaWiki:Common.js/highlightTable.js * * Version 1.0: 16 July 2014 */

window.user = window.user || {}; window.user.peng = window.user.peng || {}; window.user.peng.dndl = (function { // update D&D location page with a selection of penguins  'use strict';

var self = {}, gwikiRows = [], gdomTBody, gdomRows, gwikiNewContent, gsWeek, goRequest;

// call the MediaWiki API using POST function apiCall(query, next) {   var urlAPI = wgServer + wgScriptPath + '/api.php';

goRequest.open('POST', urlAPI, true); goRequest.setRequestHeader('Content-Type','application/x-www-form-urlencoded;');

goRequest.onreadystatechange = function {     if (goRequest.readyState === 4) {       goRequest.onreadystatechange = undefined; if (goRequest.status === 200) {         next; }       else {         self.message = 'apiCall :: "' + query + '" returned "' + goRequest.statusText + '"'; }     }    };

goRequest.send(query); }

// process action=edit return function onEdit {   var o;

o = JSON.parse(goRequest.responseText); if (o.error) {     self.message = 'onEdit :: ' + o.error.code + ': ' + o.error.info; document.getElementById('pengMessage').innerHTML = 'Edit error.'; }   else if (o.edit) {     self.message = 'onEdit :: ' + o.edit.result; document.getElementById('pengMessage').innerHTML = 'Edit done.'; }   else {     self.message = 'onEdit :: ' + goRequest.responseText; document.getElementById('pengMessage').innerHTML = 'Edit ended abnormally.'; } }

// process action=query return function onQuery {   var regex = /\{\|(.|\n)*\|\}/;

var wikiContent = '', sBaseTime, sStartTime, sToken, o, p;

o = JSON.parse(goRequest.responseText); if (o.error) {     self.message = 'onQuery :: ' + o.error.code + ': ' + o.error.info; document.getElementById('pengMessage').innerHTML = 'Query error.'; return; }   else if (!o.query.pages) {     self.message = 'onQuery :: ' + goRequest.responseText; document.getElementById('pengMessage').innerHTML = 'Query ended abnormally.'; return; }

o = o.query.pages; for (p in o)   { // there should be only 1 page since we asked for only 1 page if (o.hasOwnProperty(p)) {       sBaseTime = o[p].touched; sStartTime = o[p].starttimestamp; sToken = o[p].edittoken; wikiContent = o[p].revisions[0]['*']; }   }

if (wikiContent.search(regex) < 0) {     self.message = 'onQuery :: No old content found to replace'; document.getElementById('pengMessage').innerHTML = 'Query ended abnormally.'; return; }   wikiContent = wikiContent.replace(regex, gwikiNewContent); document.getElementById('pengMessage').innerHTML = 'Running edit ...';

// Wikia insists on title, not page ID   apiCall(    [      'action=edit',      'format=json',      'title=' + encodeURIComponent(self.title),      'section=4',      'text=' + encodeURIComponent(wikiContent),      'summary=' + encodeURIComponent('/* Locations */ New week info v') + gsWeek,      'basetimestamp=' + encodeURIComponent(sBaseTime),      'starttimestamp=' + encodeURIComponent(sStartTime),      'token=' + encodeURIComponent(sToken)    ].join('&'), onEdit); }

// duplicate all high-lighted rows function onClickTwin {   var nLen = gdomRows.length;

var domRow, i;

for (i = nLen - 2 ; i > 0 ; --i) {     if (gdomRows[i].className === 'highlight-on') {       domRow = gdomRows[i].cloneNode(true); domRow.removeAttribute('class'); gdomTBody.insertBefore(domRow, gdomRows[i + 1]); gwikiRows.splice(i, 0, gwikiRows[i - 1]); }   }  }

// compose new table and start the edit process function onClickCommit {   // epoch day 14111 is 20 Aug 2008, the beginning of "week 0" var nWeek = Math.floor((new Date.getTime / 86400000 - 14111) / 7), d = new Date((nWeek * 7 + 14111) * 86400000), sMonth = [         'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ][d.getUTCMonth], nLen = gwikiRows.length;

var i;

// compose the new table for (i = 0 ; i < nLen ; ++i) {     gwikiRows[i] = '| ' + (i + 1).toString + '\n' + gwikiRows[i].join('\n|'); }   gwikiRows = gwikiRows.join('|-\n'); gwikiRows = [     '{| class="wikitable" id="pengLocations"', '|+ style="text-align:left;" | For the week beginning: ' + d.getUTCDate.toString + ' ' + sMonth, '|-',     '! No. !! Spawn area ', '! class="pengToggle" | Requirement !! Type ', '! class="pengToggle" | Penguin Points (after Cold War) ', '! class="pengToggle" | Maps (Click to enlarge) ', '|-'   ].join('\n') + '\n' + gwikiRows + '|}';

gwikiNewContent = gwikiRows; gsWeek = nWeek.toString;

// display processing gwikiRows = gwikiRows.replace(/\>/g, '&gt;').replace(/' + gwikiRows + '   ' + ' Running query ... ';

apiCall(   [      'action=query',      'format=json',      'prop=' + encodeURIComponent('revisions|info'),      'rvprop=content',      'rvlimit=1',      'rvsection=4',      'rvcontentformat=' + encodeURIComponent('text/x-wiki'),      'intoken=edit',      'titles=' + encodeURIComponent(self.title)    ].join('&'), onQuery); }

// use the high-lighted selections for this week function onClickUse {   var nMonth = new Date.getUTCMonth;

var domRow, domButtonTH, domButtons, domButton, nLen, bFound, i, s;

// selection sort gwikiRows based on f(gwikiRows[]) // gwikiRows and nLen = gwikiRows.length are inherited function sort(f) {     var sRow, iKey, jKey, i, j, k;

for (i = 0 ; i < nLen - 1 ; ++i) {       iKey = f(i); for (j = i + 1 ; j < nLen ; ++j) {         jKey = f(j); if (jKey < iKey) {           sRow = gwikiRows[j]; // shift gwikiRows[i .. j-1] down one for (k = j ; k > i ; --k) {             gwikiRows[k] = gwikiRows[k - 1]; }           gwikiRows[i] = sRow; iKey = jKey; }       }      }    }

// get button info domButtonTH = document.getElementById('pengData').getElementsByTagName('th'); domButtonTH = domButtonTH[domButtonTH.length - 1]; domButtons = domButtonTH.getElementsByTagName('input');

// wait until goRequest completes if (goRequest.readyState !== 4) { // try again later domButtons[0].disabled = true; domButtons[1].disabled = true; goRequest.onreadystatechange = onClickUse; return; }   goRequest.onreadystatechange = undefined; if (goRequest.status !== 200) {     domButtons[0].disabled = true; domButtons[1].disabled = true; self.message = 'onClickUse :: Error retrieving wiki markup'; return; }

gwikiRows = goRequest.responseText; // need just the row data gwikiRows = gwikiRows.substr(gwikiRows.search(/\n\|-/) + 4); gwikiRows = gwikiRows.substr(0, gwikiRows.search(/\|\}/)); // file link -> file gwikiRows = gwikiRows.replace(/\[\[:File/g, '160px'); // Hallowe'en and Christmas if ((nMonth === 9) || (nMonth === 11)) {     s = (nMonth === 9) ? 'Pumpkin' : 'Snowman'; gwikiRows = gwikiRows .replace(/Barrel/g, s)       .replace(/Bush/g, s)        .replace(/Cactus/g, s)        .replace(/Crate/g, s)        .replace(/Rock/g, s)        .replace(/Toadstool/g, s); }   // discard the coord column gwikiRows = gwikiRows.split(/\|-\n/); nLen = gwikiRows.length; for (i = 0 ; i < nLen ; ++i) { // Note: split gets rid of all but the first '|' (temporarily) gwikiRows[i] = gwikiRows[i].split('\n|'); gwikiRows[i].splice(4, 1); }

gdomRows = document.getElementById('pengData').getElementsByTagName('tr'); // gdomRows includes the th rows, so there's an offset of 1 nLen = gdomRows.length; bFound = false; for (i = 1 ; i < nLen - 1 ; ++i) {     domRow = gdomRows[i]; if (domRow.className === 'highlight-on') {       bFound = true; gwikiRows[i - 1].push(domRow); }   }    if (!bFound) {     self.message = 'onClickUse :: No rows selected'; if (domButtons[0].disabled === true) { // re-enable the buttons domButtons[0].disabled = false; domButtons[1].disabled = false; }     return; }

// delete gwikiRows with no domRow i = 0; while (i < gwikiRows.length) {     if (gwikiRows[i].length === 6) {       ++i; }     else // gwikiRows[i].length === 5 {       gwikiRows.splice(i, 1); }   }  /*    sort order: ---   Disguise    (col 3): Polar Bear > other Points     (col 4): 3 > 1 (2) > 1 Requirement (col 2): other > None Location   (col 1): Wilderness > other */   nLen = gwikiRows.length; sort(function (i)   {      return gwikiRows[i][0].search(/^\|\s*Wilderness/);    }); sort(function (i)   {      return -(gwikiRows[i][1].search(/^\s*None/));    }); sort(function (i)   {      switch (gwikiRows[i][3].trim)      {        case '1':          return 1;        case '3':          return 3;        default: // '1 (2)'          return 2;      }    }); sort(function (i)   {      return gwikiRows[i][2].search(/^\s*Polar\s+Bear/);    });

gdomTBody = gdomRows[0].parentNode; // keep sorted HTML for (i = 0 ; i < nLen ; ++i) {     gdomTBody.insertBefore(gwikiRows[i].pop, gdomTBody.lastChild); }   while (gdomRows[1].className !== 'highlight-on') {     gdomTBody.removeChild(gdomRows[1]); }   // reuse reset button & discard the use button ... if (domButtons[0].disabled === true) {     domButtons[0].disabled = false; }   if (document.removeEventListener) {     domButtons[1].removeEventListener('click', onClickUse); }   else if (document.detachEvent) {     domButtons[1].detachEvent('onclick', onClickUse); }   domButtonTH.removeChild(domButtons[1]); // ... add some more buttons domButton = document.createElement('input'); domButton.type = 'button'; domButton.value = 'Twin selection'; domButtonTH.appendChild(domButton.cloneNode(true)); domButton.value = 'Commit'; domButtonTH.appendChild(domButton); if (document.addEventListener) {     domButtons[1].addEventListener('click', onClickTwin); domButtons[2].addEventListener('click', onClickCommit); }   else {     domButton[1].attachEvent('onclick', onClickTwin); domButton[2].attachEvent('onclick', onClickCommit); } }

$(function main {    var domTable,        domButtonCell,        domButton;

if (!JSON.parse) {     self.message = 'main :: No JSON support'; return; }

domTable = document.getElementById('pengData'); if ((!domTable) || (domTable.className.search('lighttable') === -1)) {     self.message = 'main :: No lighttable with ID "pengData" found'; return; }

// the button row is the header row at the end added by lighttable domButtonCell = domTable.getElementsByTagName('tr'); domButtonCell = domButtonCell[domButtonCell.length - 1].getElementsByTagName('th'); if (domButtonCell.length === 0) { // try again later window.setTimeout(main, 10); return; }

domButtonCell = domButtonCell[0]; domButton = document.createElement('input'); domButton.type = 'button'; domButton.value = 'Use selection';

if (document.addEventListener) { // for most browsers, except IE 8 and earlier domButton.addEventListener('click', onClickUse); }   else if (document.attachEvent) { // for IE 8 and earlier domButton.attachEvent('onclick', onClickUse); }   else {     self.message = 'main :: Unable to add event listeners'; return; }

domButtonCell.appendChild(domButton);

// get raw for the original wiki markup if (window.XMLHttpRequest) { // most browsers goRequest = new XMLHttpRequest; }   else if (window.ActiveXObject) { // IE 6 and previous goRequest = new ActiveXObject('Microsoft.XMLHTTP'); }   else {     self.message = 'main :: Unable to create XMLHttpRequest'; domButton.disabled = true; return; }   goRequest.open('GET',      wgServer + wgArticlePath.replace('$1', wgPageName) + '?action=raw',      true); goRequest.send; });

self.message = self.message || 'OK'; self.title = 'Distractions and Diversions Locations/Penguin Hide and Seek';

return self; });