MediaWiki:Dialog/receive

/* This script provides functions to receive parameters passed via Dialog/button, and to register page dependencies. Any javascript page importing this page should also contain a commented link to it, for Special:WhatLinksHere/.

For instructions, see the |talk page. */

if (! window.wikidialog) window.wikidialog = {}; if (! window.wikidialog.receiveAnonymous) (function {    //    // version    //    function receiveVersion { return '0.42 (2019-11-05)'; }    //    window.wikidialog.safeHtml = function (s) {        return s.replace(/\/g,'&gt;');    };    function getWikidialogID {        var s = location.search.match(/[\?&]wikidialogid=(\d+)/);        if (s && s.length && (s.length > 1)) {            var thisID = Number(s[1])            if (sessionStorage) {                var nextID = 0;                if (sessionStorage.wikidialogNextID) { nextID = Number(sessionStorage.wikidialogNextID); }                if (nextID <= thisID) { sessionStorage.wikidialogNextID = (thisID + 1); }            }            return thisID;        }        if (sessionStorage) {            if (! sessionStorage.wikidialogNextID) sessionStorage.wikidialogNextID = '1';           return (Number(sessionStorage.wikidialogNextID) - 1);        }        return 0;    }    function getData {        var id = getWikidialogID;        var data = {};        var params = sessionStorage['wikidialog:' + id + ':params'];        if (params) {            params = params.split(',');            for (var k = 0; k < params.length; k++) if (params[k]) data[params[k]] = sessionStorage['wikidialog:' + id + ':in:' + params[k]];        }        return data;    }    function anchorEncode(s) {        return encodeURIComponent( s.replace( / /g, '_' ) )            .replace( /!/g, '%21' ).replace( /'/g, '%27' )            .replace( /\(/g, '%28' ).replace( /\)/g, '%29' )            .replace( /\*/g, '%2A' ).replace( /~/g, '%7E' )            .replace( /%3A/g, ':' ).replace( /%/g, '.' );    }    function saveGeometries(id, tag, carry) { var areas = $('input.wikidialog-text, textarea.wikidialog-textarea').map(function {            var t = $(this);            if (t.css('display') == 'none') return;            return t;        }); if ((typeof carry) == "object") { areas = areas.map(function {                var t = $(this);                var tid = t.attr('id');                for (var k = 0; k < carry.length; k++)                    if ((tid == ('wikidialog-' + carry[k])) || (tid == ('wikidialog-' + anchorEncode(carry[k]))) )                       return t;                return;            }); }       areas.each(function  {            var t = $(this);            var name = t.attr('id').substring(11);            sessionStorage['wikidialog:' + id + ':' + tag + ':' + name + ':scroll-top' ] = t.scrollTop;            sessionStorage['wikidialog:' + id + ':' + tag + ':' + name + ':scroll-left'] = t.scrollLeft;            sessionStorage['wikidialog:' + id + ':' + tag + ':' + name + ':height'     ] = t.height;            sessionStorage['wikidialog:' + id + ':' + tag + ':' + name + ':width'      ] = t.width;        }); }   function collectGeometry(id, tag, name) { sessionStorage.removeItem('wikidialog:' + id + ':' + tag + ':' + name + ':scroll-top'); sessionStorage.removeItem('wikidialog:' + id + ':' + tag + ':' + name + ':scroll-left'); sessionStorage.removeItem('wikidialog:' + id + ':' + tag + ':' + name + ':height'); sessionStorage.removeItem('wikidialog:' + id + ':' + tag + ':' + name + ':width'); }   function restoreGeometries(id, tag) { $('input.wikidialog-text, textarea.wikidialog-textarea').each(function {            var t = $(this);            if (t.css('display') == 'none') return;            var name = t.attr('id').substring(11);            var st = sessionStorage['wikidialog:' + id + ':' + tag + ':' + name + ':scroll-top' ];            var sl = sessionStorage['wikidialog:' + id + ':' + tag + ':' + name + ':scroll-left'];            var ht = sessionStorage['wikidialog:' + id + ':' + tag + ':' + name + ':height'     ];            var wd = sessionStorage['wikidialog:' + id + ':' + tag + ':' + name + ':width'      ];            if (st) t.scrollTop( st);            if (sl) t.scrollLeft(sl);            if (ht) t.height(    ht);            if (wd) t.width(     wd);            collectGeometry(id, tag, name);        }); }   function addNote(s) { var id = getWikidialogID; var note = sessionStorage['wikidialog:' + id + ':notes']; s = 'Dialog note: ' + window.wikidialog.safeHtml(s) + ' '; sessionStorage['wikidialog:' + id + ':notes'] = (note ? (note + s) : s); }   function clearNotes { var id = getWikidialogID; sessionStorage.removeItem('wikidialog:' + id + ':notes'); sessionStorage.removeItem('wikidialog:' + id + ':keep-notes'); }   function getNotes { return sessionStorage['wikidialog:' + getWikidialogID + ':notes']; }   function releaseSavedFieldValues(sfx, id) { if (! sfx) sfx = ''; // precaution if (! id) id = getWikidialogID; // default var ls = sessionStorage['wikidialog:' + id + ':saves' + sfx]; if (! ls) ls = ''; // precaution ls = ls.split(','); var k;       for (k = ls.length - 1; k>=0; k--) { sessionStorage.removeItem('wikidialog:' + id + ':sv' + sfx + ':' + ls[k]); collectGeometry(id, ('sv' + sfx), ls[k]); }       sessionStorage.removeItem('wikidialog:' + id + ':saves' + sfx); }   function activateSavedFieldValues(sfx, id) { if (! sfx) return; if (! id) id = getWikidialogID; // default releaseSavedFieldValues('', id); var ls = sessionStorage['wikidialog:' + id + ':saves' + sfx]; if (! ls) ls = ''; // precaution ls = ls.split(','); for (var k = ls.length - 1; k>=0; k--) { sessionStorage[          'wikidialog:' + id + ':sv:'            + ls[k]] = sessionStorage[      'wikidialog:' + id + ':sv' + sfx + ':' + ls[k]]; sessionStorage[          'wikidialog:' + id + ':sv:'            + ls[k].substring(11) + ':scroll-top'] = sessionStorage[      'wikidialog:' + id + ':sv' + sfx + ':' + ls[k].substring(11) + ':scroll-top']; sessionStorage[          'wikidialog:' + id + ':sv:'            + ls[k].substring(11) + ':scroll-left'] = sessionStorage[      'wikidialog:' + id + ':sv' + sfx + ':' + ls[k].substring(11) + ':scroll-left']; sessionStorage[          'wikidialog:' + id + ':sv:'            + ls[k].substring(11) + ':height'] = sessionStorage[      'wikidialog:' + id + ':sv' + sfx + ':' + ls[k].substring(11) + ':height']; sessionStorage[          'wikidialog:' + id + ':sv:'            + ls[k].substring(11) + ':width'] = sessionStorage[      'wikidialog:' + id + ':sv' + sfx + ':' + ls[k].substring(11) + ':width']; // don't remove yet; hopefully no field is listed more than once, // but if it is we don't want that to cause misbehavior here }       for (var k = ls.length - 1; k>=0; k--) { sessionStorage.removeItem('wikidialog:' + id + ':sv' + sfx + ':' + ls[k]); collectGeometry(id, ('sv' + sfx), ls[k]); }       sessionStorage['wikidialog:' + id + ':saves'] = sessionStorage['wikidialog:' + id + ':saves' + sfx]; sessionStorage.removeItem('wikidialog:' + id + ':saves' + sfx); }   function saveFieldValues(id, sfx) { if (! sfx) sfx = ''; // precaution var s = ''; var n = 64; // SINGLE POINT TO ADJUST max number of fields to save $('input.wikidialog-text, textarea.wikidialog-textarea, select.wikidialog-select').each(function {            var t = $(this);            if (t.css('display') == 'none') return;            n--;            if (n <= 0) return;            var tname = t.attr('id');            var tvalue = t.val;            sessionStorage['wikidialog:' + id + ':sv' + sfx + ':' + tname] = tvalue;            if (s) s += ',';            s += tname;        }); saveGeometries(id, ('sv' + sfx)); $('input.wikidialog-checkbox').each(function {            n--;            if (n <= 0) return;            var t = $(this);            var tname = t.attr('id');            var tchecked = (t[0].checked ? 'yes' : '');           sessionStorage['wikidialog:' + id + ':sv' + sfx + ':' + tname] = tchecked;            if (s) s += ',';            s += tname;        }); sessionStorage['wikidialog:' + id + ':saves' + sfx] = s;   } function restoreSavedFieldValues { var id = getWikidialogID; var ls = sessionStorage['wikidialog:' + id + ':saves']; if (! ls) ls = ''; // precaution; ls = ls.split(','); $('input.wikidialog-text, textarea.wikidialog-textarea').each(function {            var n = $(this);            var ni = n.attr('id');            var k;            for (k = ls.length - 1; k>=0; k--) if (ls[k] == ni) {                var sv = sessionStorage['wikidialog:' + id + ':sv:' + ni];                if (! sv) sv = ''; // precaution               n.val(sv);                break;            }        }); restoreGeometries(id, 'sv'); $('input.wikidialog-checkbox').each(function {            var n = $(this);            var ni = n.attr('id');            var k;            for (k = ls.length - 1; k>=0; k--) if (ls[k] == ni) {                var sv = sessionStorage['wikidialog:' + id + ':sv:' + ni];                if (sv) n.attr('checked','yes');                else n.removeAttr('checked');                break;            }        }); $('select.wikidialog-select').each(function {            var n = $(this);            var ni = n.attr('id');            for (k = ls.length - 1; k>=0; k--) if (ls[k] == ni) {                var sv = sessionStorage['wikidialog:' + id + ':sv:' + ni];                var k;                for (var j=0; j<this.length; j++)                    if (this[j].value == sv) {                        this.selectedIndex = j;                        break;                    }                break;            }        }); }   function clearRollbackDelegating { var id = getWikidialogID; if (sessionStorage['wikidialog:' + id + ':rb-available']) { sessionStorage.removeItem('wikidialog:' + id + ':rb-available'); //           sessionStorage.removeItem('wikidialog:' + id + ':rb-incoming'); sessionStorage.removeItem('wikidialog:' + id + ':rb-unauth'); sessionStorage.removeItem('wikidialog:' + id + ':rb-origin'); sessionStorage.removeItem('wikidialog:' + id + ':rb-proxy'); //           sessionStorage.removeItem('wikidialog:' + id + ':rb-added'); //           ls = sessionStorage['wikidialog:' + id + ':rb-changed']; if (! ls) ls = ''; // precaution; ls = ls.split(','); for (k = ls.length - 1; k>=0; k--) sessionStorage.removeItem('wikidialog:' + id + ':rb-in:' + ls[k]); sessionStorage.removeItem('wikidialog:' + id + ':rb-changed'); //           releaseSavedFieldValues('-rb', id); }   }    function clearRollbackSimple { var id = getWikidialogID; if (sessionStorage['wikidialog:' + id + ':prevurl']) { sessionStorage.removeItem('wikidialog:' + id + ':prevurl'); clearRollbackDelegating; }   }    function getStableUrl(unforced) { var currentUrl = (location.pathname + location.search); if (unforced) { return currentUrl; } else { var newUrl = mw.util.getUrl(mw.config.get('wgPageName')) + '?wikidialogid=' + getWikidialogID; if (newUrl == currentUrl) { newUrl += '&x=x'; }           return newUrl; }   }    function stashUnstableUrl { //       // if we're here, and there's no id in the url, by definition it's unstable //       var s = location.search.match(/[\?&]wikidialogid=(\d+)/); if (s && s.length && (s.length > 1)) { sessionStorage.removeItem('wikidialogUnstableUrl'); } else { sessionStorage.wikidialogUnstableUrl = location.href; }   }    function delegateVerified(data, metaproc, shortcut, shortcutParam) { var olddata = getData; var id = getWikidialogID; if (data) for (var p in data) { sessionStorage['wikidialog:' + id + ':in:' + p] = data[p]; var params = sessionStorage['wikidialog:' + id + ':params']; if (! params) params = ''; // robust against undefined, which may arise during query-url conversion if (! (p in olddata)) sessionStorage['wikidialog:' + id + ':params'] = params + ',' + p + ','; }       var carry = ''; if (metaproc) { var metadata = metaproc({                   unauth: sessionStorage['wikidialog:' + id + ':unauth'],                    origin: sessionStorage['wikidialog:' + id + ':origin'],                    proxy:  sessionStorage['wikidialog:' + id + ':proxy']                }); sessionStorage['wikidialog:' + id + ':unauth'] = ((('unauth' in metadata) && metadata.unauth) ? metadata.unauth : ''); sessionStorage['wikidialog:' + id + ':origin'] = ((('origin' in metadata) && metadata.origin) ? metadata.origin : ''); sessionStorage['wikidialog:' + id + ':proxy' ] = ((('proxy' in metadata) && metadata.proxy ) ? metadata.proxy  : ''); carry                                         = ((('carry'  in metadata) && metadata.carry ) ? metadata.carry  : ''); }       sessionStorage['wikidialog:' + id + ':incoming'] = getStableUrl(shortcut); if (sessionStorage['wikidialog:' + id + ':keep-notes']) { sessionStorage.removeItem('wikidialog:' + id + ':keep-notes'); } else { clearNotes; }       saveGeometries(id, 'in', carry); if (shortcut) shortcut(shortcutParam); else location = getStableUrl(shortcut); }   function authenticIncoming { var id = getWikidialogID; var origin = sessionStorage['wikidialog:' + id + ':origin']; if (! origin) origin = ''; // precaution else origin = mw.util.getUrl(origin); var proxy = sessionStorage['wikidialog:' + id + ':proxy']; if (! proxy) proxy = ''; // precaution else proxy = mw.util.getUrl(proxy); var someFound = false; var noneFailed = true; $('span.wikidialog-origin').each(function { // Template:Dialog/require origin            someFound = true;            var s = $(this).text;            s = s.split('&');            if (s.length == 1) return; // Template:Dialog/null requirement            if (origin) {                if (s[1]) s[1] = mw.util.getUrl(s[1]);                for (var k = 2; (k < s.length); k++) s[k] = mw.util.getUrl(s[k]);                if (s[1] == proxy) for (var k = 2; (k < s.length); k++) if (s[k] == origin) return;            }            noneFailed = false;            return false;        }); if (! someFound) { addNote('No outgoing authentication because no requirement clause was found.'); } else if (! noneFailed) { addNote('No outgoing authentication because a requirement clause failed.'); }       return (someFound && noneFailed); }   function registerAuthentication(origin, callback) { var proxy = ''; if (! origin) origin = mw.config.get('wgPageName'); else if ((typeof origin) == 'function') { callback = origin; origin = mw.config.get('wgPageName'); } else proxy = mw.config.get('wgPageName'); $('span.wikidialog-button, input.wikidialog-button, button.wikidialog-button').each(function {            var button = $(this);            var wikidialogButtonData = button.data;            if ('wikidialogButtonData' in wikidialogButtonData)                wikidialogButtonData = wikidialogButtonData.wikidialogButtonData;            else wikidialogButtonData = {};            wikidialogButtonData.origin = origin;            if (proxy) wikidialogButtonData.proxy = proxy;            button.data('wikidialogButtonData',wikidialogButtonData);        }); if (callback) callback; }   function registerUnauthenticated(requesting) { $('span.wikidialog-button, input.wikidialog-button, button.wikidialog-button').each(function {            var button = $(this);            var wikidialogButtonData = button.data;            if ('wikidialogButtonData' in wikidialogButtonData)                wikidialogButtonData = wikidialogButtonData.wikidialogButtonData;            else wikidialogButtonData = {};            wikidialogButtonData.unauth = requesting;            button.data('wikidialogButtonData',wikidialogButtonData);        }); }   function maybeCollect(activeList, stack) { function isActive(id) { for (var k = activeList.length - 1; k>=0; k--  ) if (activeList[k] == id) return true; for (var k = stack.length - 2;     k>=0; k -= 2) if (stack[k]      == id) return true; return false; }       for (var id = Number(sessionStorage.wikidialogNextID) - 1; id>=0; id--) if (! isActive(id)) { sessionStorage.removeItem('wikidialog:' + id + ':incoming'); sessionStorage.removeItem('wikidialog:' + id + ':unauth'); sessionStorage.removeItem('wikidialog:' + id + ':origin'); sessionStorage.removeItem('wikidialog:' + id + ':proxy'); sessionStorage.removeItem('wikidialog:' + id + ':newparams'); var ls = sessionStorage['wikidialog:' + id + ':params']; if (! ls) ls = ''; // precaution; ls = ls.split(','); for (var k = ls.length - 1; k>=0; k--) { sessionStorage.removeItem('wikidialog:' + id + ':in:' + ls[k]); collectGeometry(id,'in',ls[k]); }           sessionStorage.removeItem('wikidialog:' + id + ':params'); }   }    var maxIDsKept = 4; // SINGLE POINT TO ADJUST number of active IDs kept function updateActiveList { var id = getWikidialogID; var a = sessionStorage.wikidialogActiveList; if (! a) { // rather than use specialized code here, drop into the general case a = ('' + id); }       a = a.split(','); var s = sessionStorage.wikidialogStack; if (! s) s = ''; // precaution s = s.split('&'); var k;       for (k=0; k0; k--) a[k] = a[k - 1]; a[0] = id; sessionStorage.wikidialogActiveList = a.join(','); maybeCollect(a, s); return; }       if (a.length < maxIDsKept) { sessionStorage.wikidialogActiveList = id + ',' + a.join(','); a[a.length] = id; maybeCollect(a, s); return; }       for (k = a.length - 1; k>0; k--) a[k] = a[k-1]; a[0] = id; sessionStorage.wikidialogActiveList = a.join(','); maybeCollect(a, s); }   function canRollbackSimple { var prevurl = sessionStorage['wikidialog:' + getWikidialogID + ':prevurl']; if (! prevurl) return false; clearRollbackDelegating; var s = prevurl.match(/[\?&]wikidialogid=(\d+)/); if (s && s.length && (s.length > 0)) { // safe because contains an id           return true; }       s = prevurl.match(/[\?&]wikidialogrolledback=/); if (s && s.length && (s.length > 0)) { // hopefully safe because active predecessor, if any, is warned return true; }       // no grounds to claim safety (this shouldn't happen) return false; }   function canRollbackDelegating { var id = getWikidialogID; if (sessionStorage['wikidialog:' + id + ':prevurl']) { clearRollbackDelegating; return false; } else if (sessionStorage['wikidialog:' + id + ':rb-available']) { return true; } else { return false; }   }    window.wikidialog.addNote = addNote; window.wikidialog.clearNotes = clearNotes; window.wikidialog.getNotes = getNotes; window.wikidialog.keepNotes = function { // impending non-manual delegation sessionStorage['wikidialog:' + getWikidialogID + ':keep-notes'] = 'x'; }   window.wikidialog.canRollback = function  { return (canRollbackSimple || canRollbackDelegating); }   window.wikidialog.rollback = function (shortcut, shortcutParam) { window.wikidialog.noSequence; // if we get here at all, don't sequence var id = getWikidialogID; var prevurl = sessionStorage['wikidialog:' + id + ':prevurl']; if (prevurl) { clearRollbackDelegating; clearRollbackSimple; delete window.wikidialog; // precautionary rescript location = prevurl; return true; }       if (! sessionStorage['wikidialog:' + id + ':rb-available']) { return false; // not delegating-rollback either }       //        // incoming; last chance to bail //       var d = sessionStorage['wikidialog:' + id + ':rb-incoming']; if (! d) { // bailing; something's very wrong clearRollbackDelegating; return false; }       sessionStorage['wikidialog:' + id + ':incoming'] = d;        // // unauth //       d = sessionStorage['wikidialog:' + id + ':rb-unauth']; if (! d) { sessionStorage.removeItem('wikidialog:' + id + ':unauth'); } else {    sessionStorage[           'wikidialog:' + id + ':unauth'] = d; } //       // origin //       d = sessionStorage['wikidialog:' + id + ':rb-origin']; if (! d) { sessionStorage.removeItem('wikidialog:' + id + ':origin'); } else {    sessionStorage[           'wikidialog:' + id + ':origin'] = d; } //       // proxy //       d = sessionStorage['wikidialog:' + id + ':rb-proxy']; if (! d) { sessionStorage.removeItem('wikidialog:' + id + ':proxy'); } else {    sessionStorage[           'wikidialog:' + id + ':proxy'] = d; } //       // added //       var ls = sessionStorage['wikidialog:' + id + ':rb-added']; if (! ls) ls = ''; // precaution ls = ls.split(','); d = getData; var k;       for (k = ls.length - 1; k>=0; k--) { sessionStorage.removeItem('wikidialog:' + id + ':in:' + ls[k]); delete d[ls[k]]; }       var s = ''; for (var p in d) { if (s) { s += ','; } s += p;       } sessionStorage['wikidialog:' + id + ':params'] = s;       // // changed //       var ls = sessionStorage['wikidialog:' + id + ':rb-changed']; if (! ls) ls = ''; // precaution ls = ls.split(','); var k;       for (k = ls.length - 1; k>=0; k--) sessionStorage['wikidialog:' + id + ':in:' + ls[k]] = sessionStorage['wikidialog:' + id + ':rb-in:' + ls[k]]; //       // saved //       activateSavedFieldValues('-rb', id); //       // one use only //       clearRollbackDelegating; //       // nothing is new anymore //       sessionStorage['wikidialog:' + id + ':newparams'] = '&'; //       // let it fly //       if (shortcut) { // check not removed, though shortcut now considered required shortcut(shortcutParam); } else { $(window).unbind('unload.wikidialog'); // would erase activated sessionStorage['wikidialog:' + id + ':incoming'] = getStableUrl; delete window.wikidialog; // precautionary rescript location = getStableUrl; }       return true; }   window.wikidialog.pushPrevious = function  { //       // is there a prevurl? //       var id = getWikidialogID; var prevurl = sessionStorage['wikidialog:' + id + ':prevurl']; if (! prevurl) { return 'no previous url to push'; }       clearRollbackDelegating; //       // is prevurl missing an id? //       var previd = prevurl.match(/[\?&]wikidialogid=(\d+)/); if (previd && previd.length && (previd.length > 1)) { previd = previd[1]; } else { return 'no id in previous url'; }       //        // is the stack already full? //       var stack = sessionStorage.wikidialogStack; stack = (stack ? stack.split('&') : []); if (stack.length >= maxIDsKept) { return 'stack already full'; }       //        // add to the stack //       stack[stack.length] = previd; stack[stack.length] = prevurl; stack = stack.join('&'); sessionStorage.wikidialogStack = stack; }   window.wikidialog.popUrl = function  { var stack = sessionStorage.wikidialogStack; stack = (stack ? stack.split('&') : []); if (stack.length <= 0) return false; window.wikidialog.noSequence; // wary diving into unknown situation var prevurl = stack.pop; stack.pop; if (stack.length == 0) { sessionStorage.removeItem('wikidialogStack'); } else { sessionStorage.wikidialogStack = stack.join('&'); }       clearRollbackDelegating; clearRollbackSimple; location = prevurl; return true; }   window.wikidialog.validIncoming = function { if (! sessionStorage) return false; var incoming = sessionStorage['wikidialog:' + getWikidialogID + ':incoming']; if (! incoming) return false; if (incoming == (location.pathname + location.search)) return true; sessionStorage.wikidialogNextID++; return false; }   window.wikidialog.receiveAnonymous = function (callback) { if (! window.wikidialog.validIncoming) return; var id = getWikidialogID; var args = [{origin: sessionStorage['wikidialog:' + id + ':origin'], proxy: sessionStorage['wikidialog:' + id + ':proxy']}]; for (var k = 1; k < arguments.length; k++) args.push(arguments[k]); callback.apply(getData, args); }   window.wikidialog.pageQuery = function (pageName, fields, callback) { //       // fetch subject page info //  at need:     error //  on request:  exists, name, content, timestamp, //               protected, flagged, categories //       var data = { format: 'json', action: 'query', prop:  'revisions', rvprop: 'timestamp', rvlimit: 1, titles: pageName };       if ('flagged'    in fields) data.prop   += '|flagged'; if ('categories' in fields) data.prop  += '|categories'; if ('content'   in fields) data.rvprop += '|content'; if ('protected' in fields) { data.prop += '|info'; data.inprop = 'protection'; }       $.getJSON(            mw.util.wikiScript('api'),            data        ).done(function(data) {            if (! (data.query && data.query.pages))               fields.error = 'page query misfired';            else for (var p in data.query.pages) {                if ('invalid' in data.query.pages[p]){                    fields.error = 'page name invalid';                } else if ('missing' in data.query.pages[p]) {                    if ('exists' in fields) fields.exists = false;                    else fields.error = 'page not found';                } else {                    if ('exists' in fields) fields.exists = true;                    if ('name' in fields) {                        if (data.query.pages[p].title)                            fields.name = data.query.pages[p].title; // normalize                        else fields.error = 'page query misfired';                    }                    if ('content' in fields) {                        if (data.query.pages[p].revisions && data.query.pages[p].revisions[0] && data.query.pages[p].revisions[0]['*'] ) fields.content = data.query.pages[p].revisions[0]['*'];                       else fields.error = 'page query misfired';                    }                    if ('timestamp' in fields) {                        if (data.query.pages[p].revisions && data.query.pages[p].revisions[0] && data.query.pages[p].revisions[0].timestamp ) fields.timestamp = data.query.pages[p].revisions[0].timestamp;                       else fields.error = 'page query misfired';                    }                    if ('protected' in fields) {                        if ('protection' in data.query.pages[p]) {                            if (data.query.pages[p].protection[0] && data.query.pages[p].protection[1]) {                                if (('level' in data.query.pages[p].protection[0]) && ('level' in data.query.pages[p].protection[1]) ) fields.protected = ((data.query.pages[p].protection[0].level == 'sysop') && (data.query.pages[p].protection[1].level == 'sysop'));                               else fields.error = 'page query misfired';                            } else fields.protected = false;                        } else fields.error = 'page query misfired';                    }                    if ('flagged' in fields) {                        if ('flagged' in data.query.pages[p]) {                            if ('pending_since' in data.query.pages[p].flagged)                                fields.flagged = 'pending';                            else fields.flagged = 'current';                        } else fields.flagged = 'never';                    }                    if ('categories' in fields) {                        fields.categories = '';                        if (data.query.pages[p].categories)                            for (var j = (data.query.pages[p].categories.length - 1); j >= 0; j--) if (data.query.pages[p].categories[j].title) fields.categories += '"' + data.query.pages[p].categories[j].title + '" '; else fields.error = 'page query misfired'; }               }            }            callback(fields); }).fail(function { fields.error = 'page query misfired'; callback(fields); });   }    window.wikidialog.checkProtected = function (remotePageName, callbackDone, callbackFail) {        window.wikidialog.pageQuery(remotePageName, { protected: '' }, function (data) { if ('error' in data)    callbackFail(data.error + ': ' + window.wikidialog.safeHtml(remotePageName)); else if (data.protected) callbackDone; else                    callbackFail('page unsecured: ' + window.wikidialog.safeHtml(remotePageName)); });   }    window.wikidialog.pageHistory = function (pageName, fields, callback) {        //        // fetch subject page info        //   revid, timestamp, user, minor, size, comment        //        var data = {            format: 'json',            action: 'query',            prop:   'revisions',            rvprop: 'ids|timestamp|user|flags|size|comment',            rvlimit: 50,            titles:  pageName        };        if (('continue' in fields) && fields['continue']) {            data.rvcontinue = fields.continue;            delete fields.continue;        }        if ('direction' in fields) {            data.rvdir = fields.direction;            delete fields.direction;        }        $.getJSON( mw.util.wikiScript('api'), data ).done(function(data) { if (! (data.query && data.query.pages)) fields.error = 'page query misfired'; else for (var p in data.query.pages) { if ('invalid' in data.query.pages[p]){ fields.error = 'page name invalid'; } else if ('missing' in data.query.pages[p]) { fields.error = 'page not found'; } else if (data.query.pages[p].revisions &&                          data.query.pages[p].revisions[0]) { if (('continue' in data) && ('rvcontinue' in data.continue)) { fields.continue = data.continue.rvcontinue; }                   fields['revid'] = ''; fields['timestamp'] = ''; fields['user'] = ''; fields['minor'] = ''; fields['size'] = ''; fields['comment'] = ''; for (var k=(data.query.pages[p].revisions.length - 1); k >= 0; k--) { if (! data.query.pages[p].revisions[k]) continue; if (fields['revid']) { fields['revid']    = '&' + fields['revid']; fields['timestamp'] = '&' + fields['timestamp']; fields['user']     = '&' + fields['user']; fields['minor']    = '&' + fields['minor']; fields['size']     = '&' + fields['size']; fields['comment']  = '&' + fields['comment']; } else { fields['revid']    = ''; fields['timestamp'] = ''; fields['user']     = ''; fields['minor']    = ''; fields['size']     = ''; fields['comment']  = ''; }                       if (       'revid'     in data.query.pages[p].revisions[k]) { fields['revid']    = data.query.pages[p].revisions[k].revid     + fields['revid']; } if (      'timestamp' in data.query.pages[p].revisions[k]) { fields['timestamp'] = data.query.pages[p].revisions[k].timestamp + fields['timestamp']; } if (      'user'      in data.query.pages[p].revisions[k]) { fields['user']     = data.query.pages[p].revisions[k].user      + fields['user']; } if (      'minor'     in data.query.pages[p].revisions[k]) { fields['minor']    = 'm'                                        + fields['minor']; } if (      'size'      in data.query.pages[p].revisions[k]) { fields['size']     = data.query.pages[p].revisions[k].size      + fields['size']; } if (      'comment'   in data.query.pages[p].revisions[k]) { fields['comment']  = data.query.pages[p].revisions[k].comment   + fields['comment']; } }               } else { fields.error = 'page query misfired'; }           }            callback(fields); }).fail(function { fields.error = 'page query misfired'; callback(fields); });   }    window.wikidialog.categoryMembers = function (pageName, fields, callback) {        //        // fetch category members info        //   title, type, timestamp        //        var data = {            format:  'json',            action:  'query',            list:    'categorymembers',            cmtitle: pageName,            cmprop:  'title|type|timestamp',            cmlimit: 50,        };        if (('continue' in fields) && fields['continue']) {            data.cmcontinue = fields.continue;            delete fields.continue;        }        if ('direction' in fields) {            data.cmdir = fields.direction;            delete fields.direction;        }        if ('type' in fields) {            data.cmtype = fields.type;            delete fields.type;        }        if ('sort' in fields) {            data.cmsort = fields.sort;            delete fields.sort;        } $.getJSON(           mw.util.wikiScript('api'),            data        ).done(function(data) {            if (data.error && data.error.code) {                if (data.error.code == 'cminvalidcategory') fields.error = 'invalid category title';                else if (data.error.code == 'cmbadcontinue') fields.error = 'invalid category-members continue value';                else fields.error = 'category members query misfired';                addNote('Category members query result error code: ' + data.error.code);            } else if (! (data.query && data.query.categorymembers)) {               fields.error = 'category members query misfired';                addNote('Category members query result has no categorymembers element.');            } else {                if (('continue' in data) && ('cmcontinue' in data.continue)) {                    fields.continue = data.continue.cmcontinue;                }                fields['title'] = ;                fields['type'] = ;                fields['timestamp'] = '';                for (var k=(data.query.categorymembers.length - 1); k >= 0; k--) {                    if (! data.query.categorymembers[k]) continue;                   if (fields['title']) {                        fields['title']     = '&' + fields['title'];                        fields['type']      = '&' + fields['type'];                        fields['timestamp'] = '&' + fields['timestamp'];                    } else {                        fields['title']     = ;                        fields['type']      = ;                        fields['timestamp'] = '';                    }                    if (       'title'     in data.query.categorymembers[k])                      { fields['title']     = data.query.categorymembers[k].title     + fields['title']; }                    if (       'type'      in data.query.categorymembers[k])                      { fields['type']      = data.query.categorymembers[k].type      + fields['type']; }                    if (       'timestamp' in data.query.categorymembers[k]) { fields['timestamp'] = data.query.categorymembers[k].timestamp + fields['timestamp']; } }           }            callback(fields); }).fail(function { fields.error = 'category members query misfired'; addNote('Category members query API call failed.'); callback(fields); });   }    window.wikidialog.commit = function  {        clearRollbackSimple;        clearRollbackDelegating;    }    window.wikidialog.proxy = function (remotePageName, remoteProtected, callbackDone, callbackFail) {        stashUnstableUrl;        if ((typeof remoteProtected) != "boolean") {            callbackFail = callbackDone;            callbackDone = remoteProtected;            remoteProtected = false;        }        if (! authenticIncoming) {           registerUnauthenticated(remotePageName);            if (callbackFail) callbackFail('incoming action-request not authenticated');            return false;        }        if (remoteProtected) {            registerAuthentication(remotePageName, callbackDone);        } else {            registerUnauthenticated(remotePageName);            addNote('No outgoing authentication because remote page is not protected.');            if (callbackFail)                callbackFail('remote page not authenticated\n  ' + window.wikidialog.safeHtml(remotePageName));       }    }    window.wikidialog.purelySelfContained = function (callbackDone, callbackFail) {        stashUnstableUrl;        if (! authenticIncoming) {           if (callbackFail) callbackFail('incoming action-request not authenticated');            return false;        }        registerAuthentication(callbackDone);    }    window.wikidialog.recover = function  {        //        // reinstate carried-over field geometries        //        restoreGeometries(getWikidialogID, 'in');        //        // reinstate saved field values        //        restoreSavedFieldValues;        releaseSavedFieldValues;        //        // cache expiry        //        updateActiveList;        //        // register event handler for unload        //        var id = getWikidialogID;        function handleUnload {            //            // expect to leave this id and maybe come back later            // (not suitable for use on forced-reload delegating-rollback)            //            saveFieldValues(id);            if (sessionStorage.wikidialogNextID) { var s = location.search.match(/[\?&]wikidialogid=(\d+)/); if (s && s.length && (s.length > 1)) {} else sessionStorage.wikidialogNextID++; // avoid accidental revisit } else { sessionStorage.wikidialogNextID = (getWikidialogID + 2); }       }        $(window).unbind('unload.wikidialog'); $(window).one('unload.wikidialog', handleUnload); }   function delegateToInternal(withRollback, params, metaproc, shortcut, shortcutParam) { $('input.wikidialog-button, button.wikidialog-button').attr('disabled',true); if (withRollback) { window.wikidialog.commit; // disable any pre-existing rollback // set up rollback-delegating data var id = getWikidialogID; sessionStorage['wikidialog:' + id + ':rb-available'] = 'x'; sessionStorage['wikidialog:' + id + ':rb-incoming'] = sessionStorage['wikidialog:' + id + ':incoming']; if (sessionStorage['wikidialog:' + id + ':unauth']) { sessionStorage['wikidialog:' + id + ':rb-unauth'] = sessionStorage['wikidialog:' + id + ':unauth']; }           if (sessionStorage['wikidialog:' + id + ':origin']) { sessionStorage['wikidialog:' + id + ':rb-origin'] = sessionStorage['wikidialog:' + id + ':origin']; }           if (sessionStorage['wikidialog:' + id + ':proxy']) { sessionStorage['wikidialog:' + id + ':rb-proxy'] = sessionStorage['wikidialog:' + id + ':proxy']; }           saveFieldValues(id, '-rb'); var storedParams = sessionStorage['wikidialog:' + id + ':params']; storedParams = (storedParams ? storedParams.split(',') : []); var added = '';  // parameters that didn't exist previously var changed = ''; // parameters that did exist previously var k;           for (var p in params) { for (k=0; true; k++) { if (k >= storedParams.length) { added += (added ? (',' + p) : p); break; } else if (p == storedParams[k]) { changed += (changed ? (',' + p) : p); sessionStorage[   'wikidialog:' + id + ':rb-in:' + p] = sessionStorage['wikidialog:' + id + ':in:'   + p]; break; }               }            }            sessionStorage['wikidialog:' + id + ':rb-added'  ] = added; sessionStorage['wikidialog:' + id + ':rb-changed'] = changed; } else if (canRollbackSimple) { clearRollbackSimple; // delegating rollback already cleared } else if (canRollbackDelegating) { // augment rollback data var id = getWikidialogID; var storedParams = sessionStorage['wikidialog:' + id + ':params']; storedParams = (storedParams ? storedParams.split(',') : []); var added = sessionStorage['wikidialog:' + id + ':rb-added']; var changed = sessionStorage['wikidialog:' + id + ':rb-changed']; changed = changed.split(','); var k, j;           for (var p in params) { for (k=0; true; k++) { if (k >= storedParams.length) { added += (added ? (',' + p) : p); break; } else if (p == storedParams[k]) { for (j=0; true; j++) { if (j >= changed.length) { changed[changed.length] = p;                               sessionStorage[    'wikidialog:' + id + ':rb-in:' + p] = sessionStorage['wikidialog:' + id + ':in:'   + p]; break; } else if (p == changed[j]) { // value for rollback already stored break; }                       }                        break; }               }            }            sessionStorage['wikidialog:' + id + ':rb-added'] = added; sessionStorage['wikidialog:' + id + ':rb-changed'] = changed.join(','); }       delegateVerified(params, metaproc, shortcut, shortcutParam); }   window.wikidialog.delegateTo = function (shortcut, params, metaproc, shortcutParam) { // clear newparams sessionStorage['wikidialog:' + getWikidialogID + ':newparams'] = '&'; delegateToInternal(false, params, metaproc, shortcut, shortcutParam); }   window.wikidialog.delegateToPreservingNewparams = function (shortcut, params, metaproc, shortcutParam) { // leave newparams alone delegateToInternal(false, params, metaproc, shortcut, shortcutParam); }   window.wikidialog.delegateToSettingNewparams = function (shortcut, params, metaproc, shortcutParam) { var id = getWikidialogID; var x = '&'; for (var p in params) { x += p + '&'; } sessionStorage['wikidialog:' + id + ':newparams'] = x;       delegateToInternal(false, params, metaproc, shortcut, shortcutParam); }   window.wikidialog.delegateToWithRollback = function (shortcut, params, metaproc, shortcutParam) { var id = getWikidialogID; var x = '&'; for (var p in params) { x += p + '&'; } sessionStorage['wikidialog:' + id + ':newparams'] = x;       delegateToInternal(true, params, metaproc, shortcut, shortcutParam); }   window.wikidialog.startSequence = function  { sessionStorage.wikidialogSequenceBound = 10; // POINT TO ADJUST max action-sequence length //  also occurs in gadget sessionStorage.removeItem('wikidialogSequenceOngoing'); // precaution, should be unnecessary }   window.wikidialog.stepSequence = function  { if (sessionStorage.wikidialogSequenceBound) { var n = Number(sessionStorage.wikidialogSequenceBound); if (n > 0) { sessionStorage.wikidialogSequenceBound = (n - 1); }           if (n > 1) { sessionStorage.wikidialogSequenceOngoing = 'x'; }           else { sessionStorage.removeItem('wikidialogSequenceOngoing'); }       }    }    window.wikidialog.noSequence = function (o) { sessionStorage.removeItem('wikidialogSequenceBound'); sessionStorage.removeItem('wikidialogSequenceOngoing'); if (o && (typeof(o) == 'object')) { delete o['ACTION-SEQUENCE-BOUND']; }   }    window.wikidialog.ongoingSequence = function  { return (sessionStorage.wikidialogSequenceOngoing ? true : false); }   window.wikidialog.transclude = function (s) { function disassemble(s) { // break string into array of substrings //  even elements are text other than inclusion directives //  odd elements are inclusion directive labels, sans angle brackets // split keeps the parenthesized part of the delimiter; (?: ... ) is merely grouping return s.split(/<(noinclude|includeonly|onlyinclude|\/noinclude|\/includeonly|\/onlyinclude)(?:\s+[^<>]*)?>/); }       function includeonly(s) { for (var k=1; k<s.length; k+=2) if ((s[k] == 'includeonly') || (s[k] == '/includeonly')) s[k] = ''; return s;       } function hasOnlyinclude(s) { for (var k=1; k<s.length; k+=2) if (s[k] == 'onlyinclude') return true; return false; }       function onlyinclude(s) { var suppressFlag = true; s[0] = ''; for (var k=1; k<s.length; k+=2) { if (suppressFlag) { if (s[k] == 'onlyinclude') suppressFlag = false; else                      s[k+1] = ''; s[k] = ''; } else if (s[k] == '/onlyinclude') { suppressFlag = true; s[k] = ''; s[k+1] = ''; }           }            return s;        } function noinclude(s) { var suppressFlag = false; for (var k=1; k'; s[0] += s[k]; }           return s[0]; }       //        s = includeonly(disassemble(s)); if (hasOnlyinclude(s)) s = onlyinclude(s); s = reassemble(noinclude(s)); return s;   } function makeTparamRgx(name) { // the placement of parentheses here is dictated by substForTparams return new RegExp('(\\{\\{\\{)' + name + '(\\|[^\\|\\{\\}]*)?(\\}\\}\\})'); }   window.wikidialog.substituteTemplateParameters = function (data, s) { //       // substitute data for template parameters in raw wiki markup string s        // safe to substitute arbitrarily because it's raw, provided we encode =[]<>{|} //       function encodeMarkup(raw) { return raw.replace(/\||\=+|<+|>+|\[+|\]+|\{+|\}+/g,               function (s) {                    function rpt(n, t) {                        var s = ;                        while (n > 16) {                            s += ;                            n -= 16;                        }                        s += '';                        return s;                    }                    switch (s[0]) {                      case '=': return rpt(s.length, '==');  // Template:==                      case '[': return rpt(s.length, '(-');  // Template:(-                      case ']': return rpt(s.length, '-)');  // Template:-)                      case '<': return rpt(s.length, '(\\'); // Template:(\                      case '>': return rpt(s.length, '\\)'); // Template:\)                      case '{': return rpt(s.length, '(*');  // Template:(* case '|': return '|';                 // Template:! case '}': return rpt(s.length, '*)'); // Template:*) }               });        }        var d = data;        data = {};        for (var q in d)            if ((typeof d[q]) != "string")                data[q] = (d[q] ? d[q].toString : '');           else                data[q] = d[q];        if (! s) return s;       s = s.split(makeTparamRgx("([^\\{\\|\\}]*)"));        for (var k = 0; (k < s.length); k++)            if ((s[k] == '{{{') & (s[k+1] != '{{{')) {                if (s[k+1] in data) {                    s[k] = ;                    s[k+1] = data[s[k+1]];                    s[k+1] = encodeMarkup(s[k+1]);                    s[k+2] = ;                    s[k+3] = ;                }                k += 3;            }        return s.join();    }    window.wikidialog.substituteParameters = function (pageName, actionParams, requests, content, callback) {        // requests is optional        if ((typeof requests) == "string") {            callback = content;            content = requests;            requests = {};        }        function makeInitRgx(name) {            var maxBracesDepth = 32; // SINGLE POINT TO ADJUST max braces depth in dialog/init calls            var rgx = "\\{[^\\{\\}]*\\}"; for (var j = 1; j <= maxBracesDepth; j++) rgx = "\\{[^\\{\\}]*(?:" + rgx + "[^\\{\\}]*)*\\}"; rgx = "\\{\\{\\s*[Dd]ialog/init\\s*\\|\\s*(" + name + "|\\(\\s*" + name + "(?:\\s+" + name + ")*\\s*\\))\\s*\\|([^\\{\\|\\}]*(?:" + rgx + "[^\\{\\|\\}]*)*)((?:\\|[^\\{\\|\\}\\=]*)?)\\}\\}"; return new RegExp(rgx); // three sets of parentheses here, for the three possible parameters to dialog/init }       function reservedParam(s) { return ((s.search(/[A-Z]/) == 0) && (s.search(/[a-z]/) < 0)); }       function localParam (s) { return (s.search(/local/) == 0); }       function activeParams  { //           // result is ampersand separated and delimited, // so each name on it is ampersand delimited //           var id = getWikidialogID; var result = sessionStorage['wikidialog:' + id + ':newparams']; if (! result) { result = sessionStorage['wikidialog:' + id + ':params']; if (! result) { result = '&'; } else { result = (',' + result + ',').replace(/,+/g, '&'); }           }            return result; }       function paramIsActive(p) { return (activeParams.search('&' + p + '&') >= 0); }       function paramIsTranscluded(p) { var rgx = makeTparamRgx(p); if (typeof content == "string") return (content.search(rgx) >= 0); for (var k = 0; (k < content.length); k++) if (content[k].search(rgx) >= 0) return true; return false; }       function substForTparams(data) { if (typeof content == "string") content = window.wikidialog.substituteTemplateParameters(data, content); else for (var k = 0; (k < content.length); k++) content[k] = window.wikidialog.substituteTemplateParameters(data, content[k]); }       function processInitCalls(pred, callback) { //           // processes dialog/init calls // pred is optional; it's a critierion for possible deferral, so if provided, don't reassemble content when done //           function assignment(definiend, value) { if (definiend.search(/\(/) < 0) { // simple definiend                   actionParams[definiend] = value;                } else { // compound definiend                    definiend = definiend.replace(/\s*[\(\)]\s*/g,"").split(/\s+/);                    value = $.trim(value);                    var rgx1 = '"[^"]*(?:""[^"]*)*"'; // string                    var rgx2 = "\\(\\s*" + rgx1 + "(?:\\s+" + rgx1 + ")*\\s*\\)"; // list                    var vs = value.match(rgx2);                    if (! vs) {                       addNote('dialog/init compound definiend (' + definiend.join(' ') + ') value not well-formed.');                        return;                    }                    value = vs[0];                    vs = value.match(RegExp(rgx1, "g"));                    if (vs.length != definiend.length) {                        addNote('dialog/init compound definiend (' + definiend.join(' ') + ") value length doesn't match.");                        return;                    }                    for (var k=0; k<vs.length; k++)                        if (reservedParam(definiend[k])) {                            addNote('dialog/init prohibited from setting reserved parameter ' + definiend[k] + ' (in compound).');                        } else {                            actionParams[definiend[k]] = vs[k].slice(1, (vs[k].length - 1)).replace(/""/g, '"');                        } }           }            function f(n) { // process first n calls, from nth back to 1st if (n < 1) { callback; return; }               //                // process nth remaining dialog/init call, then recurse //               if (! content[4*n - 3]) { // already processed f(n - 1); return; }               if (! pred(content[4*n - 2])) { // defer processing addNote('dialog/init parameter ' + content[4*n - 3] + ' deferred from early processing.'); f(n - 1); return; }               if (reservedParam(content[4*n - 3])) { // simple reserved (reserved in compounds are detected elsewhere) addNote('dialog/init prohibited from setting reserved parameter ' + content[4*n - 3] + '.'); content[4*n - 3] = ''; if (! content[4*n - 1]) content[4*n - 2] = ''; // leave body for later expansion content[4*n - 1] = ''; f(n - 1); return; }               if (content[4*n - 2].search(/\{\{/) < 0) { // nothing to expand assignment(content[4*n - 3], content[4*n - 2]); content[4*n - 3] = ''; if (! content[4*n - 1]) content[4*n - 2] = ''; // leave body for later expansion content[4*n - 1] = ''; f(n - 1); return; }               $.ajax({                    type: 'POST',                    url:  mw.util.wikiScript('api'),                    data: { format:  'json',                            action:  'expandtemplates',                            text:    content[4*n - 2],                            title:   pageName,                            prop:    'wikitext'                          },                    datatype: 'json'                }).done(function(data) {                    if ((! data.expandtemplates) || (! data.expandtemplates.wikitext))                        assignment(content[4*n - 3], );                    else                        assignment(content[4*n - 3], data.expandtemplates.wikitext);                    content[4*n - 3] = ;                    if (! content[4*n - 1]) content[4*n - 2] = ; // leave body for later expansion                   content[4*n - 1] = ;                    f(n - 1);                }).fail(function  {                    show('Error processing dialog/init call: expand-templates request failed.');                }); }           function makeReassembler(callback) { return (function {                   content = content.join('');                    callback;                }); }           //            // find the calls //           if (typeof content == "string") content = content.split(makeInitRgx("[\\w\\-\\u0080-\\uFFFF]+")); var n = (content.length - 1) / 4; while (n > 8) { // SINGLE POINT TO ADJUST max number of dialog/init calls processed content[4*n - 3] = ''; if (! content[4*n - 1]) content[4*n - 2] = ''; content[4*n - 1] = ''; n--; }           if (! callback) { callback = makeReassembler(pred); pred = (function (s) { return true; }); }           f(n); }       function stepNine { //           // process remaining dialog/init calls, reassemble, and done //           processInitCalls(function  {                callback(content);            }); }       function stepEight { //           // fetch fileinfo if requested //           if (! (   actionParams['file'] && paramIsTranscluded('FILE-INFO-[^\\{\\|\\}]*') && actionParams['local-file-info'])) { stepNine; return; }           addNote('Info requested for file "' + actionParams['file'] + '".'); $.ajax({               type: 'POST',                url:  mw.util.wikiScript('api'),                data: { format:  'json',                        action:  'query',                        titles:  actionParams['file'],                        prop:    'imageinfo',                        iiprop:  (  paramIsTranscluded('FILE-INFO-META-[^\\{\\|\\}]*') ? 'size|extmetadata' : 'size')                     },                datatype: 'json'            }).done(function(data) {                if (data.query && data.query.pages) {                    var fields = {};                    for (var p in data.query.pages) {                        var ii = data.query.pages[p].imageinfo;                        if (ii && ii[0]) {                            if (ii[0]['size'  ]) fields['FILE-INFO-SIZE'  ] = ii[0]['size'  ];                            if (ii[0]['width' ]) fields['FILE-INFO-WIDTH' ] = ii[0]['width' ];                            if (ii[0]['height']) fields['FILE-INFO-HEIGHT'] = ii[0]['height'];                            var emd = ii[0]['extmetadata'];                            if (emd) for (var q in emd) {                                if (emd[q]['value'])                                    fields['FILE-INFO-META-' + q.toUpperCase] = emd[q]['value']; }                       }                    }                    substForTparams(fields); addNote('Info provided for file "' + actionParams['file'] + '".'); } else { addNote('Failed info retrieval for file "' + actionParams['file'] + '".'); }               stepNine; }).fail(function { show('Error processing dialog request: imageinfo request failed.'); });       }        function stepSeven {            //            // fetch expanded text if requested            //            if (! (  paramIsTranscluded('EXPANDED-TEXT')                   && actionParams['local-text-to-expand'])) {                stepEight;                return;            }            $.ajax({ type: 'POST', url: mw.util.wikiScript('api'), data: { format: 'json', action: 'expandtemplates', text:   actionParams['local-text-to-expand'], title:  pageName, prop:   'wikitext' },               datatype: 'json' }).done(function(data) { if ((data.expandtemplates) && (data.expandtemplates.wikitext)) substForTparams({ 'EXPANDED-TEXT': data.expandtemplates.wikitext }); stepEight; }).fail(function { show('Error processing dialog request: expand-templates request failed.'); });       }        function stepSix {            //            // fetch category members if requested            //            if (! (  actionParams['category']                   && paramIsTranscluded('CATEGORY-MEMBERS-[^\\{\\|\\}]*')                   && actionParams['local-category-members'])) {                stepSeven;                return;            }            var fields = {};            if (actionParams['local-category-members-continue' ]) fields.continue  = actionParams['local-category-members-continue'];            if (actionParams['local-category-members-direction']) fields.direction = actionParams['local-category-members-direction'];            if (actionParams['local-category-members-type'     ]) fields.type      = actionParams['local-category-members-type'];            if (actionParams['local-category-members-sort'     ]) fields.sort      = actionParams['local-category-members-sort'];            window.wikidialog.categoryMembers(actionParams['category'], fields, function (result) { var data = {}; for (var p in result) { data       ['CATEGORY-MEMBERS-' + p.toUpperCase] = result[p]; actionParams['CATEGORY-MEMBERS-' + p.toUpperCase] = result[p]; }                   substForTparams(data); stepSeven; });       }        function stepFive {            //            // fetch page history if requested            //            if (! (  actionParams['subject']                   && paramIsTranscluded('SUBJECT-HISTORY-[^\\{\\|\\}]*')                   && actionParams['local-subject-history'])) {                stepSix;                return;            }            var fields = {};            if (actionParams['local-subject-history-continue' ]) fields.continue  = actionParams['local-subject-history-continue'];            if (actionParams['local-subject-history-direction']) fields.direction = actionParams['local-subject-history-direction'];            window.wikidialog.pageHistory(actionParams['subject'], fields, function (result) { var data = {}; for (var p in result) { data       ['SUBJECT-HISTORY-' + p.toUpperCase] = result[p]; actionParams['SUBJECT-HISTORY-' + p.toUpperCase] = result[p]; }                   substForTparams(data); stepSix; });       }        function stepFour {            //            // process first round of dialog/init calls            //            processInitCalls((function (s) {                    return (   (s.search(makeTparamRgx('SUBJECT-HISTORY-[^\\{\\|\\}]*')) < 0) && (s.search(makeTparamRgx('CATEGORY-MEMBERS-[^\\{\\|\\}]*')) < 0) && (s.search(makeTparamRgx('EXPANDED-TEXT')) < 0));               }), stepFive);        }        function stepThree {            //            // substitute for most template parameters, excluding complicated            // query results controled by local parameter via dialog/init            //            substForTparams(actionParams)            stepFour;        }        function stepTwo {            //            // fetch preload page if named and called for            //            if (! ('PRELOAD-PAGENAME' in actionParams)) {               stepThree;                return;            }            if (! (paramIsTranscluded("PRELOAD-CONTENT"))) {               stepThree;                return;            }            window.wikidialog.pageQuery( actionParams['PRELOAD-PAGENAME'], { content: '' }, function (fields) { if ('error' in fields) { stepThree; return; }                   actionParams['PRELOAD-CONTENT'] = window.wikidialog.transclude(fields.content); stepThree; });       }        function stepOne {            //            // remove reserved and local parameters            //            var subtractParams = {};            for (var p in actionParams) if (reservedParam(p) || localParam(p)) {                subtractParams[p] = actionParams[p];            }            for (var p in subtractParams) {                delete actionParams[p];            }            //            // prep request/authentication parameters            //            var id = getWikidialogID;            var origin = sessionStorage['wikidialog:' + id + ':origin'];            if (origin) {                actionParams['INCOMING-AUTHENTICATED'] = origin;                actionParams['REQUESTING-PAGE'] = origin;            }            else {                var unauth = sessionStorage['wikidialog:' + id + ':unauth'];                if (unauth) actionParams['REQUESTING-PAGE'] = unauth; }           actionParams['ACTIVE-PARAMETERS'] = activeParams; //           // prep user name/groups parameters //           var un = mw.config.get('wgUserName'); actionParams['USERNAME'] = (!un ? "" : un); var ug = mw.config.get('wgUserGroups'); actionParams['USER-GROUPS'] = (!ug ? "" : ug.join(" ")); //           // prep version parameters //           if (window.wikidialog.gadgetVersion) { actionParams['DIALOG-GADGET-VERSION'] = window.wikidialog.gadgetVersion; }           actionParams['DIALOG-RECEIVE-VERSION'] = receiveVersion; //           // prep stack-depth parameter //           var stack = sessionStorage.wikidialogStack; if (stack) { actionParams['STACK-DEPTH'] = '' + (stack.split('&').length / 2); }           //            // prep action-dependent parameters //           for (var p in requests) if (reservedParam(p)) { actionParams[p] = requests[p]; }           //            // prep sequence parameter //           if (sessionStorage.wikidialogSequenceBound) { actionParams['ACTION-SEQUENCE-BOUND'] = sessionStorage.wikidialogSequenceBound; }           //            // fetch subject page info unless there's no subject //           if (! ('subject' in actionParams)) { stepTwo; return; }           var fields = { name: , exists:  }; for (var p in requests) fields[p] = ''; if (paramIsTranscluded("SUBJECT-CONTENT"))   fields.content = ''; if (paramIsTranscluded("SUBJECT-TIMESTAMP")) fields.timestamp = ''; if (paramIsTranscluded("SUBJECT-CATEGORIES")) fields.categories = ''; if (paramIsTranscluded("SUBJECT-FLAGGED"))   fields.flagged = ''; window.wikidialog.pageQuery(actionParams.subject, fields, function (fields) {               if ('error' in fields) {                    stepTwo;                    return;                }                if (('exists' in fields) && (! fields.exists)) {                    actionParams['SUBJECT-EXISTS'] = 'false';                    stepTwo;                    return;                }                actionParams['SUBJECT-EXISTS'] = 'true';                actionParams.subject = fields.name; // normalize                if ('content' in fields)    actionParams['SUBJECT-CONTENT']    = fields.content;                if ('timestamp' in fields)  actionParams['SUBJECT-TIMESTAMP']  = fields.timestamp;                if ('categories' in fields) actionParams['SUBJECT-CATEGORIES'] = fields.categories;                if ('flagged' in fields)    actionParams['SUBJECT-FLAGGED']    = fields.flagged; stepTwo; });       }        stepOne;    } });