summaryrefslogtreecommitdiff
path: root/resources/jquery/jquery.form.js
diff options
context:
space:
mode:
Diffstat (limited to 'resources/jquery/jquery.form.js')
-rw-r--r--resources/jquery/jquery.form.js310
1 files changed, 215 insertions, 95 deletions
diff --git a/resources/jquery/jquery.form.js b/resources/jquery/jquery.form.js
index 53c078f9..fdcdd15a 100644
--- a/resources/jquery/jquery.form.js
+++ b/resources/jquery/jquery.form.js
@@ -1,6 +1,6 @@
/*!
* jQuery Form Plugin
- * version: 2.52 (07-DEC-2010)
+ * version: 2.84 (12-AUG-2011)
* @requires jQuery v1.3.2 or later
*
* Examples and documentation at: http://malsup.com/jquery/form/
@@ -8,7 +8,7 @@
* http://www.opensource.org/licenses/mit-license.php
* http://www.gnu.org/licenses/gpl.html
*/
-(function($) {
+;(function($) {
/*
Usage Note:
@@ -49,22 +49,26 @@ $.fn.ajaxSubmit = function(options) {
log('ajaxSubmit: skipping submit process - no element selected');
return this;
}
+
+ var method, action, url, $form = this;
if (typeof options == 'function') {
options = { success: options };
}
- var action = this.attr('action');
- var url = (typeof action === 'string') ? $.trim(action) : '';
+ method = this.attr('method');
+ action = this.attr('action');
+ url = (typeof action === 'string') ? $.trim(action) : '';
+ url = url || window.location.href || '';
if (url) {
// clean url (don't include hash vaue)
url = (url.match(/^([^#]+)/)||[])[1];
}
- url = url || window.location.href || '';
options = $.extend(true, {
url: url,
- type: this.attr('method') || 'GET',
+ success: $.ajaxSettings.success,
+ type: method || 'GET',
iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank'
}, options);
@@ -87,7 +91,7 @@ $.fn.ajaxSubmit = function(options) {
if (options.data) {
options.extraData = options.data;
for (n in options.data) {
- if(options.data[n] instanceof Array) {
+ if( $.isArray(options.data[n]) ) {
for (var k in options.data[n]) {
a.push( { name: n, value: options.data[n][k] } );
}
@@ -123,7 +127,7 @@ $.fn.ajaxSubmit = function(options) {
options.data = q; // data is the query string for 'post'
}
- var $form = this, callbacks = [];
+ var callbacks = [];
if (options.resetForm) {
callbacks.push(function() { $form.resetForm(); });
}
@@ -161,14 +165,20 @@ $.fn.ajaxSubmit = function(options) {
// hack to fix Safari hang (thanks to Tim Molendijk for this)
// see: http://groups.google.com/group/jquery-dev/browse_thread/thread/36395b7ab510dd5d
if (options.closeKeepAlive) {
- $.get(options.closeKeepAlive, fileUpload);
+ $.get(options.closeKeepAlive, function() { fileUpload(a); });
}
else {
- fileUpload();
+ fileUpload(a);
}
}
else {
- $.ajax(options);
+ // IE7 massage (see issue 57)
+ if ($.browser.msie && method == 'get') {
+ var ieMeth = $form[0].getAttribute('method');
+ if (typeof ieMeth === 'string')
+ options.type = ieMeth;
+ }
+ $.ajax(options);
}
// fire 'notify' event
@@ -177,8 +187,17 @@ $.fn.ajaxSubmit = function(options) {
// private function for handling file uploads (hat tip to YAHOO!)
- function fileUpload() {
- var form = $form[0];
+ function fileUpload(a) {
+ var form = $form[0], el, i, s, g, id, $io, io, xhr, sub, n, timedOut, timeoutHandle;
+ var useProp = !!$.fn.prop;
+
+ if (a) {
+ // ensure that every serialized input is still enabled
+ for (i=0; i < a.length; i++) {
+ el = $(form[a[i].name]);
+ el[ useProp ? 'prop' : 'attr' ]('disabled', false);
+ }
+ }
if ($(':input[name=submit],:input[id=submit]', form).length) {
// if there is an input with a name or id of 'submit' then we won't be
@@ -187,23 +206,25 @@ $.fn.ajaxSubmit = function(options) {
return;
}
- var s = $.extend(true, {}, $.ajaxSettings, options);
+ s = $.extend(true, {}, $.ajaxSettings, options);
s.context = s.context || s;
- var id = 'jqFormIO' + (new Date().getTime()), fn = '_'+id;
- window[fn] = function() {
- var f = $io.data('form-plugin-onload');
- if (f) {
- f();
- window[fn] = undefined;
- try { delete window[fn]; } catch(e){}
- }
- };
- var $io = $('<iframe id="' + id + '" name="' + id + '" src="'+ s.iframeSrc +'" onload="window[\'_\'+this.id]()" />');
- var io = $io[0];
+ id = 'jqFormIO' + (new Date().getTime());
+ if (s.iframeTarget) {
+ $io = $(s.iframeTarget);
+ n = $io.attr('name');
+ if (n == null)
+ $io.attr('name', id);
+ else
+ id = n;
+ }
+ else {
+ $io = $('<iframe name="' + id + '" src="'+ s.iframeSrc +'" />');
+ $io.css({ position: 'absolute', top: '-1000px', left: '-1000px' });
+ }
+ io = $io[0];
- $io.css({ position: 'absolute', top: '-1000px', left: '-1000px' });
- var xhr = { // mock object
+ xhr = { // mock object
aborted: 0,
responseText: null,
responseXML: null,
@@ -212,13 +233,19 @@ $.fn.ajaxSubmit = function(options) {
getAllResponseHeaders: function() {},
getResponseHeader: function() {},
setRequestHeader: function() {},
- abort: function() {
+ abort: function(status) {
+ var e = (status === 'timeout' ? 'timeout' : 'aborted');
+ log('aborting upload... ' + e);
this.aborted = 1;
$io.attr('src', s.iframeSrc); // abort op in progress
+ xhr.error = e;
+ s.error && s.error.call(s.context, xhr, e, status);
+ g && $.event.trigger("ajaxError", [xhr, s, e]);
+ 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
if (g && ! $.active++) {
$.event.trigger("ajaxStart");
@@ -228,7 +255,7 @@ $.fn.ajaxSubmit = function(options) {
}
if (s.beforeSend && s.beforeSend.call(s.context, xhr, s) === false) {
- if (s.global) {
+ if (s.global) {
$.active--;
}
return;
@@ -237,13 +264,10 @@ $.fn.ajaxSubmit = function(options) {
return;
}
- var cbInvoked = false;
- var timedOut = 0;
-
// add submitting element to data if we know it
- var sub = form.clk;
+ sub = form.clk;
if (sub) {
- var n = sub.name;
+ n = sub.name;
if (n && !sub.disabled) {
s.extraData = s.extraData || {};
s.extraData[n] = sub.value;
@@ -253,7 +277,15 @@ $.fn.ajaxSubmit = function(options) {
}
}
}
+
+ var CLIENT_TIMEOUT_ABORT = 1;
+ var SERVER_ABORT = 2;
+ function getDoc(frame) {
+ var doc = frame.contentWindow ? frame.contentWindow.document : frame.contentDocument ? frame.contentDocument : frame.document;
+ return doc;
+ }
+
// take a breath so that pending repaints get some cpu time before the upload starts
function doSubmit() {
// make sure form attrs are set
@@ -261,15 +293,15 @@ $.fn.ajaxSubmit = function(options) {
// update form attrs in IE friendly way
form.setAttribute('target',id);
- if (form.getAttribute('method') != 'POST') {
+ if (!method) {
form.setAttribute('method', 'POST');
}
- if (form.getAttribute('action') != s.url) {
+ if (a != s.url) {
form.setAttribute('action', s.url);
}
// ie borks in some cases when setting encoding
- if (! s.skipEncodingOverride) {
+ if (! s.skipEncodingOverride && (!method || /post/i.test(method))) {
$form.attr({
encoding: 'multipart/form-data',
enctype: 'multipart/form-data'
@@ -278,7 +310,23 @@ $.fn.ajaxSubmit = function(options) {
// support timout
if (s.timeout) {
- setTimeout(function() { timedOut = true; cb(); }, 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.toLowerCase() == 'uninitialized')
+ setTimeout(checkState,50);
+ }
+ catch(e) {
+ log('Server abort: ' , e, ' (', e.name, ')');
+ cb(SERVER_ABORT);
+ timeoutHandle && clearTimeout(timeoutHandle);
+ timeoutHandle = undefined;
+ }
}
// add "extra" data to form if provided in options
@@ -287,14 +335,17 @@ $.fn.ajaxSubmit = function(options) {
if (s.extraData) {
for (var n in s.extraData) {
extraInputs.push(
- $('<input type="hidden" name="'+n+'" value="'+s.extraData[n]+'" />')
+ $('<input type="hidden" name="'+n+'" />').attr('value',s.extraData[n])
.appendTo(form)[0]);
}
}
- // add iframe to doc and submit the form
- $io.appendTo('body');
- $io.data('form-plugin-onload', cb);
+ if (!s.iframeTarget) {
+ // add iframe to doc and submit the form
+ $io.appendTo('body');
+ io.attachEvent ? io.attachEvent('onload', cb) : io.addEventListener('load', cb, false);
+ }
+ setTimeout(checkState,15);
form.submit();
}
finally {
@@ -315,24 +366,42 @@ $.fn.ajaxSubmit = function(options) {
else {
setTimeout(doSubmit, 10); // this lets dom updates render
}
-
- var data, doc, domCheckCount = 50;
- function cb() {
- if (cbInvoked) {
+ var data, doc, domCheckCount = 50, callbackProcessed;
+
+ function cb(e) {
+ if (xhr.aborted || callbackProcessed) {
+ return;
+ }
+ try {
+ doc = getDoc(io);
+ }
+ catch(ex) {
+ log('cannot access response document: ', ex);
+ e = SERVER_ABORT;
+ }
+ if (e === CLIENT_TIMEOUT_ABORT && xhr) {
+ xhr.abort('timeout');
+ return;
+ }
+ else if (e == SERVER_ABORT && xhr) {
+ xhr.abort('server abort');
return;
}
- $io.removeData('form-plugin-onload');
-
- var ok = true;
+ if (!doc || doc.location.href == s.iframeSrc) {
+ // response not received yet
+ if (!timedOut)
+ return;
+ }
+ io.detachEvent ? io.detachEvent('onload', cb) : io.removeEventListener('load', cb, false);
+
+ var status = 'success', errMsg;
try {
if (timedOut) {
throw 'timeout';
}
- // extract the server response from the iframe
- doc = io.contentWindow ? io.contentWindow.document : io.contentDocument ? io.contentDocument : io.document;
-
+
var isXml = s.dataType == 'xml' || doc.XMLDocument || $.isXMLDoc(doc);
log('isXml='+isXml);
if (!isXml && window.opera && (doc.body == null || doc.body.innerHTML == '')) {
@@ -349,76 +418,104 @@ $.fn.ajaxSubmit = function(options) {
}
//log('response detected');
- cbInvoked = true;
- xhr.responseText = 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;
+ if (isXml)
+ s.dataType = 'xml';
xhr.getResponseHeader = function(header){
var headers = {'content-type': s.dataType};
return headers[header];
};
-
- var scr = /(json|script)/.test(s.dataType);
+ // support for XHR 'status' & 'statusText' emulation :
+ if (docRoot) {
+ xhr.status = Number( docRoot.getAttribute('status') ) || xhr.status;
+ xhr.statusText = docRoot.getAttribute('statusText') || xhr.statusText;
+ }
+
+ var dt = s.dataType || '';
+ var scr = /(json|script|text)/.test(dt.toLowerCase());
if (scr || s.textarea) {
// see if user embedded response in textarea
var ta = doc.getElementsByTagName('textarea')[0];
if (ta) {
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) {
// account for browsers injecting pre around json response
var pre = doc.getElementsByTagName('pre')[0];
var b = doc.getElementsByTagName('body')[0];
if (pre) {
- xhr.responseText = pre.textContent;
+ xhr.responseText = pre.textContent ? pre.textContent : pre.innerHTML;
}
else if (b) {
xhr.responseText = b.innerHTML;
}
- }
+ }
}
else if (s.dataType == 'xml' && !xhr.responseXML && xhr.responseText != null) {
xhr.responseXML = toXml(xhr.responseText);
}
- data = $.httpData(xhr, s.dataType);
+
+ try {
+ data = httpData(xhr, s.dataType, s);
+ }
+ catch (e) {
+ status = 'parsererror';
+ xhr.error = errMsg = (e || status);
+ }
}
- catch(e){
- log('error caught:',e);
- ok = false;
- xhr.error = e;
- $.handleError(s, xhr, 'error', e);
+ catch (e) {
+ log('error caught: ',e);
+ status = 'error';
+ xhr.error = errMsg = (e || status);
}
-
+
if (xhr.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
- if (ok) {
- s.success.call(s.context, data, 'success', xhr);
- if (g) {
- $.event.trigger("ajaxSuccess", [xhr, s]);
- }
- }
- if (g) {
- $.event.trigger("ajaxComplete", [xhr, s]);
+ if (status === 'success') {
+ s.success && s.success.call(s.context, data, 'success', xhr);
+ g && $.event.trigger("ajaxSuccess", [xhr, s]);
}
+ else if (status) {
+ if (errMsg == undefined)
+ errMsg = xhr.statusText;
+ s.error && s.error.call(s.context, xhr, status, errMsg);
+ g && $.event.trigger("ajaxError", [xhr, s, errMsg]);
+ }
+
+ g && $.event.trigger("ajaxComplete", [xhr, s]);
+
if (g && ! --$.active) {
$.event.trigger("ajaxStop");
}
- if (s.complete) {
- s.complete.call(s.context, xhr, ok ? 'success' : 'error');
- }
+
+ s.complete && s.complete.call(s.context, xhr, status);
+
+ callbackProcessed = true;
+ if (s.timeout)
+ clearTimeout(timeoutHandle);
// clean up
setTimeout(function() {
- $io.removeData('form-plugin-onload');
- $io.remove();
+ if (!s.iframeTarget)
+ $io.remove();
xhr.responseXML = null;
}, 100);
}
- function toXml(s, doc) {
+ var toXml = $.parseXML || function(s, doc) { // use parseXML if available (jQuery 1.5+)
if (window.ActiveXObject) {
doc = new ActiveXObject('Microsoft.XMLDOM');
doc.async = 'false';
@@ -427,8 +524,33 @@ $.fn.ajaxSubmit = function(options) {
else {
doc = (new DOMParser()).parseFromString(s, 'text/xml');
}
- return (doc && doc.documentElement && doc.documentElement.tagName != 'parsererror') ? doc : null;
- }
+ return (doc && doc.documentElement && doc.documentElement.nodeName != 'parsererror') ? doc : null;
+ };
+ var parseJSON = $.parseJSON || function(s) {
+ return window['eval']('(' + s + ')');
+ };
+
+ var httpData = function( xhr, type, s ) { // mostly lifted from jq1.4.4
+
+ var ct = xhr.getResponseHeader('content-type') || '',
+ xml = type === 'xml' || !type && ct.indexOf('xml') >= 0,
+ data = xml ? xhr.responseXML : xhr.responseText;
+
+ if (xml && data.documentElement.nodeName === 'parsererror') {
+ $.error && $.error('parsererror');
+ }
+ if (s && s.dataFilter) {
+ data = s.dataFilter(data, type);
+ }
+ if (typeof data === 'string') {
+ if (type === 'json' || !type && ct.indexOf('json') >= 0) {
+ data = parseJSON(data);
+ } else if (type === "script" || !type && ct.indexOf("javascript") >= 0) {
+ $.globalEval(data);
+ }
+ }
+ return data;
+ };
}
};
@@ -462,7 +584,7 @@ $.fn.ajaxForm = function(options) {
log('terminating; zero elements found by selector' + ($.isReady ? '' : ' (DOM not ready)'));
return this;
}
-
+
return this.ajaxFormUnbind().bind('submit.form-plugin', function(e) {
if (!e.isDefaultPrevented()) { // if event has been canceled, don't proceed
e.preventDefault();
@@ -526,7 +648,7 @@ $.fn.formToArray = function(semantic) {
if (!els) {
return a;
}
-
+
var i,j,n,v,el,max,jmax;
for(i=0, max=els.length; i < max; i++) {
el = els[i];
@@ -711,9 +833,10 @@ $.fn.clearForm = function() {
* Clears the selected form elements.
*/
$.fn.clearFields = $.fn.clearInputs = function() {
+ 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() {
var t = this.type, tag = this.tagName.toLowerCase();
- if (t == 'text' || t == 'password' || tag == 'textarea') {
+ if (re.test(t) || tag == 'textarea') {
this.value = '';
}
else if (t == 'checkbox' || t == 'radio') {
@@ -775,16 +898,13 @@ $.fn.selected = function(select) {
};
// helper fn for console logging
-// set $.fn.ajaxSubmit.debug to true to enable debug logging
function log() {
- if ($.fn.ajaxSubmit.debug) {
- var msg = '[jquery.form] ' + Array.prototype.join.call(arguments,'');
- if (window.console && window.console.log) {
- window.console.log(msg);
- }
- else if (window.opera && window.opera.postError) {
- window.opera.postError(msg);
- }
+ var msg = '[jquery.form] ' + Array.prototype.join.call(arguments,'');
+ if (window.console && window.console.log) {
+ window.console.log(msg);
+ }
+ else if (window.opera && window.opera.postError) {
+ window.opera.postError(msg);
}
};