MediaWiki:AjaxSubmit.js

// ajaxSubmit //  Submit a form through Ajax. Doesn't handle file uploads yet. // // Parameters: //  form                 DOM element   The form to submit //  button      optional DOM element   If set and a submit button of 'form', is added to the //                                     form arguments sent //  func        optional Function      Function to call once the call has been made or the //                                     result has arrived, if want_result === true //  want_result optional Boolean       If true, call func with the result of the submit once //                                     it has arrived. Otherwise, call func as soon as the //                                     submit request has been received by the server, and //                                     ignore any result of the submit. // // Notes: //  Func should be a function (request). If func is not defined, //  ajaxSubmit just submits the form and ignores any result. /*global mw*/ function ajaxSubmit(form, button, func, want_result) { "use strict"; if (want_result && (!func || typeof(func) != 'function' || func.length < 1)) { /**** TODO: improve error handling: should throw an exception! */		alert('Logic error in ajaxSubmit: func must be function (request).'); return; }	if (func && typeof(func) != 'function') { /**** TODO: improve error handling: should throw an exception! */		alert('Error in ajaxSubmit: func must be a function, found a ' + typeof(func) + '.'); return; }

var is_simple = false; // True if it's a GET request, or if the form is 'application/x-www-form-urlencoded' var boundary = null; // Otherwise, it's 'multipart/form-data', and the multipart delimiter is 'boundary'

function encode_entry(name, value) { if (!name || !name.length || !value || !value.length) return null; if (!boundary) return name + '=' + encodeURIComponent(value); else return boundary + '\r\n' + 'Content-Disposition: form-data; name="' + name + '"\r\n' + '\r\n' + value.replace(/\r?\n/g, '\r\n') + '\r\n'; // RFC 2046: newlines always must be represented as CR-LF }

function encode_field(element) { var name = element.name; if (!name || !name.length) name = element.id; return encode_entry(name, element.value); }

function form_add_argument(args, field) { if (!field || !field.length) return args; if (!args || !args.length) return field; if (is_simple) return args + '&' + field; else return args + field; }

var request; if (window.LAPI && window.LAPI.Ajax && window.LAPI.Ajax.getRequest) { request = window.LAPI.Ajax.getRequest; } else { try { request = new window.XMLHttpRequest; } catch (anything) { if (window.ActiveXObject) request = new window.ActiveXObject('Microsoft.XMLHTTP'); }	}	var method = form.getAttribute('method').toUpperCase; var uri = form.getAttribute('action'); if (uri.length >= 2 && uri.substring(0, 2) === '//') { // Protocol-relative URI; can cause trouble on IE7 uri = document.location.protocol + uri; } else if (uri[0] === '/') { // Some browsers already expand the action URI (e.g. Opera 9.26) uri = mw.config.get('wgServer') + uri; if (uri.length >= 2 && uri.substring(0, 2) === '//') uri = document.location.protocol + uri; }	// Encode the field values

var is_get = method === 'GET'; var encoding = form.getAttribute('enctype'); if (encoding) { encoding = encoding.toLowerCase; if (!encoding.length) encoding = null; }	is_simple = is_get || !encoding || encoding === 'application/x-www-form-urlencoded';

var args = ''; var boundary_string = '' + mw.config.get('wgArticleId') + mw.config.get('wgCurRevisionId') + 'auto_submit_by_lupo';

boundary = null;

if (!is_simple) boundary = '--' + boundary_string;

for (var i = 0; i < form.elements.length; i++) { var element = form.elements[i]; var single_select = false; switch (element.type) { case 'checkbox': case 'radio': if (!element.checked) break; else if (element.id === 'wpWatchthis' && document.getElementById('ca-unwatch')) { args = form_add_argument(args, encode_entry('wpWatchthis', '1')); break; }			/* falls through */ case 'hidden': case 'text': case 'password': case 'textarea': args = form_add_argument(args, encode_field(element)); break; case 'select-one': single_select = true; /* falls through */ case 'select-multiple': var name = element.name || element.id || ''; if (!name.length) break; for (var j = 0; j < element.length; j++) { if (element[j].selected) { var value = element[j].value || element[j].text; args = form_add_argument(args, encode_entry(name, value)); if (single_select) break; // No need to scan the rest }			}			break; case 'file': break; }	}	if (button && button.form === form && button.type === 'submit') args = form_add_argument(args, encode_field(button));

// Close the multipart request if (!is_simple && args.length > 0) args += boundary;

if (method === 'GET') { uri += (uri.indexOf('?') < 0 ? '?' : '&') + args; args = null; }	// Make the request request.open(method, uri, true); if (want_result && request.overrideMimeType) request.overrideMimeType('application/xml'); request.setRequestHeader('Pragma', 'cache=no'); request.setRequestHeader('Cache-Control', 'no-transform'); if (method === 'POST') { if (!encoding) encoding = 'application/x-www-form-urlencoded'; if (!is_simple) { request.setRequestHeader(				'Content-type', encoding + '; charset=UTF-8; boundary="' + boundary_string + '"'); } else { request.setRequestHeader('Content-type', encoding); }	}	request.onreadystatechange = function { if (want_result) { if (request.readyState < 4) return; func(request); } else { // Call func as soon as the request has been sent and we start getting the result. if (request.readyState === 3 && func) func(request); }	};	request.send(args); }

// submitAndClose //  Submit a form and close the window containing it as soon as the request has been //  received by the server // // Parameters: //  form   DOM element   The form to submit. function submitAndClose(form) { ajaxSubmit(form, null, function {		window.close;	}); }