Update jQuery Form to 3.37.0 (unused in WP core).

props usermrpapa.
fixes #23944.

Built from https://develop.svn.wordpress.org/trunk@25462


git-svn-id: http://core.svn.wordpress.org/trunk@25383 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
Andrew Nacin 2013-09-16 21:06:09 +00:00
parent 3137e83126
commit 090b3c8355
3 changed files with 999 additions and 631 deletions

View File

@ -1,24 +1,26 @@
/*! /*!
* jQuery Form Plugin * jQuery Form Plugin
* version: 2.73 (03-MAY-2011) * version: 3.37.0-2013.07.11
* @requires jQuery v1.3.2 or later * @requires jQuery v1.5 or later
* * Copyright (c) 2013 M. Alsup
* Examples and documentation at: http://malsup.com/jquery/form/ * Examples and documentation at: http://malsup.com/jquery/form/
* Dual licensed under the MIT and GPL licenses: * Project repository: https://github.com/malsup/form
* http://www.opensource.org/licenses/mit-license.php * Dual licensed under the MIT and GPL licenses.
* http://www.gnu.org/licenses/gpl.html * https://github.com/malsup/form#copyright-and-license
*/ */
/*global ActiveXObject */
;(function($) { ;(function($) {
"use strict";
/* /*
Usage Note: Usage Note:
----------- -----------
Do not use both ajaxSubmit and ajaxForm on the same form. These Do not use both ajaxSubmit and ajaxForm on the same form. These
functions are intended to be exclusive. Use ajaxSubmit if you want functions are mutually exclusive. Use ajaxSubmit if you want
to bind your own submit handler to the form. For example, to bind your own submit handler to the form. For example,
$(document).ready(function() { $(document).ready(function() {
$('#myForm').bind('submit', function(e) { $('#myForm').on('submit', function(e) {
e.preventDefault(); // <-- important e.preventDefault(); // <-- important
$(this).ajaxSubmit({ $(this).ajaxSubmit({
target: '#output' target: '#output'
@ -35,37 +37,76 @@
}); });
}); });
You can also use ajaxForm with delegation (requires jQuery v1.7+), so the
form does not have to exist when you invoke ajaxForm:
$('#myForm').ajaxForm({
delegation: true,
target: '#output'
});
When using ajaxForm, the ajaxSubmit function will be invoked for you When using ajaxForm, the ajaxSubmit function will be invoked for you
at the appropriate time. at the appropriate time.
*/ */
/**
* Feature detection
*/
var feature = {};
feature.fileapi = $("<input type='file'/>").get(0).files !== undefined;
feature.formdata = window.FormData !== undefined;
var hasProp = !!$.fn.prop;
// attr2 uses prop when it can but checks the return type for
// an expected string. this accounts for the case where a form
// contains inputs with names like "action" or "method"; in those
// cases "prop" returns the element
$.fn.attr2 = function() {
if ( ! hasProp )
return this.attr.apply(this, arguments);
var val = this.prop.apply(this, arguments);
if ( ( val && val.jquery ) || typeof val === 'string' )
return val;
return this.attr.apply(this, arguments);
};
/** /**
* ajaxSubmit() provides a mechanism for immediately submitting * ajaxSubmit() provides a mechanism for immediately submitting
* an HTML form using AJAX. * an HTML form using AJAX.
*/ */
$.fn.ajaxSubmit = function(options) { $.fn.ajaxSubmit = function(options) {
/*jshint scripturl:true */
// fast fail if nothing selected (http://dev.jquery.com/ticket/2752) // fast fail if nothing selected (http://dev.jquery.com/ticket/2752)
if (!this.length) { if (!this.length) {
log('ajaxSubmit: skipping submit process - no element selected'); log('ajaxSubmit: skipping submit process - no element selected');
return this; return this;
} }
var method, action, url, $form = this;
if (typeof options == 'function') { if (typeof options == 'function') {
options = { success: options }; options = { success: options };
} }
else if ( options === undefined ) {
options = {};
}
var action = this.attr('action'); method = options.type || this.attr2('method');
var url = (typeof action === 'string') ? $.trim(action) : ''; action = options.url || this.attr2('action');
url = (typeof action === 'string') ? $.trim(action) : '';
url = url || window.location.href || '';
if (url) { if (url) {
// clean url (don't include hash vaue) // clean url (don't include hash vaue)
url = (url.match(/^([^#]+)/)||[])[1]; url = (url.match(/^([^#]+)/)||[])[1];
} }
url = url || window.location.href || '';
options = $.extend(true, { options = $.extend(true, {
url: url, url: url,
success: $.ajaxSettings.success, success: $.ajaxSettings.success,
type: this[0].getAttribute('method') || 'GET', // IE7 massage (see issue 57) type: method || 'GET',
iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank' iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank'
}, options); }, options);
@ -84,21 +125,16 @@ $.fn.ajaxSubmit = function(options) {
return this; return this;
} }
var n,v,a = this.formToArray(options.semantic); var traditional = options.traditional;
if ( traditional === undefined ) {
traditional = $.ajaxSettings.traditional;
}
var elements = [];
var qx, a = this.formToArray(options.semantic, elements);
if (options.data) { if (options.data) {
options.extraData = options.data; options.extraData = options.data;
for (n in options.data) { qx = $.param(options.data, traditional);
if(options.data[n] instanceof Array) {
for (var k in options.data[n]) {
a.push( { name: n, value: options.data[n][k] } );
}
}
else {
v = options.data[n];
v = $.isFunction(v) ? v() : v; // if value is fn, invoke it
a.push( { name: n, value: v } );
}
}
} }
// give pre-submit callback an opportunity to abort the submit // give pre-submit callback an opportunity to abort the submit
@ -114,8 +150,10 @@ $.fn.ajaxSubmit = function(options) {
return this; return this;
} }
var q = $.param(a); var q = $.param(a, traditional);
if (qx) {
q = ( q ? (q + '&' + qx) : qx );
}
if (options.type.toUpperCase() == 'GET') { if (options.type.toUpperCase() == 'GET') {
options.url += (options.url.indexOf('?') >= 0 ? '&' : '?') + q; options.url += (options.url.indexOf('?') >= 0 ? '&' : '?') + q;
options.data = null; // data is null for 'get' options.data = null; // data is null for 'get'
@ -124,12 +162,12 @@ $.fn.ajaxSubmit = function(options) {
options.data = q; // data is the query string for 'post' options.data = q; // data is the query string for 'post'
} }
var $form = this, callbacks = []; var callbacks = [];
if (options.resetForm) { if (options.resetForm) {
callbacks.push(function() { $form.resetForm(); }); callbacks.push(function() { $form.resetForm(); });
} }
if (options.clearForm) { if (options.clearForm) {
callbacks.push(function() { $form.clearForm(); }); callbacks.push(function() { $form.clearForm(options.includeHidden); });
} }
// perform a load on the target only if dataType is not provided // perform a load on the target only if dataType is not provided
@ -145,58 +183,179 @@ $.fn.ajaxSubmit = function(options) {
} }
options.success = function(data, status, xhr) { // jQuery 1.4+ passes xhr as 3rd arg options.success = function(data, status, xhr) { // jQuery 1.4+ passes xhr as 3rd arg
var context = options.context || options; // jQuery 1.4+ supports scope context var context = options.context || this ; // jQuery 1.4+ supports scope context
for (var i=0, max=callbacks.length; i < max; i++) { for (var i=0, max=callbacks.length; i < max; i++) {
callbacks[i].apply(context, [data, status, xhr || $form, $form]); callbacks[i].apply(context, [data, status, xhr || $form, $form]);
} }
}; };
if (options.error) {
var oldError = options.error;
options.error = function(xhr, status, error) {
var context = options.context || this;
oldError.apply(context, [xhr, status, error, $form]);
};
}
if (options.complete) {
var oldComplete = options.complete;
options.complete = function(xhr, status) {
var context = options.context || this;
oldComplete.apply(context, [xhr, status, $form]);
};
}
// are there files to upload? // are there files to upload?
var fileInputs = $('input:file', this).length > 0;
// [value] (issue #113), also see comment:
// https://github.com/malsup/form/commit/588306aedba1de01388032d5f42a60159eea9228#commitcomment-2180219
var fileInputs = $('input[type=file]:enabled[value!=""]', this);
var hasFileInputs = fileInputs.length > 0;
var mp = 'multipart/form-data'; var mp = 'multipart/form-data';
var multipart = ($form.attr('enctype') == mp || $form.attr('encoding') == mp); var multipart = ($form.attr('enctype') == mp || $form.attr('encoding') == mp);
var fileAPI = feature.fileapi && feature.formdata;
log("fileAPI :" + fileAPI);
var shouldUseFrame = (hasFileInputs || multipart) && !fileAPI;
var jqxhr;
// options.iframe allows user to force iframe mode // options.iframe allows user to force iframe mode
// 06-NOV-09: now defaulting to iframe mode if file input is detected // 06-NOV-09: now defaulting to iframe mode if file input is detected
if (options.iframe !== false && (fileInputs || options.iframe || multipart)) { if (options.iframe !== false && (options.iframe || shouldUseFrame)) {
// hack to fix Safari hang (thanks to Tim Molendijk for this) // hack to fix Safari hang (thanks to Tim Molendijk for this)
// see: http://groups.google.com/group/jquery-dev/browse_thread/thread/36395b7ab510dd5d // see: http://groups.google.com/group/jquery-dev/browse_thread/thread/36395b7ab510dd5d
if (options.closeKeepAlive) { if (options.closeKeepAlive) {
$.get(options.closeKeepAlive, fileUpload); $.get(options.closeKeepAlive, function() {
jqxhr = fileUploadIframe(a);
});
} }
else { else {
fileUpload(); jqxhr = fileUploadIframe(a);
} }
} }
else if ((hasFileInputs || multipart) && fileAPI) {
jqxhr = fileUploadXhr(a);
}
else { else {
$.ajax(options); jqxhr = $.ajax(options);
} }
$form.removeData('jqxhr').data('jqxhr', jqxhr);
// clear element array
for (var k=0; k < elements.length; k++)
elements[k] = null;
// fire 'notify' event // fire 'notify' event
this.trigger('form-submit-notify', [this, options]); this.trigger('form-submit-notify', [this, options]);
return this; return this;
// utility fn for deep serialization
// private function for handling file uploads (hat tip to YAHOO!) function deepSerialize(extraData){
function fileUpload() { var serialized = $.param(extraData, options.traditional).split('&');
var form = $form[0]; var len = serialized.length;
var result = [];
if ($(':input[name=submit],:input[id=submit]', form).length) { var i, part;
// if there is an input with a name or id of 'submit' then we won't be for (i=0; i < len; i++) {
// able to invoke the submit fn on the form (at least not x-browser) // #252; undo param space replacement
alert('Error: Form elements must not have name or id of "submit".'); serialized[i] = serialized[i].replace(/\+/g,' ');
return; part = serialized[i].split('=');
// #278; use array instead of object storage, favoring array serializations
result.push([decodeURIComponent(part[0]), decodeURIComponent(part[1])]);
}
return result;
} }
var s = $.extend(true, {}, $.ajaxSettings, options); // XMLHttpRequest Level 2 file uploads (big hat tip to francois2metz)
function fileUploadXhr(a) {
var formdata = new FormData();
for (var i=0; i < a.length; i++) {
formdata.append(a[i].name, a[i].value);
}
if (options.extraData) {
var serializedData = deepSerialize(options.extraData);
for (i=0; i < serializedData.length; i++)
if (serializedData[i])
formdata.append(serializedData[i][0], serializedData[i][1]);
}
options.data = null;
var s = $.extend(true, {}, $.ajaxSettings, options, {
contentType: false,
processData: false,
cache: false,
type: method || 'POST'
});
if (options.uploadProgress) {
// workaround because jqXHR does not expose upload property
s.xhr = function() {
var xhr = $.ajaxSettings.xhr();
if (xhr.upload) {
xhr.upload.addEventListener('progress', function(event) {
var percent = 0;
var position = event.loaded || event.position; /*event.position is deprecated*/
var total = event.total;
if (event.lengthComputable) {
percent = Math.ceil(position / total * 100);
}
options.uploadProgress(event, position, total, percent);
}, false);
}
return xhr;
};
}
s.data = null;
var beforeSend = s.beforeSend;
s.beforeSend = function(xhr, o) {
o.data = formdata;
if(beforeSend)
beforeSend.call(this, xhr, o);
};
return $.ajax(s);
}
// private function for handling file uploads (hat tip to YAHOO!)
function fileUploadIframe(a) {
var form = $form[0], el, i, s, g, id, $io, io, xhr, sub, n, timedOut, timeoutHandle;
var deferred = $.Deferred();
if (a) {
// ensure that every serialized input is still enabled
for (i=0; i < elements.length; i++) {
el = $(elements[i]);
if ( hasProp )
el.prop('disabled', false);
else
el.removeAttr('disabled');
}
}
s = $.extend(true, {}, $.ajaxSettings, options);
s.context = s.context || s; s.context = s.context || s;
var id = 'jqFormIO' + (new Date().getTime()), fn = '_'+id; id = 'jqFormIO' + (new Date().getTime());
var $io = $('<iframe id="' + id + '" name="' + id + '" src="'+ s.iframeSrc +'" />'); if (s.iframeTarget) {
var io = $io[0]; $io = $(s.iframeTarget);
n = $io.attr2('name');
if (!n)
$io.attr2('name', id);
else
id = n;
}
else {
$io = $('<iframe name="' + id + '" src="'+ s.iframeSrc +'" />');
$io.css({ position: 'absolute', top: '-1000px', left: '-1000px' }); $io.css({ position: 'absolute', top: '-1000px', left: '-1000px' });
}
io = $io[0];
var xhr = { // mock object
xhr = { // mock object
aborted: 0, aborted: 0,
responseText: null, responseText: null,
responseXML: null, responseXML: null,
@ -209,17 +368,28 @@ $.fn.ajaxSubmit = function(options) {
var e = (status === 'timeout' ? 'timeout' : 'aborted'); var e = (status === 'timeout' ? 'timeout' : 'aborted');
log('aborting upload... ' + e); log('aborting upload... ' + e);
this.aborted = 1; this.aborted = 1;
try { // #214, #257
if (io.contentWindow.document.execCommand) {
io.contentWindow.document.execCommand('Stop');
}
}
catch(ignore) {}
$io.attr('src', s.iframeSrc); // abort op in progress $io.attr('src', s.iframeSrc); // abort op in progress
xhr.error = e; xhr.error = e;
s.error && s.error.call(s.context, xhr, e, e); if (s.error)
g && $.event.trigger("ajaxError", [xhr, s, e]); s.error.call(s.context, xhr, e, status);
s.complete && s.complete.call(s.context, xhr, e); if (g)
$.event.trigger("ajaxError", [xhr, s, e]);
if (s.complete)
s.complete.call(s.context, xhr, e);
} }
}; };
var g = s.global; g = s.global;
// trigger ajax global events so that activity/block indicators work like normal // trigger ajax global events so that activity/block indicators work like normal
if (g && ! $.active++) { if (g && 0 === $.active++) {
$.event.trigger("ajaxStart"); $.event.trigger("ajaxStart");
} }
if (g) { if (g) {
@ -230,18 +400,18 @@ $.fn.ajaxSubmit = function(options) {
if (s.global) { if (s.global) {
$.active--; $.active--;
} }
return; deferred.reject();
return deferred;
} }
if (xhr.aborted) { if (xhr.aborted) {
return; deferred.reject();
return deferred;
} }
var timedOut = 0, timeoutHandle;
// add submitting element to data if we know it // add submitting element to data if we know it
var sub = form.clk; sub = form.clk;
if (sub) { if (sub) {
var n = sub.name; n = sub.name;
if (n && !sub.disabled) { if (n && !sub.disabled) {
s.extraData = s.extraData || {}; s.extraData = s.extraData || {};
s.extraData[n] = sub.value; s.extraData[n] = sub.value;
@ -252,22 +422,67 @@ $.fn.ajaxSubmit = function(options) {
} }
} }
var CLIENT_TIMEOUT_ABORT = 1;
var SERVER_ABORT = 2;
function getDoc(frame) {
/* it looks like contentWindow or contentDocument do not
* carry the protocol property in ie8, when running under ssl
* frame.document is the only valid response document, since
* the protocol is know but not on the other two objects. strange?
* "Same origin policy" http://en.wikipedia.org/wiki/Same_origin_policy
*/
var doc = null;
// IE8 cascading access check
try {
if (frame.contentWindow) {
doc = frame.contentWindow.document;
}
} catch(err) {
// IE8 access denied under ssl & missing protocol
log('cannot get iframe.contentWindow document: ' + err);
}
if (doc) { // successful getting content
return doc;
}
try { // simply checking may throw in ie8 under ssl or mismatched protocol
doc = frame.contentDocument ? frame.contentDocument : frame.document;
} catch(err) {
// last attempt
log('cannot get iframe.contentDocument: ' + err);
doc = frame.document;
}
return doc;
}
// Rails CSRF hack (thanks to Yvan Barthelemy)
var csrf_token = $('meta[name=csrf-token]').attr('content');
var csrf_param = $('meta[name=csrf-param]').attr('content');
if (csrf_param && csrf_token) {
s.extraData = s.extraData || {};
s.extraData[csrf_param] = csrf_token;
}
// take a breath so that pending repaints get some cpu time before the upload starts // take a breath so that pending repaints get some cpu time before the upload starts
function doSubmit() { function doSubmit() {
// make sure form attrs are set // make sure form attrs are set
var t = $form.attr('target'), a = $form.attr('action'); var t = $form.attr2('target'), a = $form.attr2('action');
// update form attrs in IE friendly way // update form attrs in IE friendly way
form.setAttribute('target',id); form.setAttribute('target',id);
if (form.getAttribute('method') != 'POST') { if (!method) {
form.setAttribute('method', 'POST'); form.setAttribute('method', 'POST');
} }
if (form.getAttribute('action') != s.url) { if (a != s.url) {
form.setAttribute('action', s.url); form.setAttribute('action', s.url);
} }
// ie borks in some cases when setting encoding // ie borks in some cases when setting encoding
if (! s.skipEncodingOverride) { if (! s.skipEncodingOverride && (!method || /post/i.test(method))) {
$form.attr({ $form.attr({
encoding: 'multipart/form-data', encoding: 'multipart/form-data',
enctype: 'multipart/form-data' enctype: 'multipart/form-data'
@ -276,7 +491,24 @@ $.fn.ajaxSubmit = function(options) {
// support timout // support timout
if (s.timeout) { if (s.timeout) {
timeoutHandle = setTimeout(function() { timedOut = true; cb(true); }, s.timeout); timeoutHandle = setTimeout(function() { timedOut = true; cb(CLIENT_TIMEOUT_ABORT); }, s.timeout);
}
// look for server aborts
function checkState() {
try {
var state = getDoc(io).readyState;
log('state = ' + state);
if (state && state.toLowerCase() == 'uninitialized')
setTimeout(checkState,50);
}
catch(e) {
log('Server abort: ' , e, ' (', e.name, ')');
cb(SERVER_ABORT);
if (timeoutHandle)
clearTimeout(timeoutHandle);
timeoutHandle = undefined;
}
} }
// add "extra" data to form if provided in options // add "extra" data to form if provided in options
@ -284,16 +516,38 @@ $.fn.ajaxSubmit = function(options) {
try { try {
if (s.extraData) { if (s.extraData) {
for (var n in s.extraData) { for (var n in s.extraData) {
if (s.extraData.hasOwnProperty(n)) {
// if using the $.param format that allows for multiple values with the same name
if($.isPlainObject(s.extraData[n]) && s.extraData[n].hasOwnProperty('name') && s.extraData[n].hasOwnProperty('value')) {
extraInputs.push( extraInputs.push(
$('<input type="hidden" name="'+n+'" value="'+s.extraData[n]+'" />') $('<input type="hidden" name="'+s.extraData[n].name+'">').val(s.extraData[n].value)
.appendTo(form)[0]);
} else {
extraInputs.push(
$('<input type="hidden" name="'+n+'">').val(s.extraData[n])
.appendTo(form)[0]); .appendTo(form)[0]);
} }
} }
}
}
if (!s.iframeTarget) {
// add iframe to doc and submit the form // add iframe to doc and submit the form
$io.appendTo('body'); $io.appendTo('body');
io.attachEvent ? io.attachEvent('onload', cb) : io.addEventListener('load', cb, false); if (io.attachEvent)
io.attachEvent('onload', cb);
else
io.addEventListener('load', cb, false);
}
setTimeout(checkState,15);
try {
form.submit(); form.submit();
} catch(err) {
// just in case form has element with name/id of 'submit'
var submitFn = document.createElement('form').submit;
submitFn.apply(form);
}
} }
finally { finally {
// reset attrs and remove "extra" input elements // reset attrs and remove "extra" input elements
@ -320,20 +574,34 @@ $.fn.ajaxSubmit = function(options) {
if (xhr.aborted || callbackProcessed) { if (xhr.aborted || callbackProcessed) {
return; return;
} }
if (e === true && xhr) {
doc = getDoc(io);
if(!doc) {
log('cannot access response document');
e = SERVER_ABORT;
}
if (e === CLIENT_TIMEOUT_ABORT && xhr) {
xhr.abort('timeout'); xhr.abort('timeout');
deferred.reject(xhr, 'timeout');
return;
}
else if (e == SERVER_ABORT && xhr) {
xhr.abort('server abort');
deferred.reject(xhr, 'error', 'server abort');
return; return;
} }
var doc = io.contentWindow ? io.contentWindow.document : io.contentDocument ? io.contentDocument : io.document;
if (!doc || doc.location.href == s.iframeSrc) { if (!doc || doc.location.href == s.iframeSrc) {
// response not received yet // response not received yet
if (!timedOut) if (!timedOut)
return; return;
} }
io.detachEvent ? io.detachEvent('onload', cb) : io.removeEventListener('load', cb, false); if (io.detachEvent)
io.detachEvent('onload', cb);
else
io.removeEventListener('load', cb, false);
var ok = true; var status = 'success', errMsg;
try { try {
if (timedOut) { if (timedOut) {
throw 'timeout'; throw 'timeout';
@ -341,7 +609,7 @@ $.fn.ajaxSubmit = function(options) {
var isXml = s.dataType == 'xml' || doc.XMLDocument || $.isXMLDoc(doc); var isXml = s.dataType == 'xml' || doc.XMLDocument || $.isXMLDoc(doc);
log('isXml='+isXml); log('isXml='+isXml);
if (!isXml && window.opera && (doc.body == null || doc.body.innerHTML == '')) { if (!isXml && window.opera && (doc.body === null || !doc.body.innerHTML)) {
if (--domCheckCount) { if (--domCheckCount) {
// in some browsers (Opera) the iframe DOM is not always traversable when // in some browsers (Opera) the iframe DOM is not always traversable when
// the onload callback fires, so we loop a bit to accommodate // the onload callback fires, so we loop a bit to accommodate
@ -355,7 +623,8 @@ $.fn.ajaxSubmit = function(options) {
} }
//log('response detected'); //log('response detected');
xhr.responseText = doc.body ? doc.body.innerHTML : doc.documentElement ? doc.documentElement.innerHTML : null; var docRoot = doc.body ? doc.body : doc.documentElement;
xhr.responseText = docRoot ? docRoot.innerHTML : null;
xhr.responseXML = doc.XMLDocument ? doc.XMLDocument : doc; xhr.responseXML = doc.XMLDocument ? doc.XMLDocument : doc;
if (isXml) if (isXml)
s.dataType = 'xml'; s.dataType = 'xml';
@ -363,58 +632,89 @@ $.fn.ajaxSubmit = function(options) {
var headers = {'content-type': s.dataType}; var headers = {'content-type': s.dataType};
return headers[header]; return headers[header];
}; };
// support for XHR 'status' & 'statusText' emulation :
if (docRoot) {
xhr.status = Number( docRoot.getAttribute('status') ) || xhr.status;
xhr.statusText = docRoot.getAttribute('statusText') || xhr.statusText;
}
var scr = /(json|script|text)/.test(s.dataType); var dt = (s.dataType || '').toLowerCase();
var scr = /(json|script|text)/.test(dt);
if (scr || s.textarea) { if (scr || s.textarea) {
// see if user embedded response in textarea // see if user embedded response in textarea
var ta = doc.getElementsByTagName('textarea')[0]; var ta = doc.getElementsByTagName('textarea')[0];
if (ta) { if (ta) {
xhr.responseText = ta.value; xhr.responseText = ta.value;
// support for XHR 'status' & 'statusText' emulation :
xhr.status = Number( ta.getAttribute('status') ) || xhr.status;
xhr.statusText = ta.getAttribute('statusText') || xhr.statusText;
} }
else if (scr) { else if (scr) {
// account for browsers injecting pre around json response // account for browsers injecting pre around json response
var pre = doc.getElementsByTagName('pre')[0]; var pre = doc.getElementsByTagName('pre')[0];
var b = doc.getElementsByTagName('body')[0]; var b = doc.getElementsByTagName('body')[0];
if (pre) { if (pre) {
xhr.responseText = pre.textContent; xhr.responseText = pre.textContent ? pre.textContent : pre.innerText;
} }
else if (b) { else if (b) {
xhr.responseText = b.innerHTML; xhr.responseText = b.textContent ? b.textContent : b.innerText;
} }
} }
} }
else if (s.dataType == 'xml' && !xhr.responseXML && xhr.responseText != null) { else if (dt == 'xml' && !xhr.responseXML && xhr.responseText) {
xhr.responseXML = toXml(xhr.responseText); xhr.responseXML = toXml(xhr.responseText);
} }
data = httpData(xhr, s.dataType, s); try {
data = httpData(xhr, dt, s);
} }
catch(e){ catch (err) {
log('error caught:',e); status = 'parsererror';
ok = false; xhr.error = errMsg = (err || status);
xhr.error = e; }
s.error && s.error.call(s.context, xhr, 'error', e); }
g && $.event.trigger("ajaxError", [xhr, s, e]); catch (err) {
log('error caught: ',err);
status = 'error';
xhr.error = errMsg = (err || status);
} }
if (xhr.aborted) { if (xhr.aborted) {
log('upload aborted'); log('upload aborted');
ok = false; status = null;
}
if (xhr.status) { // we've set xhr.status
status = (xhr.status >= 200 && xhr.status < 300 || xhr.status === 304) ? 'success' : 'error';
} }
// ordering of these callbacks/triggers is odd, but that's how $.ajax does it // ordering of these callbacks/triggers is odd, but that's how $.ajax does it
if (ok) { if (status === 'success') {
s.success && s.success.call(s.context, data, 'success', xhr); if (s.success)
g && $.event.trigger("ajaxSuccess", [xhr, s]); s.success.call(s.context, data, 'success', xhr);
deferred.resolve(xhr.responseText, 'success', xhr);
if (g)
$.event.trigger("ajaxSuccess", [xhr, s]);
}
else if (status) {
if (errMsg === undefined)
errMsg = xhr.statusText;
if (s.error)
s.error.call(s.context, xhr, status, errMsg);
deferred.reject(xhr, 'error', errMsg);
if (g)
$.event.trigger("ajaxError", [xhr, s, errMsg]);
} }
g && $.event.trigger("ajaxComplete", [xhr, s]); if (g)
$.event.trigger("ajaxComplete", [xhr, s]);
if (g && ! --$.active) { if (g && ! --$.active) {
$.event.trigger("ajaxStop"); $.event.trigger("ajaxStop");
} }
s.complete && s.complete.call(s.context, xhr, ok ? 'success' : 'error'); if (s.complete)
s.complete.call(s.context, xhr, status);
callbackProcessed = true; callbackProcessed = true;
if (s.timeout) if (s.timeout)
@ -422,7 +722,7 @@ $.fn.ajaxSubmit = function(options) {
// clean up // clean up
setTimeout(function() { setTimeout(function() {
$io.removeData('form-plugin-onload'); if (!s.iframeTarget)
$io.remove(); $io.remove();
xhr.responseXML = null; xhr.responseXML = null;
}, 100); }, 100);
@ -440,16 +740,19 @@ $.fn.ajaxSubmit = function(options) {
return (doc && doc.documentElement && doc.documentElement.nodeName != 'parsererror') ? doc : null; return (doc && doc.documentElement && doc.documentElement.nodeName != 'parsererror') ? doc : null;
}; };
var parseJSON = $.parseJSON || function(s) { var parseJSON = $.parseJSON || function(s) {
/*jslint evil:true */
return window['eval']('(' + s + ')'); return window['eval']('(' + s + ')');
}; };
var httpData = function( xhr, type, s ) { // mostly lifted from jq1.4.4 var httpData = function( xhr, type, s ) { // mostly lifted from jq1.4.4
var ct = xhr.getResponseHeader('content-type') || '', var ct = xhr.getResponseHeader('content-type') || '',
xml = type === 'xml' || !type && ct.indexOf('xml') >= 0, xml = type === 'xml' || !type && ct.indexOf('xml') >= 0,
data = xml ? xhr.responseXML : xhr.responseText; data = xml ? xhr.responseXML : xhr.responseText;
if (xml && data.documentElement.nodeName === 'parsererror') { if (xml && data.documentElement.nodeName === 'parsererror') {
$.error && $.error('parsererror'); if ($.error)
$.error('parsererror');
} }
if (s && s.dataFilter) { if (s && s.dataFilter) {
data = s.dataFilter(data, type); data = s.dataFilter(data, type);
@ -463,6 +766,8 @@ $.fn.ajaxSubmit = function(options) {
} }
return data; return data;
}; };
return deferred;
} }
}; };
@ -482,8 +787,11 @@ $.fn.ajaxSubmit = function(options) {
* the form itself. * the form itself.
*/ */
$.fn.ajaxForm = function(options) { $.fn.ajaxForm = function(options) {
options = options || {};
options.delegation = options.delegation && $.isFunction($.fn.on);
// in jQuery 1.3+ we can fix mistakes with the ready state // in jQuery 1.3+ we can fix mistakes with the ready state
if (this.length === 0) { if (!options.delegation && this.length === 0) {
var o = { s: this.selector, c: this.context }; var o = { s: this.selector, c: this.context };
if (!$.isReady && o.s) { if (!$.isReady && o.s) {
log('DOM not ready, queuing ajaxForm'); log('DOM not ready, queuing ajaxForm');
@ -497,18 +805,38 @@ $.fn.ajaxForm = function(options) {
return this; return this;
} }
return this.ajaxFormUnbind().bind('submit.form-plugin', function(e) { if ( options.delegation ) {
$(document)
.off('submit.form-plugin', this.selector, doAjaxSubmit)
.off('click.form-plugin', this.selector, captureSubmittingElement)
.on('submit.form-plugin', this.selector, options, doAjaxSubmit)
.on('click.form-plugin', this.selector, options, captureSubmittingElement);
return this;
}
return this.ajaxFormUnbind()
.bind('submit.form-plugin', options, doAjaxSubmit)
.bind('click.form-plugin', options, captureSubmittingElement);
};
// private event handlers
function doAjaxSubmit(e) {
/*jshint validthis:true */
var options = e.data;
if (!e.isDefaultPrevented()) { // if event has been canceled, don't proceed if (!e.isDefaultPrevented()) { // if event has been canceled, don't proceed
e.preventDefault(); e.preventDefault();
$(this).ajaxSubmit(options); $(this).ajaxSubmit(options);
} }
}).bind('click.form-plugin', function(e) { }
function captureSubmittingElement(e) {
/*jshint validthis:true */
var target = e.target; var target = e.target;
var $el = $(target); var $el = $(target);
if (!($el.is(":submit,input:image"))) { if (!($el.is("[type=submit],[type=image]"))) {
// is this a child element of the submit el? (ex: a span within a button) // is this a child element of the submit el? (ex: a span within a button)
var t = $el.closest(':submit'); var t = $el.closest('[type=submit]');
if (t.length == 0) { if (t.length === 0) {
return; return;
} }
target = t[0]; target = t[0];
@ -516,10 +844,10 @@ $.fn.ajaxForm = function(options) {
var form = this; var form = this;
form.clk = target; form.clk = target;
if (target.type == 'image') { if (target.type == 'image') {
if (e.offsetX != undefined) { if (e.offsetX !== undefined) {
form.clk_x = e.offsetX; form.clk_x = e.offsetX;
form.clk_y = e.offsetY; form.clk_y = e.offsetY;
} else if (typeof $.fn.offset == 'function') { // try to use dimensions plugin } else if (typeof $.fn.offset == 'function') {
var offset = $el.offset(); var offset = $el.offset();
form.clk_x = e.pageX - offset.left; form.clk_x = e.pageX - offset.left;
form.clk_y = e.pageY - offset.top; form.clk_y = e.pageY - offset.top;
@ -530,8 +858,8 @@ $.fn.ajaxForm = function(options) {
} }
// clear form vars // clear form vars
setTimeout(function() { form.clk = form.clk_x = form.clk_y = null; }, 100); setTimeout(function() { form.clk = form.clk_x = form.clk_y = null; }, 100);
}); }
};
// ajaxFormUnbind unbinds the event handlers that were bound by ajaxForm // ajaxFormUnbind unbinds the event handlers that were bound by ajaxForm
$.fn.ajaxFormUnbind = function() { $.fn.ajaxFormUnbind = function() {
@ -549,7 +877,7 @@ $.fn.ajaxFormUnbind = function() {
* It is this array that is passed to pre-submit callback functions provided to the * It is this array that is passed to pre-submit callback functions provided to the
* ajaxSubmit() and ajaxForm() methods. * ajaxSubmit() and ajaxForm() methods.
*/ */
$.fn.formToArray = function(semantic) { $.fn.formToArray = function(semantic, elements) {
var a = []; var a = [];
if (this.length === 0) { if (this.length === 0) {
return a; return a;
@ -565,14 +893,14 @@ $.fn.formToArray = function(semantic) {
for(i=0, max=els.length; i < max; i++) { for(i=0, max=els.length; i < max; i++) {
el = els[i]; el = els[i];
n = el.name; n = el.name;
if (!n) { if (!n || el.disabled) {
continue; continue;
} }
if (semantic && form.clk && el.type == "image") { if (semantic && form.clk && el.type == "image") {
// handle image inputs on the fly when semantic == true // handle image inputs on the fly when semantic == true
if(!el.disabled && form.clk == el) { if(form.clk == el) {
a.push({name: n, value: $(el).val()}); a.push({name: n, value: $(el).val(), type: el.type });
a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y}); a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
} }
continue; continue;
@ -580,12 +908,30 @@ $.fn.formToArray = function(semantic) {
v = $.fieldValue(el, true); v = $.fieldValue(el, true);
if (v && v.constructor == Array) { if (v && v.constructor == Array) {
if (elements)
elements.push(el);
for(j=0, jmax=v.length; j < jmax; j++) { for(j=0, jmax=v.length; j < jmax; j++) {
a.push({name: n, value: v[j]}); a.push({name: n, value: v[j]});
} }
} }
else if (feature.fileapi && el.type == 'file') {
if (elements)
elements.push(el);
var files = el.files;
if (files.length) {
for (j=0; j < files.length; j++) {
a.push({name: n, value: files[j], type: el.type});
}
}
else {
// #180
a.push({ name: n, value: '', type: el.type });
}
}
else if (v !== null && typeof v != 'undefined') { else if (v !== null && typeof v != 'undefined') {
a.push({name: n, value: v}); if (elements)
elements.push(el);
a.push({name: n, value: v, type: el.type, required: el.required});
} }
} }
@ -647,19 +993,19 @@ $.fn.fieldSerialize = function(successful) {
* <input name="C" type="radio" value="C2" /> * <input name="C" type="radio" value="C2" />
* </fieldset></form> * </fieldset></form>
* *
* var v = $(':text').fieldValue(); * var v = $('input[type=text]').fieldValue();
* // if no values are entered into the text inputs * // if no values are entered into the text inputs
* v == ['',''] * v == ['','']
* // if values entered into the text inputs are 'foo' and 'bar' * // if values entered into the text inputs are 'foo' and 'bar'
* v == ['foo','bar'] * v == ['foo','bar']
* *
* var v = $(':checkbox').fieldValue(); * var v = $('input[type=checkbox]').fieldValue();
* // if neither checkbox is checked * // if neither checkbox is checked
* v === undefined * v === undefined
* // if both checkboxes are checked * // if both checkboxes are checked
* v == ['B1', 'B2'] * v == ['B1', 'B2']
* *
* var v = $(':radio').fieldValue(); * var v = $('input[type=radio]').fieldValue();
* // if neither radio is checked * // if neither radio is checked
* v === undefined * v === undefined
* // if first radio is checked * // if first radio is checked
@ -680,7 +1026,10 @@ $.fn.fieldValue = function(successful) {
if (v === null || typeof v == 'undefined' || (v.constructor == Array && !v.length)) { if (v === null || typeof v == 'undefined' || (v.constructor == Array && !v.length)) {
continue; continue;
} }
v.constructor == Array ? $.merge(val, v) : val.push(v); if (v.constructor == Array)
$.merge(val, v);
else
val.push(v);
} }
return val; return val;
}; };
@ -735,19 +1084,20 @@ $.fieldValue = function(el, successful) {
* - inputs of type submit, button, reset, and hidden will *not* be effected * - inputs of type submit, button, reset, and hidden will *not* be effected
* - button elements will *not* be effected * - button elements will *not* be effected
*/ */
$.fn.clearForm = function() { $.fn.clearForm = function(includeHidden) {
return this.each(function() { return this.each(function() {
$('input,select,textarea', this).clearFields(); $('input,select,textarea', this).clearFields(includeHidden);
}); });
}; };
/** /**
* Clears the selected form elements. * Clears the selected form elements.
*/ */
$.fn.clearFields = $.fn.clearInputs = function() { $.fn.clearFields = $.fn.clearInputs = function(includeHidden) {
var re = /^(?:color|date|datetime|email|month|number|password|range|search|tel|text|time|url|week)$/i; // 'hidden' is not in this list
return this.each(function() { return this.each(function() {
var t = this.type, tag = this.tagName.toLowerCase(); var t = this.type, tag = this.tagName.toLowerCase();
if (t == 'text' || t == 'password' || tag == 'textarea') { if (re.test(t) || tag == 'textarea') {
this.value = ''; this.value = '';
} }
else if (t == 'checkbox' || t == 'radio') { else if (t == 'checkbox' || t == 'radio') {
@ -755,6 +1105,22 @@ $.fn.clearFields = $.fn.clearInputs = function() {
} }
else if (tag == 'select') { else if (tag == 'select') {
this.selectedIndex = -1; this.selectedIndex = -1;
}
else if (t == "file") {
if (/MSIE/.test(navigator.userAgent)) {
$(this).replaceWith($(this).clone(true));
} else {
$(this).val('');
}
}
else if (includeHidden) {
// includeHidden can be the value true, or it can be a selector string
// indicating a special test; for example:
// $('#myForm').clearForm('.special:hidden')
// the above would clean hidden inputs that have the class of 'special'
if ( (includeHidden === true && /hidden/.test(t)) ||
(typeof includeHidden == 'string' && $(this).is(includeHidden)) )
this.value = '';
} }
}); });
}; };
@ -808,10 +1174,13 @@ $.fn.selected = function(select) {
}); });
}; };
// expose debug var
$.fn.ajaxSubmit.debug = false;
// helper fn for console logging // helper fn for console logging
// set $.fn.ajaxSubmit.debug to true to enable debug logging
function log() { function log() {
if ($.fn.ajaxSubmit.debug) { if (!$.fn.ajaxSubmit.debug)
return;
var msg = '[jquery.form] ' + Array.prototype.join.call(arguments,''); var msg = '[jquery.form] ' + Array.prototype.join.call(arguments,'');
if (window.console && window.console.log) { if (window.console && window.console.log) {
window.console.log(msg); window.console.log(msg);
@ -819,7 +1188,6 @@ function log() {
else if (window.opera && window.opera.postError) { else if (window.opera && window.opera.postError) {
window.opera.postError(msg); window.opera.postError(msg);
} }
} }
};
})(jQuery); })(jQuery);

File diff suppressed because one or more lines are too long

View File

@ -182,7 +182,7 @@ function wp_default_scripts( &$scripts ) {
$scripts->add( 'jquery-ui-widget', '/wp-includes/js/jquery/ui/jquery.ui.widget.min.js', array('jquery'), '1.10.3', 1 ); $scripts->add( 'jquery-ui-widget', '/wp-includes/js/jquery/ui/jquery.ui.widget.min.js', array('jquery'), '1.10.3', 1 );
// deprecated, not used in core, most functionality is included in jQuery 1.3 // deprecated, not used in core, most functionality is included in jQuery 1.3
$scripts->add( 'jquery-form', "/wp-includes/js/jquery/jquery.form$suffix.js", array('jquery'), '2.73', 1 ); $scripts->add( 'jquery-form', "/wp-includes/js/jquery/jquery.form$suffix.js", array('jquery'), '3.37.0', 1 );
// jQuery plugins // jQuery plugins
$scripts->add( 'jquery-color', "/wp-includes/js/jquery/jquery.color.min.js", array('jquery'), '2.1.1', 1 ); $scripts->add( 'jquery-color', "/wp-includes/js/jquery/jquery.color.min.js", array('jquery'), '2.1.1', 1 );