User:Quarl/wikiedit.js

// 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

//

// 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);

//