MediaWiki:AjaxSubmit.js

// /* Purpose: For ImageAnnotator gadget ("add note") on File: pages. Source: Commons: http://commons.wikimedia.org/w/index.php?title=MediaWiki:AjaxSubmit.js  Documentation: http://commons.wikimedia.org/wiki/Help:Gadget-ImageAnnotator installed by phlox 2009-09-05 // 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. function ajaxSubmit (form, button, func, want_result) { 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 == 0 || !value || value.length == 0) return null; if (!boundary) return name + '=' + encodeURIComponent (value); else return boundary + '\r\n' + 'Content-Disposition: form-data; name="' + name + '"\r\n' + '\r\n' + value + '\r\n'; // Must be encoded?? How? escape? or encodeURIComponent? } function encode_field (element) {   var name = element.name; if (!name || name.length == 0) name = element.id; return encode_entry (name, element.value); } function form_add_argument (args, field) {   if (!field || field.length == 0) return args; if (!args || args.length == 0) return field; if (is_simple) return args + '&' + field; else return args + field; } var request   = sajax_init_object; var method   = form.getAttribute ('method').toUpperCase ; var uri      = form.getAttribute ('action'); if (uri.charAt (0) == '/') { // Some browsers already expand the action URI (e.g. Opera 9.26) uri = wgServer + uri; } // Encode the field values

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

var args           = ""; var boundary_string = '' + wgArticleId+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 fall-through case 'hidden': case 'text': case 'password': case 'textarea': args = form_add_argument (args, encode_field (element)); break; case 'select-one': single_select = true; // fall-through case 'select-multiple': var name = element.name || element.id || ""; if (name.length == 0) 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 = args + boundary;

if (method == 'GET') { uri = 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 == null) 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); }   try { request.setRequestHeader ('Content-length', args.length); } catch (anything) { // Just swallow. Some browsers don't like setting this but prefer to do it themselves. // Safari 4 for instance issues an "error" about an "unsafe" setting not done, but then // continues anyway. The exception handler here is just paranoia in case someone decides // to make this a hard error. } }  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 ; }); }