MediaWiki:Common.js/w/Wikibooks:Dialog/do
Appearance
| This is the JavaScript for all users. You can propose changes on the discussion page or at the proposals reading room. Errors made here can disrupt Wikibooks. You can test changes in your personal JavaScript first. Due to caching, changes can take up to 31 days before propagating to all users. |
Note: After publishing, you may have to bypass your browser's cache to see the changes.
- Mozilla / Firefox / Safari: hold down Shift while clicking Reload, or press Ctrl-Shift-R (Cmd-Shift-R on Apple Mac);
- Internet Explorer: hold Ctrl while clicking Refresh, or press Ctrl-F5;
- Konqueror: simply click the Reload button, or press F5;
- Opera users may need to completely clear their cache in Tools→Preferences.
/* For [[{{evalx|(get-substring (get-arg 3) (+ 1 (length (get-arg 2))))|{{dialog/js prefix}}|{{PAGENAME}}}}]]. See [[Special:WhatLinksHere/{{#titleparts:{{PAGENAME}}||2}}]]. [[Category:Dialog javascript pages|do]] */
function reservedParams(pagename, delegatedData) { var r = { 'DIALOG-DO-VERSION': '0.39 (2019-10-12)' };
if (pagename) {
r['PRELOAD-PAGENAME'] = pagename + '/preload';
}
if (delegatedData) for (var p in delegatedData)
if ((p.search(/[A-Z]/) == 0) && (p.search(/[a-z]/) < 0)) {
r[p] = delegatedData[p];
}
return r;
}
function wikidialogShow(callback) {
if (('wikidialog' in window) && ('show' in window.wikidialog)) {
window.wikidialog.show();
if (callback) callback();
}
else $.getScript( // [[MediaWiki:Gadget-wikidialog.js]]
mw.config.get('wgScript') + '?title=' + mw.util.wikiUrlencode('MediaWiki:Gadget-wikidialog.js') +
'&action=raw&ctype=text/javascript',
function () {
if (callback) callback();
}
);
}
function primaryVerb(delegatedData) {
function getQueryParams(q) {
function decode(s) {
function f(c) {
if (c < 64) return (c - 48);
if (c < 96) return (c - 55);
return (c - 87);
}
return s.replace(/%[a-fA-F0-9][a-fA-F0-9]/g,function(s) {
return String.fromCharCode((f(s.charCodeAt(1)) * 16) +
f(s.charCodeAt(2)));
});
};
if (! q) { q = location.search.substring(1); }
else if (q.search(/\?/) >= 0) { q = q.substring(q.search(/\?/) + 1); }
q = q.split(/[&]/);
var result = {};
for (var k=0; k<q.length; k++) {
var j = q[k].search('=');
if (j > 0) result[decode(q[k].substring(0,j))] = decode(q[k].substring(j+1));
}
return result;
}
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 idSelector(s) {
s = s.replace( /\./g, '\\.' );
return 'input#wikidialog-' + s + ', textarea#wikidialog-' + s + ', select#wikidialog-' + s;
}
function fieldSelector(s) {
var sa = anchorEncode(s);
if (sa == s) {
return idSelector(s);
} else {
return idSelector(s) + ', ' + idSelector(sa);
}
}
function getButtonParams(button, data, fixed) { // button is a jquery object of length 1
var wikidialogButtonData = (data ? data : button.data('wikidialogButtonData'));
var params = {};
for (var j = 0; j < wikidialogButtonData.length; j++) {
var d = wikidialogButtonData[j].match(/[\w\-\u0080-\uFFFF]+/g); // STUFF ALLOWED IN FIELD NAMES
d[1] = (d[1] ? d[1] : d[0]);
d[1] = $(fieldSelector(d[1]));
if (d[1].length == 0) {
} else {
var elt = d[1].first();
d[1] = d[1].add(button);
for (var k = 0; k < d[1].length; k++) {
if ( $(d[1][k]).hasClass('wikidialog-button')
|| $(d[1][k]).hasClass('wikidialog-link')) {
k++;
if (k < d[1].length) elt = $(d[1][k]);
break;
}
}
switch (elt.attr('type')) {
case 'checkbox':
d[1] = (elt[0].checked ? 'yes' : '');
break;
default:
d[1] = elt.val();
break;
}
params[d[0]] = d[1];
}
}
if (fixed) for (var p in fixed) { params[p] = fixed[p]; }
return params;
}
function getButtonCarryovers(button) { // button is a jquery object of length 1
var wikidialogButtonData = button.data('wikidialogButtonData');
var carryovers = [];
for (var j = 0; j < wikidialogButtonData.length; j++) {
var d = wikidialogButtonData[j].match(/[\w\-\u0080-\uFFFF]+/g); // STUFF ALLOWED IN FIELD NAMES
if (d[1]) {} else { carryovers[carryovers.length] = d[0]; }
}
return carryovers;
}
function getButtonMetadata(button) { // button is a jquery object of length 1
var wikidialogButtonData = button.data('wikidialogButtonData');
var carryovers = getButtonCarryovers(button);
return {
unauth: (('unauth' in wikidialogButtonData) ? wikidialogButtonData.unauth : mw.config.get('wgPageName')),
origin: (('origin' in wikidialogButtonData) ? wikidialogButtonData.origin : ''),
proxy: (('proxy' in wikidialogButtonData) ? wikidialogButtonData.proxy : ''),
carry: carryovers
};
}
function showHere(content, maybeStopButton) {
if (maybeStopButton) {
if (window.wikidialog.ongoingSequence()) {
content = '<div align="center"><span class="wikidialog-stop-sequence">STOP SEQUENCE</span></div>' + content;
}
} else { // if the sequence can't be stopped, it shouldn't exist
window.wikidialog.noSequence();
}
$('div.wikidialog-do').replaceWith('<div class="wikidialog-do wikidialog-rewritten">' + content + '</div>');
$('span.wikidialog-stop-sequence').replaceWith(function () {
function handleStopButton(event) {
$('button.wikidialog-stop-sequence').attr('disabled',true);
window.wikidialog.noSequence();
}
var t = $(this).text();
return $(document.createElement('button')).attr('type','button').addClass(this.className).html(t).attr('title',t).click(handleStopButton);
});
}
function stripHtml(s) {
return s.replace(/<[^<>]*>/g, '');
}
function convertLocalParams(actionParams, prefix) {
var result = {};
for (var p in actionParams)
if (p.search(/local/) == 0)
result[prefix + '-' + p.toUpperCase()] = actionParams[p];
return result;
}
function defaultErrorPanel(message, actionParams) {
function handleWriteData(event) {
function showStarted() { $('button.wikidialog-error-write').attr('disabled',true); }
function showSucceeded() { $('li.wikidialog-error-offer-write').replaceWith(''); }
function showFailed() { $('button.wikidialog-error-write').attr('disabled',false); }
function errorWriteStepTwo(newContent, pageName, oldContent) {
//
// check the data isn't already there
// ask the user to confirm
// write
//
if (oldContent.indexOf(newContent) >= 0) {
alert('The data to be written appears to be\nalready present on your user talk page');
showFailed();
return;
}
if (! confirm('Save dialog data to user talk page?')) {
showFailed();
return;
}
var section = ('[[Help:Dialog|Dialog]] data (saved on error by action [[' + mw.config.get('wgPageName') + '|do]])');
var apidata = { format: 'json',
action: 'edit',
text: newContent,
title: pageName,
section: 'new',
sectiontitle: section,
summary: ('/* ' + section + ' */ new section'),
};
apidata.token = mw.user.tokens.get('csrfToken'); // always the last field added
$.ajax({
type: 'POST',
url: mw.util.wikiScript('api'),
data: apidata,
datatype: 'json'
}).done(function(data) {
if (data && data.edit && data.edit.result && (data.edit.result == 'Success')) {
alert('Dialog data saved');
showSucceeded();
} else if (data && data.error) {
alert('Dialog data save error "' + data.error.code + '"');
showFailed();
} else {
alert('Dialog data save unknown error');
showFailed();
}
}).fail(function () {
alert('Dialog data save misfired');
showFailed();
});
}
function errorWriteStepOne() {
//
// figure what to write
// figure where to write
// query what's already there
//
showStarted();
var s = '';
for (var p in actionParams) {
if (s) { s += '\n----\n----\n'; }
if (actionParams[p]) {
s += p + '\n----\n' + actionParams[p];
} else {
s += p;
}
}
var userName = mw.config.get('wgUserName');
if (! userName) { // should prevent the button from being created, but check here anyway
alert('You have to be logged in to write the data');
showFailed();
return;
}
var pageName = 'User talk:' + userName;
window.wikidialog.pageQuery(
pageName,
{ exists: '', name: '', content: '' },
function (data) {
if ('error' in data) {
alert('write failed\n' + data.error);
showFailed();
return;
}
errorWriteStepTwo(s, pageName, (data.exists ? data.content : ''));
});
}
errorWriteStepOne();
}
//
// look for id in url
//
var idInUrl = ('wikidialogid' in getQueryParams());
//
// text
//
if (! idInUrl) { message = stripHtml(message); }
var s = '<big><b>' + message + '</b></big>\n<p>Options from here:\n<ul>\n';
if (idInUrl) {
s += "<li>To retry the action that has failed, click this link: " +
'<b><a href="' + location + '">retry</a></b>.</li>\n';
} else {
s += '<li>This url is unstable; if you need to save your data, ' +
'save it before doing anything else from here.\n<ul>\n';
}
s += '<li>Your surviving data is listed below; ' +
'you could copy-and-paste it to somewhere.</li>\n';
if (mw.config.get('wgUserName')) { s +=
'<li class="wikidialog-error-offer-write">' +
"As an on-wiki alternative, here's a button to write the data to your user talk page: " +
'<span class="wikidialog-error-write">x</span>.</li>\n';
}
if (! idInUrl) {
s += '</ul>\n</li>\n<li><b>If</b> the failed action was the first at this url, ' +
'you can retry it by clicking this link: <a href="' +
location + '">retry</a>.</li>';
}
s += '<li>You may be able to recover additional dialog data through the <a href="' +
mw.util.getUrl(mw.config.get('wgSiteName') + ':Dialog/diagnostic panel') +
'">diagnostic panel</a>. The data set shown below might not be listed on the ' +
"panel, though it should be accessible using the panel's expert mode.</li>\n</ul></p>";
for (var p in actionParams) {
if (actionParams[p]) {
s += '\n<hr></hr>\n<p><b>' + p + ':</b></p>\n<p><code>' +
window.wikidialog.safeHtml(actionParams[p]) + '</code></p>';
} else {
s += '\n<hr></hr>\n<p><b>' + p + '</b></p>';
}
}
//
// display
//
showHere(s);
$('.wikidialog-error-write').replaceWith(function () {
return $(document.createElement('button')).attr('type','button')
.addClass('wikidialog-error-write').html('write')
.attr('title','write').click(handleWriteData);
});
}
//
// user: deliberate decision by user
// soft: perhaps a dialog misdesign
// hard: seems to be an API failure
// reset: loss of session data
//
var actionNoconfirmCondition = 'user&action no-confirm error';
var viewParseCondition = 'hard&view parse failure';
var viewMissingCondition = 'soft&view missing error';
var editAuthCondition = 'soft&edit authorization error';
var editFailureCondition = 'soft&edit failure';
var editSessionCondition = 'reset&edit session failure';
var editContentCondition = 'hard&edit form content failure';
var editControlCondition = 'hard&edit form control failure';
var editStatusCondition = 'soft&edit page-status error';
var editFormCondition = 'hard&edit form failure';
var editExistCondition = 'hard&edit existence failure';
var editSpecCondition = 'soft&edit spec error';
var editProtectCondition = 'soft&edit form protection error';
//
function handleCondition(message, actionParams, handling, mayOmitReload) {
function reservedParam(s) {
return ((s.search(/[A-Z]/) == 0) && (s.search(/[a-z]/) < 0));
}
function localParam(s) {
return (s.search(/local/) == 0);
}
function filterParams() {
var result = {};
for (var p in actionParams) if (! (reservedParam(p) || localParam(p))) {
result[p] = actionParams[p];
}
return result;
}
//
// filter params (precaution)
//
actionParams = filterParams();
//
// rollback if possible
//
if (window.wikidialog.canRollback()) {
alert(stripHtml(message));
var shortcutParams = convertLocalParams(actionParams, 'ROLLBACK');
if (handling) {
handling = handling.split(/[&]/);
shortcutParams['ROLLBACK-CLASS'] = handling[0];
shortcutParams['ROLLBACK-CONDITION'] = handling[1];
}
if (mayOmitReload ? window.wikidialog.rollback(primaryVerb, shortcutParams)
: window.wikidialog.rollback())
return;
}
//
// fall through
//
defaultErrorPanel(message, actionParams);
}
function confirmAction(parsedContent, actionName, actionDescription, pageDescription,
actionParams, callback) {
//
// assumes template already detected in raw content
//
var p = new RegExp('<span class="wikidialog-confirm-' + actionName +
'"( style="display:none;?")?>[^<>]*<\\/span>', 'g');
var m = parsedContent.match(p);
if (m && (m.length > 0)) {
for (var k=0; k<m.length; k++) { m[k] = m[k].split(/[<>]/)[2]; }
var m2 = []; // remove duplicates
for (var k=0; k<m.length; k++) {
var k2 = 0;
while ((k2 < m2.length) && (m2[k2] != m[k])) k2++;
if (k2 == m2.length) { m2[k2] = m[k]; }
}
m = m2; // duplicates removed
m = ((m.length == 1) ? m[0] :
("Something's wrong; the " + pageDescription + " is reporting " +
'multiple confirmation questions:\n' + m.join(' ; ') +
'\n\nProceed to ' + actionDescription + '?'));
if (! window.wikidialog.canRollback()) {
m += "\n[note: cancel from here is just an error," +
"\n as I don't know how to get back to the preceding page from here]";
}
if (! confirm(m)) {
handleCondition('You have chosen not to proceed with this dialog action',
actionParams, actionNoconfirmCondition, true);
return;
}
parsedContent.replace(p, '');
} else {
window.wikidialog.addNote("Confirmation template detected, but no request in expanded " +
pageDescription + ".");
}
callback();
}
function doView(actionParams) {
function makeDelegatingButtonHandler(target) { // don't install unless wikidialogButtonData.action == 'do'
// in some browsers, event target may be a copy lacking the data
return function (event) {
if (target.hasClass('wikidialog-sequence-next')) {
window.wikidialog.stepSequence();
} else {
window.wikidialog.startSequence();
}
window.wikidialog.delegateToWithRollback(
primaryVerb,
getButtonParams(target),
function (metadata) { return getButtonMetadata(target); },
convertLocalParams(actionParams, 'INCOMING'));
};
}
function viewStepSeven(dialogPage, dialogProtected) {
//
// customize page display
//
$('h1.firstHeading').html(dialogPage + ' <span style="font-size:small">(via <a href="' +
mw.util.wikiScript('index') + '?title=' + mw.config.get('wgPageName') + '">do</a>)</span>');
$('li#ca-talk').css("display", "none");
var dialogPageEncode = mw.util.wikiUrlencode(dialogPage);
$("li[id^='ca-']").each(function () {
var n = $(this);
n.html(n.html().replace(/"\/wiki\/((?:Special:\w+\/)?)[^"]+"/, '"/wiki/$1' + dialogPageEncode + '"')
.replace(/\?title\=[^&]+&/, '?title=' + dialogPageEncode + '&'));
});
$("li[id^='ca-nstab-']").each(function () {
var n = $(this);
n.html(n.html().replace(/ the \w+ page/, " the dialog page").replace(/>[\w\s]*age<\//, '>Dialog page<\/'));
});
$('a').each(function () {
var n = $(this);
var href = n.attr('href');
if (href && (href.search(/\?/) >= 0)
&& (href.search(mw.config.get('wgSiteName') + ':Dialog\/do') >= 0)
&& (href.search(/[\?&]verb\=/) >= 0)
&& (href.search(/[\?&]dialog-confirm\=/) < 0)) {
var queryParams = getQueryParams(href);
var buttonData = [];
if ('FIELDS' in queryParams) {
buttonData = queryParams.FIELDS.split(/,/);
delete queryParams.FIELDS;
}
n.addClass('wikidialog-link');
n.click(function () {
window.wikidialog.delegateToWithRollback(
primaryVerb,
getButtonParams(n, buttonData, queryParams),
function (metadata) { return { unauth: actionParams.page }; },
convertLocalParams(actionParams, 'INCOMING'));
return false;
});
}
});
//
// subst for dialog field values, now that the fields have been set up
//
$('input.wikidialog-text, textarea.wikidialog-textarea').each(function () {
var n = $(this);
var p = n.attr('id');
if (p && (p.substr(0,11) == 'wikidialog-')) {
p = p.substr(11);
if (p in actionParams) {
n.val(actionParams[p]);
}
}
});
$('input.wikidialog-checkbox').each(function () {
var n = $(this);
var p = n.attr('id');
if (p && (p.substr(0,11) == 'wikidialog-')) {
p = p.substr(11);
if (p in actionParams) {
if (actionParams[p]) n.attr('checked','yes');
else n.prop('checked', false);
}
}
});
$('select.wikidialog-select').each(function () {
var n = $(this);
var p = n.attr('id');
if (p && (p.substr(0,11) == 'wikidialog-')) {
p = p.substr(11);
if (p in actionParams)
for (var k=0; k<this.length; k++)
if (this[k].value == actionParams[p]) {
this.selectedIndex = k;
break;
}
}
});
//
// check for saved field values
//
window.wikidialog.recover();
//
// declare page dependencies
//
window.wikidialog.proxy(dialogPage, dialogProtected);
//
// enable button delegation
//
$('input.wikidialog-delegable, button.wikidialog-delegable').each(function () {
var n = $(this);
if (n.data('wikidialogButtonData').action == 'do')
n.unbind('click').click(makeDelegatingButtonHandler(n));
});
//
// check for local-error
//
if (('local-error' in actionParams) && (actionParams['local-error'])) {
if ((dialogPage.length < 5) || (dialogPage.substring(dialogPage.length - 5) != 'error')) {
$('input.wikidialog-button, button.wikidialog-button').attr('disabled',true); // disable while checking
window.wikidialog.pageQuery((dialogPage + '/error'), { name: '' }, function (data) {
$('input.wikidialog-button, button.wikidialog-button').attr('disabled',false);
if ('error' in data) return;
actionParams.page = data.name;
window.wikidialog.keepNotes();
window.wikidialog.delegateToPreservingNewparams(primaryVerb, actionParams,
function (metadata) {
if ((! dialogProtected) && (metadata.origin)) {
return { unauth: metadata.origin };
} else {
return metadata;
}
},
convertLocalParams(actionParams, 'INCOMING'));
});
return;
}
}
//
// preview
//
$('.wikidialog-preview .wikidialog-button').filter('input, button').filter(':not(.wikidialog-live)')
.removeClass('wikidialog-button').attr('disabled',true);
$('.wikidialog-preview input.wikidialog-sequence-next').removeClass('wikidialog-sequence-next');
$('.wikidialog-preview button.wikidialog-sequence-next').removeClass('wikidialog-sequence-next');
//
// anchor
//
if (('anchor' in actionParams) && actionParams.anchor) {
location = ('#' + actionParams.anchor);
}
//
// sequencing
//
if (('ACTION-SEQUENCE-BOUND' in actionParams) && (actionParams['ACTION-SEQUENCE-BOUND'])) {
if (Number(actionParams['ACTION-SEQUENCE-BOUND']) <= 0) {
window.wikidialog.addNote('Action-sequence expired; remaining bound is <= 0.');
window.wikidialog.noSequence(actionParams);
} else if ((dialogPage.length >= 5) && (dialogPage.substring(dialogPage.length - 5) == 'error')) {
window.wikidialog.addNote('Action-sequence feature disabled due to page name.');
window.wikidialog.noSequence(actionParams);
} else if (! (('local-sequence' in actionParams) && (actionParams['local-sequence']))) {
window.wikidialog.addNote('Action-sequence feature disabled due to lack of local-sequence parameter.');
window.wikidialog.noSequence(actionParams);
} else {
var button = $('input.wikidialog-sequence-next, button.wikidialog-sequence-next');
if (button.length != 1) {
if (button.length > 1) {
alert("you'll have to proceed manually from here\n" +
"(an action sequence was detected, but this\n" +
" page has ambiguous sequence directions)");
window.wikidialog.addNote('Action-sequence canceled due to multiple sequence buttons.');
} else {
window.wikidialog.addNote('Action-sequence canceled due to lack of a sequence button.');
}
window.wikidialog.noSequence(actionParams);
} else if (! button.hasClass('wikidialog-delegable')) {
window.wikidialog.addNote("Action-sequence canceled because sequence button isn't marked delegable.");
window.wikidialog.noSequence(actionParams);
} else {
metadata = getButtonMetadata(button);
if (! (('origin' in metadata) && metadata.origin)) {
window.wikidialog.addNote('Action-sequence canceled due to lack of outgoing authentication.');
window.wikidialog.noSequence(actionParams);
} else {
window.wikidialog.keepNotes();
button.click();
}
}
}
if (! window.wikidialog.ongoingSequence())
$('.wikidialog-stop-sequence').replaceWith('');
}
//
// notes
//
var notes = window.wikidialog.getNotes();
$('span.wikidialog-notes').html(notes ? notes : "");
}
function viewStepSix(dialogPage, content, dialogProtected) {
//
// put it on the page
//
showHere(content, true);
//
// set up the dialog fields
//
wikidialogShow(function () {
viewStepSeven(dialogPage, dialogProtected);
});
}
function viewStepFive(dialogPage, content, dialogProtected) {
//
// commit
//
window.wikidialog.commit();
//
// check for [[Template:Dialog/preview|preview]]
//
var p = /<span class="wikidialog-preview"><preview(-live)?><\/span>/g;
if ((! ('preview' in actionParams)) || (content.search(p) < 0)) {
viewStepSix(dialogPage, content, dialogProtected);
return;
}
//
// parse preview
//
var previewPage = dialogPage;
if (('subject' in actionParams) && actionParams.subject) previewPage = actionParams.subject;
$.ajax({
type: 'POST',
url: mw.util.wikiScript('api'),
data: { format: 'json',
action: 'parse',
text: actionParams.preview,
title: previewPage,
prop: 'text'
},
datatype: 'json'
}).done(function(data) {
var preview;
var emsg = '';
if (data.error) {
if (data.error.info) emsg = data.error.info
else emsg = data.error.code;
} else if (data.parse && data.parse.text && data.parse.text['*'])
preview = data.parse.text['*'];
else emsg = 'parse request misfired';
if (emsg) {
window.wikidialog.addNote('Preview not parsed: ' + emsg + '.');
viewStepSix(dialogPage, content, dialogProtected);
return;
}
//
// substitute for whitelisted dialog parameters
//
if ('local-preview-parameters' in actionParams) {
var lpp = actionParams['local-preview-parameters'].split(/[&]/);
var wdp = {};
for (var k=0; k<lpp.length; k++)
if (lpp[k] && (lpp[k] in actionParams))
wdp[lpp[k]] = actionParams[lpp[k]];
preview = window.wikidialog.substituteTemplateParameters(wdp, preview);
}
//
// insert preview
//
content = content.replace(p,function (pat, opt) {
return '<div' + (opt ? '' : ' class="wikidialog-preview"') + '>' + preview + '</div>';
});
viewStepSix(dialogPage, content, dialogProtected);
}).fail(function () {
window.wikidialog.addNote('Preview parse failed.');
viewStepSix(dialogPage, content, dialogProtected);
});
}
function viewStepFour(dialogPage, content, dialogProtected, requestConfirm) {
//
// pop
//
if (actionParams['local-pop']
&& (actionParams[actionParams['local-pop']])
&& dialogProtected) {
if (window.wikidialog.popUrl()) return;
}
//
// push
//
if (actionParams['local-push']
&& (actionParams[actionParams['local-push']])
&& dialogProtected
&& window.wikidialog.canRollback()) {
var emsg = window.wikidialog.pushPrevious();
if (typeof(delegatedData) == 'string') { delegatedData = {}; }
if (emsg) {
delegatedData['INCOMING-PUSH-ERROR'] = emsg;
} else {
delegatedData['INCOMING-PUSH'] = 'done';
}
actionParams[actionParams['local-push']] = '';
window.wikidialog.delegateToPreservingNewparams(
primaryVerb,
actionParams,
function (metadata) { return metadata; },
delegatedData);
return;
}
//
// confirm
//
if (requestConfirm)
confirmAction(content, 'view', 'the destination page', 'destination page',
actionParams, function () {
viewStepFive(dialogPage, content, dialogProtected);
});
else viewStepFive(dialogPage, content, dialogProtected);
}
function viewStepThree(dialogPage, content, dialogProtected) {
//
// detect requestConfirm based on unexpanded content
//
var requestConfirm = false;
if (content.search(/\{\{\s*[Dd]ialog\/confirm view\s*(\}|\|)/) >= 0) {
if (dialogProtected) {
requestConfirm = true;
} else {
window.wikidialog.addNote("View confirmation template detected, but page isn't protected.");
}
}
//
// parse
//
$.ajax({
type: 'POST',
url: mw.util.wikiScript('api'),
data: { format: 'json',
action: 'parse',
text: content,
title: dialogPage,
prop: 'text'
},
datatype: 'json'
}).done(function(data) {
var emsg = '';
if (data.error) {
if (data.error.info) emsg = data.error.info
else emsg = data.error.code;
} else if (data.parse && data.parse.text && data.parse.text['*'])
content = data.parse.text['*'];
else emsg = 'parse request misfired';
if (emsg) {
handleCondition('Error parsing page <a href="' + mw.util.getUrl(dialogPage) + '">' +
window.wikidialog.safeHtml(dialogPage) + '</a>: ' + emsg,
actionParams, viewParseCondition, true);
return;
}
viewStepFour(dialogPage, content, dialogProtected, requestConfirm);
}).fail(function () {
handleCondition('Page parse failed: <a href="' + mw.util.getUrl(dialogPage) + '">' +
window.wikidialog.safeHtml(dialogPage) + '</a>.',
actionParams, viewParseCondition, true);
});
}
function viewStepTwo(dialogPage, content, dialogProtected) {
window.wikidialog.substituteParameters(
dialogPage,
actionParams,
reservedParams(dialogPage, delegatedData),
content,
function (content) {
viewStepThree(dialogPage, content, dialogProtected);
});
}
function viewStepOne(dialogPage) {
//
// fetch page content
//
window.wikidialog.pageQuery(dialogPage, { name: '', content: '', protected: '' }, function (data) {
if ('error' in data) {
handleCondition('Error accessing page <a href="' + mw.util.getUrl(dialogPage) + '" class="new">' +
window.wikidialog.safeHtml(dialogPage) + '</a>: ' + data.error,
actionParams, viewMissingCondition, true);
return;
}
viewStepTwo(data.name, data.content, data.protected);
});
}
//
// step zero: extract params
//
var dialogPage = actionParams.page;
if (! dialogPage) { showHere('No page specified.'); return; }
viewStepOne(dialogPage);
}
function doEdit(actionParams) {
function handleAuthenticationError() {
var message = 'edit request declined by <a href="' +
mw.util.getUrl(actionParams.form) + '">' +
window.wikidialog.safeHtml(actionParams.form) + '</a>';
if ('local-error' in actionParams) {
message = '(' + message + '):\n' + actionParams['local-error'];
}
showHere('<b>Error:</b> ' + stripHtml(message));
window.wikidialog.pageQuery(
(actionParams.form + '/error'),
{ name: '', protected: '' },
function (data) {
if (('error' in data) || (! data.protected)) {
handleCondition(('Error: ' + message), actionParams, editAuthCondition, true);
return;
}
actionParams.page = data.name;
actionParams.verb = 'view';
window.wikidialog.keepNotes();
window.wikidialog.delegateTo(primaryVerb, actionParams,
function (metadata) { return metadata; },
convertLocalParams(actionParams, 'INCOMING'));
});
}
function editStepEight() {
//
// rollback would no longer make any sense
//
window.wikidialog.commit();
//
// exit strategy
//
if (('page' in actionParams) && actionParams.page) {
window.wikidialog.keepNotes();
window.wikidialog.delegateTo(primaryVerb, { verb: 'view' },
function (metadata) { return metadata; },
convertLocalParams(actionParams, 'INCOMING'));
}
else location = mw.util.getUrl(actionParams.subject);
}
function editStepSeven(s, normalizedFormTitle, creationModeFlag) {
//
// save to page
//
var apidata = { format: 'json',
action: 'edit',
text: s,
title: actionParams.subject,
};
if (('local-summary' in actionParams) && (actionParams['local-summary'])) {
apidata.summary = actionParams['local-summary'] + ' (via [[' + normalizedFormTitle + '|form]])';
} else {
apidata.summary = (creationModeFlag ? 'create' : 'edit') + ' using form [[' +
normalizedFormTitle + ']] via [[' + mw.config.get('wgSiteName') + ':Dialog/do]]';
}
if ('local-basetimestamp' in actionParams) apidata.basetimestamp = actionParams['local-basetimestamp'];
if ('local-section' in actionParams) apidata.section = actionParams['local-section'];
if ('local-sectiontitle' in actionParams) apidata.sectiontitle = actionParams['local-sectiontitle'];
if ('local-minor' in actionParams) apidata.minor = actionParams['local-minor'];
if ('local-notminor' in actionParams) apidata.notminor = actionParams['local-notminor'];
apidata.token = mw.user.tokens.get('csrfToken'); // always the last field added
$.ajax({
type: 'POST',
url: mw.util.wikiScript('api'),
data: apidata,
datatype: 'json'
}).done(function(data) {
if (data && data.edit && data.edit.result && (data.edit.result == 'Success')) {
editStepEight();
} else if (data && data.error) {
if (data.error.code == 'badtoken') {
handleCondition('Loss of session data prevented ' +
(creationModeFlag ? 'creation' : 'edit') +
' of <a href="' + mw.util.getUrl(actionParams.subject) +
'">' + window.wikidialog.safeHtml(actionParams.subject) +
'</a>\nIf you try again, it will probably work; ' +
"if it doesn't, you may have to log out and in again",
actionParams, editSessionCondition);
} else {
handleCondition('Subject page ' + (creationModeFlag ? 'creation' : 'edit') + ' error "' +
data.error.code + '": ' + '<a href="' + mw.util.getUrl(actionParams.subject) +
'">' + window.wikidialog.safeHtml(actionParams.subject) +
'</a>', actionParams, editFailureCondition, true);
}
} else {
handleCondition('Subject page ' + (creationModeFlag ? 'creation' : 'edit') +
' unknown error: <a href="' + mw.util.getUrl(actionParams.subject) +
'">' + window.wikidialog.safeHtml(actionParams.subject) +
'</a>', actionParams, editFailureCondition, true);
}
}).fail(function () {
handleCondition('Subject page ' + (creationModeFlag ? 'creation' : 'edit') +
' misfired: <a href="' + mw.util.getUrl(actionParams.subject) +
'">' + window.wikidialog.safeHtml(actionParams.subject) +
'</code>', actionParams, editFailureCondition, true);
});
}
function editStepSix(s, normalizedFormTitle, creationModeFlag) {
//
// expand the transcluded form
//
$.ajax({
type: 'POST',
url: mw.util.wikiScript('api'),
data: { format: 'json',
action: 'expandtemplates',
text: s,
title: actionParams.subject,
prop: 'wikitext'
},
datatype: 'json'
}).done(function(data) {
if (data.expandtemplates && data.expandtemplates.wikitext) s = data.expandtemplates.wikitext;
else s = '';
editStepSeven(s, normalizedFormTitle, creationModeFlag);
}).fail(function () {
handleCondition('Page parse failed: <a href="' +
mw.util.getUrl(normalizedFormTitle) + '">' +
window.wikidialog.safeHtml(normalizedFormTitle) + '</a>.',
actionParams, editContentCondition, true);
});
}
function editStepFive(s, normalizedFormTitle, creationModeFlag) {
s = window.wikidialog.transclude(s);
editStepSix(s, normalizedFormTitle, creationModeFlag);
}
function editStepFour(rawFormContent, normalizedFormTitle, creationModeFlag) {
//
// parse in situ (not transcluded)
//
$.ajax({
type: 'POST',
url: mw.util.wikiScript('api'),
data: { format: 'json',
action: 'parse',
text: rawFormContent,
title: normalizedFormTitle,
prop: 'text'
},
datatype: 'json'
}).done(function(data) {
var emsg = ''
var parsedFormContent;
if (data.error) {
if (data.error.info) emsg = data.error.info
else emsg = data.error.code;
} else if (data.parse && data.parse.text && data.parse.text['*'])
parsedFormContent = data.parse.text['*'];
else emsg = 'parse request misfired';
if (emsg) {
handleCondition('Error parsing page <a href="' +
mw.util.getUrl(normalizedFormTitle) + '">' +
normalizedFormTitle +
'</a>: ' + emsg, actionParams, editControlCondition, true);
return;
}
//
// authenticate using parsed form content
//
showHere('Authenticating edit request...<span style="display:none">' + parsedFormContent + '</span>', true); // there's hidden stuff on this line
window.wikidialog.purelySelfContained(
function () {
//
// confirm
//
if (rawFormContent.search(/\{\{\s*[Dd]ialog\/confirm edit\s*(\}|\|)/) >= 0)
confirmAction(parsedFormContent, 'edit', 'edit target page', 'form',
actionParams, function () {
editStepFive(rawFormContent, normalizedFormTitle, creationModeFlag);
});
else editStepFive(rawFormContent, normalizedFormTitle, creationModeFlag);
},
function () { handleAuthenticationError(); } // specialized handler
);
}).fail(function () {
handleCondition('Page parse failed: <a href="' + mw.util.getUrl(actionParams.subject) +
'">' + window.wikidialog.safeHtml(actionParams.subject) +
'</a>.', actionParams, editControlCondition, true);
});
}
function editStepThree(rawFormContent, normalizedFormTitle, subjectExists) {
//
// verify expected subject status
//
if ('local-basetimestamp' in actionParams) {
if ('local-creation' in actionParams) {
handleCondition('Edit form error; not allowed to use both local-creation and local-basetimestamp parameters: ' +
(actionParams['local-creation'] ? window.wikidialog.safeHtml(actionParams['local-creation'])
: '<i>(blank)</i>') + ', ' +
(actionParams['local-basetimestamp'] ? window.wikidialog.safeHtml(actionParams['local-basetimestamp'])
: '<i>(blank)</i>'), actionParams, editStatusCondition, true);
return;
}
if (! subjectExists) {
handleCondition('Subject <a href="' + mw.util.getUrl(actionParams.subject) + '" class="new">' +
window.wikidialog.safeHtml(actionParams.subject) +
'</a> does not exist', actionParams, editStatusCondition, true);
return;
}
editStepFour(rawFormContent, normalizedFormTitle, false);
return;
} else if ('local-creation' in actionParams) {
if (actionParams['local-creation'] == 'required') {
if (subjectExists) handleCondition('Subject <a href="' + mw.util.getUrl(actionParams.subject) + '">' +
window.wikidialog.safeHtml(actionParams.subject) +
'</a> already exists', actionParams, editStatusCondition, true);
else editStepFour(rawFormContent, normalizedFormTitle, true);
return;
}
if (actionParams['local-creation'] == 'prohibited') {
if (subjectExists) editStepFour(rawFormContent, normalizedFormTitle, false);
else handleCondition('Subject <a href="' + mw.util.getUrl(actionParams.subject) + '" class="new">' +
window.wikidialog.safeHtml(actionParams.subject) +
'</a> does not exist', actionParams, editStatusCondition, true);
return;
}
if (actionParams['local-creation'] == 'optional') {
editStepFour(rawFormContent, normalizedFormTitle, (! subjectExists));
return;
}
handleCondition('Edit form error; unrecognized local-creation parameter: ' +
(actionParams['local-creation']
? ('<code>' + window.wikidialog.safeHtml(actionParams['local-creation']) + '</code>')
: '<i>(blank)</i>'),
actionParams, editStatusCondition, true);
return;
} else {
handleCondition('Edit form error; missing local-creation or local-basetimestamp parameter for <code>' +
window.wikidialog.safeHtml(actionParams.subject) + '</code>',
actionParams, editStatusCondition, true);
return;
}
}
function editStepTwo(rawFormContent, normalizedFormTitle) {
//
// check form designation ([[Template:Dialog/edit/form]])
//
if (rawFormContent.search(/\{\{\s*[Dd]ialog\/edit\/form\s*\}\}/) < 0) {
handleCondition('Edit form error; page does not self-identify as an edit form: <a href="' +
mw.util.getUrl(normalizedFormTitle) + '">' +
window.wikidialog.safeHtml(normalizedFormTitle) + '</a>',
actionParams, editFormCondition, true);
return;
}
//
// query subject
//
window.wikidialog.substituteParameters(
normalizedFormTitle,
actionParams,
reservedParams(actionParams.form, delegatedData),
rawFormContent,
function (rawFormContent) {
if ('SUBJECT-EXISTS' in actionParams)
editStepThree(rawFormContent, normalizedFormTitle, (actionParams['SUBJECT-EXISTS'] == 'true'));
else handleCondition('Error during edit; failed to determine whether subject already exists: <a href="' +
mw.util.getUrl(actionParams.subject) + '">' +
window.wikidialog.safeHtml(actionParams.subject) + '</a>',
actionParams, editExistCondition, true);
});
}
function editStepOne() {
//
// verify authentication, required parameters, existence/protection of form
//
if (! ('subject' in actionParams))
{ handleCondition('Bad edit request: no parameter "<code>subject</code>" specified.', actionParams, editSpecCondition, true); return; }
if (! ('form' in actionParams))
{ handleCondition('Bad edit request: no parameter "<code>form</code>" specified.', actionParams, editSpecCondition, true); return; }
if (! actionParams.subject)
{ handleCondition('Bad edit request: blank parameter "<code>subject</code>".', actionParams, editSpecCondition, true); return; }
if (! actionParams.form)
{ handleCondition('Bad edit request: blank parameter "<code>form</code>".', actionParams, editSpecCondition, true); return; }
//
// verify form exists and is fully protected
//
window.wikidialog.pageQuery(actionParams.form, { name: '', exists: '', protected: '', content: '' }, function (data) {
if ('error' in data) handleCondition(data.error + ': ' + window.wikidialog.safeHtml(actionParams.form), actionParams, editProtectCondition, true);
else if (! data.exists) handleCondition('Edit form does not exist: <a href="' +
mw.util.getUrl(actionParams.form) + '" class="new">' +
window.wikidialog.safeHtml(actionParams.form) + '</a>', actionParams, editProtectCondition, true);
else if (! data.protected) handleCondition('Edit form is unsecured: <a href="' +
mw.util.getUrl(actionParams.form) + '">' +
window.wikidialog.safeHtml(actionParams.form) + '</a>', actionParams, editProtectCondition, true);
else editStepTwo(data.content, data.name);
});
}
editStepOne();
}
function processUrl(queryParams) {
//
// assemble html
//
var fields = '';
var button = '<span class="wikidialog-button wikidialog-delegable">action=do&label=do'; // [[Template:Dialog/button]]
for (var p in queryParams) {
fields += '<span class="wikidialog-textarea wikidialog-hidden" id="wikidialog-button-local-field-' + p + '">cols=&rows=&' +
queryParams[p] + '</span>'; // [[Template:dialog/textarea]]
button += '&' + p + ':button-local-field-' + p;
}
button += '&</span>';
button = '<div style="display:none;">' + button + '</div>';
var s = button + fields + 'Loading...';
//
// deploy
//
showHere(s, true);
wikidialogShow(function () {
var n = $('input.wikidialog-delegable, button.wikidialog-delegable'); // there's only the one
n.unbind('click').click(function (event) {
// in some browsers, event target may be a copy lacking the data
window.wikidialog.delegateToSettingNewparams(primaryVerb, getButtonParams(n),
function (metadata) { return getButtonMetadata(n); });
});
n.click();
});
}
//
// receive query parameters
//
if (! window.wikidialog.validIncoming()) {
var queryParams = getQueryParams();
if ('verb' in queryParams) processUrl(queryParams);
return;
}
//
// receive dialog parameters
//
window.wikidialog.receiveAnonymous(function () {
var actionParams = this;
var actionVerb = actionParams.verb;
if ($('div.wikidialog-rewritten').length == 0) showHere('Loading...', true);
window.wikidialog.clearNotes();
if (! actionVerb) doView(actionParams);
else if (actionVerb == 'view') doView(actionParams);
else if (actionVerb == 'edit') doEdit(actionParams);
else doView(actionParams);
});
}
$.getScript( // [[MediaWiki:Dialog/receive]]
mw.config.get('wgScript') + '?title=' + mw.util.wikiUrlencode('MediaWiki:Dialog/receive') +
'&action=raw&ctype=text/javascript',
primaryVerb
);