// [[User:Quarl/wikiedit.js]] - functions for automatically editing pages
// depends: util.js, wikipage.js
// recommends: smartsubmit.js
// synposis:
// function beginEdit() {
// wikiPage.getEditorAsync(myPage_edit, data1, data2);
// }
// function myPage_edit(editor, data1, data2) {
// editor.wpTextbox1 += data1;
// editor.wpSummary += data2;
// editor.submit();
//
// WikiEditor is a class that facilitates editing and submitting Wikipedia edit forms.
//
// use asyncWikiEditor() to use the current edit form if available, else download one.
// - inside the callback, "this" is equivalent to "editor"
//
// available properties:
// wpTextbox1
// wpSummary
// wpMinoredit
// wpWatchthis
//
// available functions:
// submitDirect: submit form directly via document.form.submit
// submitHidden: create a new hidden form, attach to document, and submit
// submit: submitDirect if possible, else submitHidden
// submitAsync: asynchronously submit a form via XMLHTTPRequest, and callback result
// updateForm: update what the user sees and prepare for submitting
// refuseCreate: if wpTextbox1 is empty, alert and return 'True'
//
// WikiEditor.addSubmitHook adds a hook that's called from all form
// submissions (including asynchronous ones). For example usage see
// autoreplace.js.
// WikiEditor.addSubmitHook(function(editor, button) { ... });
// quarl 2006-01-23 initial version
// <pre><nowiki>
// WikiEditor class
//
// A WikiEditor doubles as an associative array of the edit properties -
// i.e. editor.wpTextbox1 contains the edit text.
function WikiEditor(wd) {
if (!(this instanceof WikiEditor)) return new WikiEditor(wd);
window.wikiEditor = this;
if (!(wd instanceof WikiDocument)) { alert("WikiEditor: need a WikiDocument"); return; }
this.wd = wd;
this.wp = wd.wp;
this.form = WikiEditor.getEditForm(wd.doc);
if (!this.form) { alert("WikiEditor error: no form!"); return; }
// The HTML default maxlength is 200, but the MediaWiki server actually
// accepts up to 250 chars!
this.form.wpSummary.setAttribute('maxlength', 250);
this.refuseCreate = function() {
if (!this.wpTextbox1) {
alert("Error! Page is empty; refusing to create.");
return true;
} else {
return false;
}
}
this.getFormParams = function(button) {
button = WikiEditor._checkButton(button);
d = {};
WikiEditor.updateFields(d, this, WikiEditor.wpFormFields);
d[button] = this.form[button];
return d;
}
this.updateThis = function() {
WikiEditor.updateFields(this, this.form, WikiEditor.wpFormFields);
}
this.updateForm = function() {
WikiEditor.updateFields(this.form, this, WikiEditor.wpFormFields);
}
// Direct submission, should only be used when the form is part of the
// currently-viewed HTML page. Navigates to result page.
this.submitDirect = function(button) {
button = WikiEditor._checkButton(button);
this.updateForm();
// Click the appropriate button.
// Note that this generates an onClick event, which in turn calls the
// runPreSubmitHooks function.
this.form[button].click();
}
// Adds a hidden form to the current page and submits it, navigating to
// the result page.
this.submitHidden = function(button) {
button = WikiEditor._checkButton(button);
this.runPreSubmitHooks(this, button);
var newform = document.createElement('form');
addFormHiddenParams(newform, this.getFormParams(button));
newform.name = this.form.name;
newform.method = this.form.method;
newform.id = this.form.id;
newform.action = this.form.action;
document.getElementById('bodyContent').appendChild(newform);
newform.submit();
}
// Asynchronously submit the form and call CALLBACK.
this.submitAsync = function(button, callback) {
button = WikiEditor._checkButton(button);
var cb;
if (callback) {
var thisE = this;
var args = copyArray(arguments);
args.shift(); args[0] = null;
cb = function(req) { args[0] = req; callback.apply(thisE, args); };
} else {
cb = function(req) { /* dummy */ };
}
var data = this.getFormParams(button);
this.runPreSubmitHooks(data, button);
asyncPostXML(this.form.action, data, cb);
}
// copy input fields from form into this object for easy access (we'll copy back later)
this.updateThis();
this.wpTextbox1_orig = this.form.wpTextbox1_orig;
// If this form is the current document's form, we can submit directly.
// Else we must use the hidden submit method.
if (this.form == document.editform) {
this.submit = this.submitDirect;
} else {
this.submit = this.submitHidden;
}
}
WikiEditor.getEditForm = function(doc) {
if (!doc) doc = document;
// Note: can't use "doc.editform", because 'doc' might actually be an XMLDocument (not HTMLDocument), if this is the result of an XMLHTTPRequest.
return doc.getElementById('editform');
}
WikiEditor._assocArray = function(x) {
for (var i in x) {
x[ x[i] ] = 1;
}
return x;
}
WikiEditor.wpFormFields = WikiEditor._assocArray( [
'wpSection', 'wpStarttime', 'wpEdittime', 'wpScrolltop',
'wpTextbox1', 'wpSummary', 'wpMinoredit', 'wpWatchthis',
'wpEditToken' ] );
WikiEditor.wpButtons = WikiEditor._assocArray( [ 'wpSave', 'wpPreview', 'wpDiff' ] );
WikiEditor._checkButton = function(button) {
if (!button) return 'wpSave'; // default
if (typeof button != 'string' || WikiEditor.wpButtons[button] != 1) {
alert("## WikiEditor._checkButton: invalid button '"+button+"' (error 1a0655e7-ac83-4f15-8447-694b16a834ed)");
return 'wpPreview';
}
return button;
}
WikiEditor.updateFields = function(target, source, fields) {
var targetFormP = Boolean(target.nodeName);
var sourceFormP = Boolean(source.nodeName);
for (var i in fields) {
var f = fields[i];
var v;
if (sourceFormP && source[f]) {
if (source[f].type == "checkbox") {
v = source[f].checked;
} else {
v = source[f].value;
}
} else {
v = source[f];
}
if (targetFormP) {
if (target[f].type == "checkbox") {
target[f].checked = v;
} else {
// don't set it if unchanged, to avoid focus/selection change
if (target[f].value != v) target[f].value = v;
}
} else {
target[f] = v;
}
}
}
// Get an editor for this WikiPage -- it needs to have an editDoc already (as
// an editing window.wikiPage would have); else need to use getEditorAsync().
// Usually it's easier to just always use getEditorAsync.
if(typeof WikiPage !== 'undefined') {
WikiPage.prototype.getEditor = function() {
if (!this.editor) {
if (!this.editDoc) {
alert("## WikiPage.getEditor: no editDoc (use getEditorAsync)");
return;
}
this.editor = WikiEditor(this.editDoc);
}
return this.editor;
}
// If already editing the target page, return a WikiEditor now.
// Else, download the edit form first.
// Call-back with new WikiEditor instance.
WikiPage.prototype.getEditorAsync = function(callback) {
var wp = this;
var args = copyArray(arguments); // copy arguments because we need it in 'cb' below
// already cached
if (wp.editor) {
args[0] = wp.editor;
callback.apply(wp.editor, args); return;
}
// do we already have an edit document? (window.wikiPage.editDoc would be
// initialized to 'WikiDocument(document)' as appropriate).
if (wp.editDoc) {
wp.editor = WikiEditor(wp.editDoc);
args[0] = wp.editor;
callback.apply(wp.editor, args); return;
}
// need to download a new edit document.
var cb = function(req) {
if (req.status != 200) {
alert("asyncWikiEditor: Error downloading edit page!");
return;
}
wp.setDoc(req.responseXML);
wp.editor = WikiEditor(wp.editDoc);
args[0] = wp.editor;
callback.apply(wp.editor, args); return;
};
asyncDownloadXML(wp.qurl + '&action=edit', cb);
}
}
// deprecated
function asyncWikiEditor(wp) {
var args = copyArray(arguments);
args.shift();
wp.getEditorAsync.apply(wp, args);
}
WikiEditor.pre_submit_hooks = [];
// add a submit hook to all forms (including asynchronous ones).
// Submit hooks are called with arguments (editor, form, button)
// Note that the form argument may not be the same as editor.form or
// document.form, if the submit is via submitHidden or submitAsync!
WikiEditor.addPreSubmitHook = function(func) {
WikiEditor.pre_submit_hooks.push(func);
}
WikiEditor.prototype.runPreSubmitHooks = function(data, button) {
// 'data' should be a hash array and could be either a WikiEditor
// instance, or a separate object
for (var i in WikiEditor.pre_submit_hooks) {
WikiEditor.pre_submit_hooks[i](this, data, button);
}
}
WikiEditor.onClickSubmitHook = function(button) {
var editor = wikiPage.getEditor();
if (editor.form[button].preventPreSumitHook) return;
editor.updateThis();
editor.runPreSubmitHooks(editor, button);
// submit hooks may have changed data.
editor.updateForm();
}
WikiEditor.load = function() {
if (document.forms.editform) {
// save original version of edit box
document.forms.editform.wpTextbox1_orig = document.forms.editform.wpTextbox1.value;
// hookEventObj(document.forms.editform, 'submit', WikiEditor.onClickSubmitHook);
// add submit hooks
hookEventObj(document.editform.wpSave, 'click', function() { WikiEditor.onClickSubmitHook('wpSave'); });
hookEventObj(document.editform.wpDiff, 'click', function() { WikiEditor.onClickSubmitHook('wpDiff'); });
hookEventObj(document.editform.wpPreview, 'click', function() { WikiEditor.onClickSubmitHook('wpPreview'); });
}
}
$(WikiEditor.load);
// </nowiki></pre>