joosy 1.1.1 → 1.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/joosy/version.rb +1 -1
- data/spec/javascripts/joosy/core/form_spec.js.coffee +1 -1
- data/vendor/assets/javascripts/jquery.form.js +1044 -849
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 46505115460ed2431dd17b9d3f65f8e01247bbea
|
4
|
+
data.tar.gz: 881b8abb52e4388865350b5135c88afa1a1f105b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a706ddbb53453e9635c2d4104a9571b8037d339c8f0db31bbe89a67e8a281e0434a7ebb3b84b3909cb08e812270594cbcf7864aa3719176d43e4e767008d5abb
|
7
|
+
data.tar.gz: 00c702eaa564ea00c7121d11d28f36d62e908dc05cfebe2648a44be21c89c857d411acdbceabc670593453137dd85297ca252eda2e1488b115004fb600a16c95
|
data/lib/joosy/version.rb
CHANGED
@@ -230,7 +230,7 @@ describe "Joosy.Form", ->
|
|
230
230
|
|
231
231
|
it "should trigger 'success'", ->
|
232
232
|
expect(@target.method).toEqual 'POST'
|
233
|
-
expect(@target.url).
|
233
|
+
expect(@target.url).toMatch /.*?\/tests\/1/
|
234
234
|
@target.respond 200, 'Content-Type': 'application/json', '{"form": "works"}'
|
235
235
|
expect(@spy.callCount).toEqual 1
|
236
236
|
expect(@spy.args[0][0]).toEqual {form: 'works'}
|
@@ -1,995 +1,1190 @@
|
|
1
1
|
/*!
|
2
2
|
* jQuery Form Plugin
|
3
|
-
* version:
|
4
|
-
* @requires jQuery v1.
|
5
|
-
*
|
3
|
+
* version: 3.36.0-2013.06.16
|
4
|
+
* @requires jQuery v1.5 or later
|
5
|
+
* Copyright (c) 2013 M. Alsup
|
6
6
|
* Examples and documentation at: http://malsup.com/jquery/form/
|
7
|
-
*
|
8
|
-
*
|
9
|
-
*
|
7
|
+
* Project repository: https://github.com/malsup/form
|
8
|
+
* Dual licensed under the MIT and GPL licenses.
|
9
|
+
* https://github.com/malsup/form#copyright-and-license
|
10
10
|
*/
|
11
|
+
/*global ActiveXObject */
|
11
12
|
;(function($) {
|
13
|
+
"use strict";
|
14
|
+
|
15
|
+
/*
|
16
|
+
Usage Note:
|
17
|
+
-----------
|
18
|
+
Do not use both ajaxSubmit and ajaxForm on the same form. These
|
19
|
+
functions are mutually exclusive. Use ajaxSubmit if you want
|
20
|
+
to bind your own submit handler to the form. For example,
|
21
|
+
|
22
|
+
$(document).ready(function() {
|
23
|
+
$('#myForm').on('submit', function(e) {
|
24
|
+
e.preventDefault(); // <-- important
|
25
|
+
$(this).ajaxSubmit({
|
26
|
+
target: '#output'
|
27
|
+
});
|
28
|
+
});
|
29
|
+
});
|
12
30
|
|
13
|
-
|
14
|
-
|
15
|
-
-----------
|
16
|
-
Do not use both ajaxSubmit and ajaxForm on the same form. These
|
17
|
-
functions are mutually exclusive. Use ajaxSubmit if you want
|
18
|
-
to bind your own submit handler to the form. For example,
|
19
|
-
|
20
|
-
$(document).ready(function() {
|
21
|
-
$('#myForm').bind('submit', function(e) {
|
22
|
-
e.preventDefault(); // <-- important
|
23
|
-
$(this).ajaxSubmit({
|
24
|
-
target: '#output'
|
25
|
-
});
|
26
|
-
});
|
27
|
-
});
|
28
|
-
|
29
|
-
Use ajaxForm when you want the plugin to manage all the event binding
|
30
|
-
for you. For example,
|
31
|
-
|
32
|
-
$(document).ready(function() {
|
33
|
-
$('#myForm').ajaxForm({
|
34
|
-
target: '#output'
|
35
|
-
});
|
36
|
-
});
|
37
|
-
|
38
|
-
You can also use ajaxForm with delegation (requires jQuery v1.7+), so the
|
39
|
-
form does not have to exist when you invoke ajaxForm:
|
40
|
-
|
41
|
-
$('#myForm').ajaxForm({
|
42
|
-
delegation: true,
|
43
|
-
target: '#output'
|
44
|
-
});
|
45
|
-
|
46
|
-
When using ajaxForm, the ajaxSubmit function will be invoked for you
|
47
|
-
at the appropriate time.
|
48
|
-
*/
|
49
|
-
|
50
|
-
/**
|
51
|
-
* ajaxSubmit() provides a mechanism for immediately submitting
|
52
|
-
* an HTML form using AJAX.
|
53
|
-
*/
|
54
|
-
$.fn.ajaxSubmit = function(options) {
|
55
|
-
// fast fail if nothing selected (http://dev.jquery.com/ticket/2752)
|
56
|
-
if (!this.length) {
|
57
|
-
log('ajaxSubmit: skipping submit process - no element selected');
|
58
|
-
return this;
|
59
|
-
}
|
31
|
+
Use ajaxForm when you want the plugin to manage all the event binding
|
32
|
+
for you. For example,
|
60
33
|
|
61
|
-
|
34
|
+
$(document).ready(function() {
|
35
|
+
$('#myForm').ajaxForm({
|
36
|
+
target: '#output'
|
37
|
+
});
|
38
|
+
});
|
62
39
|
|
63
|
-
|
64
|
-
|
65
|
-
}
|
40
|
+
You can also use ajaxForm with delegation (requires jQuery v1.7+), so the
|
41
|
+
form does not have to exist when you invoke ajaxForm:
|
66
42
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
if (url) {
|
72
|
-
// clean url (don't include hash vaue)
|
73
|
-
url = (url.match(/^([^#]+)/)||[])[1];
|
74
|
-
}
|
43
|
+
$('#myForm').ajaxForm({
|
44
|
+
delegation: true,
|
45
|
+
target: '#output'
|
46
|
+
});
|
75
47
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
type: method || 'GET',
|
80
|
-
iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank'
|
81
|
-
}, options);
|
48
|
+
When using ajaxForm, the ajaxSubmit function will be invoked for you
|
49
|
+
at the appropriate time.
|
50
|
+
*/
|
82
51
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
52
|
+
/**
|
53
|
+
* Feature detection
|
54
|
+
*/
|
55
|
+
var feature = {};
|
56
|
+
feature.fileapi = $("<input type='file'/>").get(0).files !== undefined;
|
57
|
+
feature.formdata = window.FormData !== undefined;
|
58
|
+
|
59
|
+
var hasProp = !!$.fn.prop;
|
60
|
+
|
61
|
+
// attr2 uses prop when it can but checks the return type for
|
62
|
+
// an expected string. this accounts for the case where a form
|
63
|
+
// contains inputs with names like "action" or "method"; in those
|
64
|
+
// cases "prop" returns the element
|
65
|
+
$.fn.attr2 = function() {
|
66
|
+
if ( ! hasProp )
|
67
|
+
return this.attr.apply(this, arguments);
|
68
|
+
var val = this.prop.apply(this, arguments);
|
69
|
+
if ( ( val && val.jquery ) || typeof val === 'string' )
|
70
|
+
return val;
|
71
|
+
return this.attr.apply(this, arguments);
|
72
|
+
};
|
91
73
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
74
|
+
/**
|
75
|
+
* ajaxSubmit() provides a mechanism for immediately submitting
|
76
|
+
* an HTML form using AJAX.
|
77
|
+
*/
|
78
|
+
$.fn.ajaxSubmit = function(options) {
|
79
|
+
/*jshint scripturl:true */
|
97
80
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
81
|
+
// fast fail if nothing selected (http://dev.jquery.com/ticket/2752)
|
82
|
+
if (!this.length) {
|
83
|
+
log('ajaxSubmit: skipping submit process - no element selected');
|
84
|
+
return this;
|
85
|
+
}
|
102
86
|
|
103
|
-
|
104
|
-
if (options.data) {
|
105
|
-
options.extraData = options.data;
|
106
|
-
qx = $.param(options.data, traditional);
|
107
|
-
}
|
87
|
+
var method, action, url, $form = this;
|
108
88
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
return this;
|
113
|
-
}
|
89
|
+
if (typeof options == 'function') {
|
90
|
+
options = { success: options };
|
91
|
+
}
|
114
92
|
|
115
|
-
|
116
|
-
|
117
|
-
if (veto.veto) {
|
118
|
-
log('ajaxSubmit: submit vetoed via form-submit-validate trigger');
|
119
|
-
return this;
|
120
|
-
}
|
93
|
+
method = options.type || this.attr2('method');
|
94
|
+
action = options.url || this.attr2('action');
|
121
95
|
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
options.data = null; // data is null for 'get'
|
129
|
-
}
|
130
|
-
else {
|
131
|
-
options.data = q; // data is the query string for 'post'
|
132
|
-
}
|
96
|
+
url = (typeof action === 'string') ? $.trim(action) : '';
|
97
|
+
url = url || window.location.href || '';
|
98
|
+
if (url) {
|
99
|
+
// clean url (don't include hash vaue)
|
100
|
+
url = (url.match(/^([^#]+)/)||[])[1];
|
101
|
+
}
|
133
102
|
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
103
|
+
options = $.extend(true, {
|
104
|
+
url: url,
|
105
|
+
success: $.ajaxSettings.success,
|
106
|
+
type: method || 'GET',
|
107
|
+
iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank'
|
108
|
+
}, options);
|
109
|
+
|
110
|
+
// hook for manipulating the form data before it is extracted;
|
111
|
+
// convenient for use with rich editors like tinyMCE or FCKEditor
|
112
|
+
var veto = {};
|
113
|
+
this.trigger('form-pre-serialize', [this, options, veto]);
|
114
|
+
if (veto.veto) {
|
115
|
+
log('ajaxSubmit: submit vetoed via form-pre-serialize trigger');
|
116
|
+
return this;
|
117
|
+
}
|
141
118
|
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
119
|
+
// provide opportunity to alter form data before it is serialized
|
120
|
+
if (options.beforeSerialize && options.beforeSerialize(this, options) === false) {
|
121
|
+
log('ajaxSubmit: submit aborted via beforeSerialize callback');
|
122
|
+
return this;
|
123
|
+
}
|
124
|
+
|
125
|
+
var traditional = options.traditional;
|
126
|
+
if ( traditional === undefined ) {
|
127
|
+
traditional = $.ajaxSettings.traditional;
|
128
|
+
}
|
129
|
+
|
130
|
+
var elements = [];
|
131
|
+
var qx, a = this.formToArray(options.semantic, elements);
|
132
|
+
if (options.data) {
|
133
|
+
options.extraData = options.data;
|
134
|
+
qx = $.param(options.data, traditional);
|
135
|
+
}
|
136
|
+
|
137
|
+
// give pre-submit callback an opportunity to abort the submit
|
138
|
+
if (options.beforeSubmit && options.beforeSubmit(a, this, options) === false) {
|
139
|
+
log('ajaxSubmit: submit aborted via beforeSubmit callback');
|
140
|
+
return this;
|
141
|
+
}
|
142
|
+
|
143
|
+
// fire vetoable 'validate' event
|
144
|
+
this.trigger('form-submit-validate', [a, this, options, veto]);
|
145
|
+
if (veto.veto) {
|
146
|
+
log('ajaxSubmit: submit vetoed via form-submit-validate trigger');
|
147
|
+
return this;
|
148
|
+
}
|
149
|
+
|
150
|
+
var q = $.param(a, traditional);
|
151
|
+
if (qx) {
|
152
|
+
q = ( q ? (q + '&' + qx) : qx );
|
153
|
+
}
|
154
|
+
if (options.type.toUpperCase() == 'GET') {
|
155
|
+
options.url += (options.url.indexOf('?') >= 0 ? '&' : '?') + q;
|
156
|
+
options.data = null; // data is null for 'get'
|
157
|
+
}
|
158
|
+
else {
|
159
|
+
options.data = q; // data is the query string for 'post'
|
160
|
+
}
|
161
|
+
|
162
|
+
var callbacks = [];
|
163
|
+
if (options.resetForm) {
|
164
|
+
callbacks.push(function() { $form.resetForm(); });
|
165
|
+
}
|
166
|
+
if (options.clearForm) {
|
167
|
+
callbacks.push(function() { $form.clearForm(options.includeHidden); });
|
168
|
+
}
|
169
|
+
|
170
|
+
// perform a load on the target only if dataType is not provided
|
171
|
+
if (!options.dataType && options.target) {
|
172
|
+
var oldSuccess = options.success || function(){};
|
173
|
+
callbacks.push(function(data) {
|
174
|
+
var fn = options.replaceTarget ? 'replaceWith' : 'html';
|
175
|
+
$(options.target)[fn](data).each(oldSuccess, arguments);
|
176
|
+
});
|
177
|
+
}
|
178
|
+
else if (options.success) {
|
179
|
+
callbacks.push(options.success);
|
180
|
+
}
|
181
|
+
|
182
|
+
options.success = function(data, status, xhr) { // jQuery 1.4+ passes xhr as 3rd arg
|
183
|
+
var context = options.context || this ; // jQuery 1.4+ supports scope context
|
184
|
+
for (var i=0, max=callbacks.length; i < max; i++) {
|
185
|
+
callbacks[i].apply(context, [data, status, xhr || $form, $form]);
|
152
186
|
}
|
187
|
+
};
|
153
188
|
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
189
|
+
if (options.error) {
|
190
|
+
var oldError = options.error;
|
191
|
+
options.error = function(xhr, status, error) {
|
192
|
+
var context = options.context || this;
|
193
|
+
oldError.apply(context, [xhr, status, error, $form]);
|
159
194
|
};
|
195
|
+
}
|
160
196
|
|
161
|
-
|
162
|
-
var
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
197
|
+
if (options.complete) {
|
198
|
+
var oldComplete = options.complete;
|
199
|
+
options.complete = function(xhr, status) {
|
200
|
+
var context = options.context || this;
|
201
|
+
oldComplete.apply(context, [xhr, status, $form]);
|
202
|
+
};
|
203
|
+
}
|
204
|
+
|
205
|
+
// are there files to upload?
|
206
|
+
|
207
|
+
// [value] (issue #113), also see comment:
|
208
|
+
// https://github.com/malsup/form/commit/588306aedba1de01388032d5f42a60159eea9228#commitcomment-2180219
|
209
|
+
var fileInputs = $('input[type=file]:enabled[value!=""]', this);
|
210
|
+
|
211
|
+
var hasFileInputs = fileInputs.length > 0;
|
212
|
+
var mp = 'multipart/form-data';
|
213
|
+
var multipart = ($form.attr('enctype') == mp || $form.attr('encoding') == mp);
|
214
|
+
|
215
|
+
var fileAPI = feature.fileapi && feature.formdata;
|
216
|
+
log("fileAPI :" + fileAPI);
|
217
|
+
var shouldUseFrame = (hasFileInputs || multipart) && !fileAPI;
|
218
|
+
|
219
|
+
var jqxhr;
|
220
|
+
|
221
|
+
// options.iframe allows user to force iframe mode
|
222
|
+
// 06-NOV-09: now defaulting to iframe mode if file input is detected
|
223
|
+
if (options.iframe !== false && (options.iframe || shouldUseFrame)) {
|
224
|
+
// hack to fix Safari hang (thanks to Tim Molendijk for this)
|
225
|
+
// see: http://groups.google.com/group/jquery-dev/browse_thread/thread/36395b7ab510dd5d
|
226
|
+
if (options.closeKeepAlive) {
|
227
|
+
$.get(options.closeKeepAlive, function() {
|
228
|
+
jqxhr = fileUploadIframe(a);
|
229
|
+
});
|
188
230
|
}
|
189
231
|
else {
|
190
|
-
|
232
|
+
jqxhr = fileUploadIframe(a);
|
191
233
|
}
|
234
|
+
}
|
235
|
+
else if ((hasFileInputs || multipart) && fileAPI) {
|
236
|
+
jqxhr = fileUploadXhr(a);
|
237
|
+
}
|
238
|
+
else {
|
239
|
+
jqxhr = $.ajax(options);
|
240
|
+
}
|
192
241
|
|
193
|
-
|
194
|
-
|
195
|
-
|
242
|
+
$form.removeData('jqxhr').data('jqxhr', jqxhr);
|
243
|
+
|
244
|
+
// clear element array
|
245
|
+
for (var k=0; k < elements.length; k++)
|
246
|
+
elements[k] = null;
|
247
|
+
|
248
|
+
// fire 'notify' event
|
249
|
+
this.trigger('form-submit-notify', [this, options]);
|
250
|
+
return this;
|
251
|
+
|
252
|
+
// utility fn for deep serialization
|
253
|
+
function deepSerialize(extraData){
|
254
|
+
var serialized = $.param(extraData, options.traditional).split('&');
|
255
|
+
var len = serialized.length;
|
256
|
+
var result = [];
|
257
|
+
var i, part;
|
258
|
+
for (i=0; i < len; i++) {
|
259
|
+
// #252; undo param space replacement
|
260
|
+
serialized[i] = serialized[i].replace(/\+/g,' ');
|
261
|
+
part = serialized[i].split('=');
|
262
|
+
// #278; use array instead of object storage, favoring array serializations
|
263
|
+
result.push([decodeURIComponent(part[0]), decodeURIComponent(part[1])]);
|
264
|
+
}
|
265
|
+
return result;
|
266
|
+
}
|
196
267
|
|
197
|
-
|
198
|
-
|
199
|
-
|
268
|
+
// XMLHttpRequest Level 2 file uploads (big hat tip to francois2metz)
|
269
|
+
function fileUploadXhr(a) {
|
270
|
+
var formdata = new FormData();
|
200
271
|
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
272
|
+
for (var i=0; i < a.length; i++) {
|
273
|
+
formdata.append(a[i].name, a[i].value);
|
274
|
+
}
|
275
|
+
|
276
|
+
if (options.extraData) {
|
277
|
+
var serializedData = deepSerialize(options.extraData);
|
278
|
+
for (i=0; i < serializedData.length; i++)
|
279
|
+
if (serializedData[i])
|
280
|
+
formdata.append(serializedData[i][0], serializedData[i][1]);
|
281
|
+
}
|
205
282
|
|
206
|
-
|
283
|
+
options.data = null;
|
207
284
|
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
285
|
+
var s = $.extend(true, {}, $.ajaxSettings, options, {
|
286
|
+
contentType: false,
|
287
|
+
processData: false,
|
288
|
+
cache: false,
|
289
|
+
type: method || 'POST'
|
290
|
+
});
|
214
291
|
|
215
|
-
|
292
|
+
if (options.uploadProgress) {
|
293
|
+
// workaround because jqXHR does not expose upload property
|
294
|
+
s.xhr = function() {
|
295
|
+
var xhr = $.ajaxSettings.xhr();
|
296
|
+
if (xhr.upload) {
|
297
|
+
xhr.upload.addEventListener('progress', function(event) {
|
298
|
+
var percent = 0;
|
299
|
+
var position = event.loaded || event.position; /*event.position is deprecated*/
|
300
|
+
var total = event.total;
|
301
|
+
if (event.lengthComputable) {
|
302
|
+
percent = Math.ceil(position / total * 100);
|
303
|
+
}
|
304
|
+
options.uploadProgress(event, position, total, percent);
|
305
|
+
}, false);
|
306
|
+
}
|
307
|
+
return xhr;
|
308
|
+
};
|
309
|
+
}
|
216
310
|
|
217
|
-
|
311
|
+
s.data = null;
|
218
312
|
var beforeSend = s.beforeSend;
|
219
313
|
s.beforeSend = function(xhr, o) {
|
220
314
|
o.data = formdata;
|
221
|
-
if(xhr.upload) { // unfortunately, jQuery doesn't expose this prop (http://bugs.jquery.com/ticket/10190)
|
222
|
-
xhr.upload.onprogress = function(event) {
|
223
|
-
o.progress(event.position, event.total);
|
224
|
-
};
|
225
|
-
}
|
226
315
|
if(beforeSend)
|
227
|
-
beforeSend.call(
|
228
|
-
|
229
|
-
|
230
|
-
|
316
|
+
beforeSend.call(this, xhr, o);
|
317
|
+
};
|
318
|
+
return $.ajax(s);
|
319
|
+
}
|
231
320
|
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
321
|
+
// private function for handling file uploads (hat tip to YAHOO!)
|
322
|
+
function fileUploadIframe(a) {
|
323
|
+
var form = $form[0], el, i, s, g, id, $io, io, xhr, sub, n, timedOut, timeoutHandle;
|
324
|
+
var deferred = $.Deferred();
|
325
|
+
|
326
|
+
if (a) {
|
327
|
+
// ensure that every serialized input is still enabled
|
328
|
+
for (i=0; i < elements.length; i++) {
|
329
|
+
el = $(elements[i]);
|
330
|
+
if ( hasProp )
|
331
|
+
el.prop('disabled', false);
|
332
|
+
else
|
333
|
+
el.removeAttr('disabled');
|
334
|
+
}
|
335
|
+
}
|
236
336
|
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
337
|
+
s = $.extend(true, {}, $.ajaxSettings, options);
|
338
|
+
s.context = s.context || s;
|
339
|
+
id = 'jqFormIO' + (new Date().getTime());
|
340
|
+
if (s.iframeTarget) {
|
341
|
+
$io = $(s.iframeTarget);
|
342
|
+
n = $io.attr2('name');
|
343
|
+
if (!n)
|
344
|
+
$io.attr2('name', id);
|
345
|
+
else
|
346
|
+
id = n;
|
347
|
+
}
|
348
|
+
else {
|
349
|
+
$io = $('<iframe name="' + id + '" src="'+ s.iframeSrc +'" />');
|
350
|
+
$io.css({ position: 'absolute', top: '-1000px', left: '-1000px' });
|
351
|
+
}
|
352
|
+
io = $io[0];
|
353
|
+
|
354
|
+
|
355
|
+
xhr = { // mock object
|
356
|
+
aborted: 0,
|
357
|
+
responseText: null,
|
358
|
+
responseXML: null,
|
359
|
+
status: 0,
|
360
|
+
statusText: 'n/a',
|
361
|
+
getAllResponseHeaders: function() {},
|
362
|
+
getResponseHeader: function() {},
|
363
|
+
setRequestHeader: function() {},
|
364
|
+
abort: function(status) {
|
365
|
+
var e = (status === 'timeout' ? 'timeout' : 'aborted');
|
366
|
+
log('aborting upload... ' + e);
|
367
|
+
this.aborted = 1;
|
368
|
+
|
369
|
+
try { // #214, #257
|
370
|
+
if (io.contentWindow.document.execCommand) {
|
371
|
+
io.contentWindow.document.execCommand('Stop');
|
248
372
|
}
|
249
|
-
}
|
373
|
+
}
|
374
|
+
catch(ignore) {}
|
375
|
+
|
376
|
+
$io.attr('src', s.iframeSrc); // abort op in progress
|
377
|
+
xhr.error = e;
|
378
|
+
if (s.error)
|
379
|
+
s.error.call(s.context, xhr, e, status);
|
380
|
+
if (g)
|
381
|
+
$.event.trigger("ajaxError", [xhr, s, e]);
|
382
|
+
if (s.complete)
|
383
|
+
s.complete.call(s.context, xhr, e);
|
250
384
|
}
|
385
|
+
};
|
251
386
|
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
387
|
+
g = s.global;
|
388
|
+
// trigger ajax global events so that activity/block indicators work like normal
|
389
|
+
if (g && 0 === $.active++) {
|
390
|
+
$.event.trigger("ajaxStart");
|
391
|
+
}
|
392
|
+
if (g) {
|
393
|
+
$.event.trigger("ajaxSend", [xhr, s]);
|
394
|
+
}
|
258
395
|
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
if (s.iframeTarget) {
|
263
|
-
$io = $(s.iframeTarget);
|
264
|
-
n = $io.attr('name');
|
265
|
-
if (n == null)
|
266
|
-
$io.attr('name', id);
|
267
|
-
else
|
268
|
-
id = n;
|
396
|
+
if (s.beforeSend && s.beforeSend.call(s.context, xhr, s) === false) {
|
397
|
+
if (s.global) {
|
398
|
+
$.active--;
|
269
399
|
}
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
xhr = { // mock object
|
278
|
-
aborted: 0,
|
279
|
-
responseText: null,
|
280
|
-
responseXML: null,
|
281
|
-
status: 0,
|
282
|
-
statusText: 'n/a',
|
283
|
-
getAllResponseHeaders: function() {},
|
284
|
-
getResponseHeader: function() {},
|
285
|
-
setRequestHeader: function() {},
|
286
|
-
abort: function(status) {
|
287
|
-
var e = (status === 'timeout' ? 'timeout' : 'aborted');
|
288
|
-
log('aborting upload... ' + e);
|
289
|
-
this.aborted = 1;
|
290
|
-
$io.attr('src', s.iframeSrc); // abort op in progress
|
291
|
-
xhr.error = e;
|
292
|
-
s.error && s.error.call(s.context, xhr, e, status);
|
293
|
-
g && $.event.trigger("ajaxError", [xhr, s, e]);
|
294
|
-
s.complete && s.complete.call(s.context, xhr, e);
|
295
|
-
}
|
296
|
-
};
|
400
|
+
deferred.reject();
|
401
|
+
return deferred;
|
402
|
+
}
|
403
|
+
if (xhr.aborted) {
|
404
|
+
deferred.reject();
|
405
|
+
return deferred;
|
406
|
+
}
|
297
407
|
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
408
|
+
// add submitting element to data if we know it
|
409
|
+
sub = form.clk;
|
410
|
+
if (sub) {
|
411
|
+
n = sub.name;
|
412
|
+
if (n && !sub.disabled) {
|
413
|
+
s.extraData = s.extraData || {};
|
414
|
+
s.extraData[n] = sub.value;
|
415
|
+
if (sub.type == "image") {
|
416
|
+
s.extraData[n+'.x'] = form.clk_x;
|
417
|
+
s.extraData[n+'.y'] = form.clk_y;
|
418
|
+
}
|
305
419
|
}
|
420
|
+
}
|
306
421
|
|
307
|
-
|
308
|
-
|
309
|
-
|
422
|
+
var CLIENT_TIMEOUT_ABORT = 1;
|
423
|
+
var SERVER_ABORT = 2;
|
424
|
+
|
425
|
+
function getDoc(frame) {
|
426
|
+
/* it looks like contentWindow or contentDocument do not
|
427
|
+
* carry the protocol property in ie8, when running under ssl
|
428
|
+
* frame.document is the only valid response document, since
|
429
|
+
* the protocol is know but not on the other two objects. strange?
|
430
|
+
* "Same origin policy" http://en.wikipedia.org/wiki/Same_origin_policy
|
431
|
+
*/
|
432
|
+
|
433
|
+
var doc = null;
|
434
|
+
|
435
|
+
// IE8 cascading access check
|
436
|
+
try {
|
437
|
+
if (frame.contentWindow) {
|
438
|
+
doc = frame.contentWindow.document;
|
310
439
|
}
|
311
|
-
|
440
|
+
} catch(err) {
|
441
|
+
// IE8 access denied under ssl & missing protocol
|
442
|
+
log('cannot get iframe.contentWindow document: ' + err);
|
312
443
|
}
|
313
|
-
|
314
|
-
|
444
|
+
|
445
|
+
if (doc) { // successful getting content
|
446
|
+
return doc;
|
315
447
|
}
|
316
448
|
|
317
|
-
//
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
s.extraData[n] = sub.value;
|
324
|
-
if (sub.type == "image") {
|
325
|
-
s.extraData[n+'.x'] = form.clk_x;
|
326
|
-
s.extraData[n+'.y'] = form.clk_y;
|
327
|
-
}
|
328
|
-
}
|
449
|
+
try { // simply checking may throw in ie8 under ssl or mismatched protocol
|
450
|
+
doc = frame.contentDocument ? frame.contentDocument : frame.document;
|
451
|
+
} catch(err) {
|
452
|
+
// last attempt
|
453
|
+
log('cannot get iframe.contentDocument: ' + err);
|
454
|
+
doc = frame.document;
|
329
455
|
}
|
456
|
+
return doc;
|
457
|
+
}
|
458
|
+
|
459
|
+
// Rails CSRF hack (thanks to Yvan Barthelemy)
|
460
|
+
var csrf_token = $('meta[name=csrf-token]').attr('content');
|
461
|
+
var csrf_param = $('meta[name=csrf-param]').attr('content');
|
462
|
+
if (csrf_param && csrf_token) {
|
463
|
+
s.extraData = s.extraData || {};
|
464
|
+
s.extraData[csrf_param] = csrf_token;
|
465
|
+
}
|
330
466
|
|
331
|
-
|
332
|
-
|
467
|
+
// take a breath so that pending repaints get some cpu time before the upload starts
|
468
|
+
function doSubmit() {
|
469
|
+
// make sure form attrs are set
|
470
|
+
var t = $form.attr2('target'), a = $form.attr2('action');
|
333
471
|
|
334
|
-
|
335
|
-
|
336
|
-
|
472
|
+
// update form attrs in IE friendly way
|
473
|
+
form.setAttribute('target',id);
|
474
|
+
if (!method) {
|
475
|
+
form.setAttribute('method', 'POST');
|
476
|
+
}
|
477
|
+
if (a != s.url) {
|
478
|
+
form.setAttribute('action', s.url);
|
337
479
|
}
|
338
480
|
|
339
|
-
//
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
481
|
+
// ie borks in some cases when setting encoding
|
482
|
+
if (! s.skipEncodingOverride && (!method || /post/i.test(method))) {
|
483
|
+
$form.attr({
|
484
|
+
encoding: 'multipart/form-data',
|
485
|
+
enctype: 'multipart/form-data'
|
486
|
+
});
|
345
487
|
}
|
346
488
|
|
347
|
-
//
|
348
|
-
|
349
|
-
|
350
|
-
|
489
|
+
// support timout
|
490
|
+
if (s.timeout) {
|
491
|
+
timeoutHandle = setTimeout(function() { timedOut = true; cb(CLIENT_TIMEOUT_ABORT); }, s.timeout);
|
492
|
+
}
|
351
493
|
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
494
|
+
// look for server aborts
|
495
|
+
function checkState() {
|
496
|
+
try {
|
497
|
+
var state = getDoc(io).readyState;
|
498
|
+
log('state = ' + state);
|
499
|
+
if (state && state.toLowerCase() == 'uninitialized')
|
500
|
+
setTimeout(checkState,50);
|
356
501
|
}
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
$form.attr({
|
364
|
-
encoding: 'multipart/form-data',
|
365
|
-
enctype: 'multipart/form-data'
|
366
|
-
});
|
502
|
+
catch(e) {
|
503
|
+
log('Server abort: ' , e, ' (', e.name, ')');
|
504
|
+
cb(SERVER_ABORT);
|
505
|
+
if (timeoutHandle)
|
506
|
+
clearTimeout(timeoutHandle);
|
507
|
+
timeoutHandle = undefined;
|
367
508
|
}
|
509
|
+
}
|
368
510
|
|
369
|
-
|
370
|
-
|
371
|
-
|
511
|
+
// add "extra" data to form if provided in options
|
512
|
+
var extraInputs = [];
|
513
|
+
try {
|
514
|
+
if (s.extraData) {
|
515
|
+
for (var n in s.extraData) {
|
516
|
+
if (s.extraData.hasOwnProperty(n)) {
|
517
|
+
// if using the $.param format that allows for multiple values with the same name
|
518
|
+
if($.isPlainObject(s.extraData[n]) && s.extraData[n].hasOwnProperty('name') && s.extraData[n].hasOwnProperty('value')) {
|
519
|
+
extraInputs.push(
|
520
|
+
$('<input type="hidden" name="'+s.extraData[n].name+'">').val(s.extraData[n].value)
|
521
|
+
.appendTo(form)[0]);
|
522
|
+
} else {
|
523
|
+
extraInputs.push(
|
524
|
+
$('<input type="hidden" name="'+n+'">').val(s.extraData[n])
|
525
|
+
.appendTo(form)[0]);
|
526
|
+
}
|
527
|
+
}
|
528
|
+
}
|
372
529
|
}
|
373
530
|
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
}
|
382
|
-
catch(e) {
|
383
|
-
log('Server abort: ' , e, ' (', e.name, ')');
|
384
|
-
cb(SERVER_ABORT);
|
385
|
-
timeoutHandle && clearTimeout(timeoutHandle);
|
386
|
-
timeoutHandle = undefined;
|
387
|
-
}
|
531
|
+
if (!s.iframeTarget) {
|
532
|
+
// add iframe to doc and submit the form
|
533
|
+
$io.appendTo('body');
|
534
|
+
if (io.attachEvent)
|
535
|
+
io.attachEvent('onload', cb);
|
536
|
+
else
|
537
|
+
io.addEventListener('load', cb, false);
|
388
538
|
}
|
539
|
+
setTimeout(checkState,15);
|
389
540
|
|
390
|
-
// add "extra" data to form if provided in options
|
391
|
-
var extraInputs = [];
|
392
541
|
try {
|
393
|
-
if (s.extraData) {
|
394
|
-
for (var n in s.extraData) {
|
395
|
-
extraInputs.push(
|
396
|
-
$('<input type="hidden" name="'+n+'">').attr('value',s.extraData[n])
|
397
|
-
.appendTo(form)[0]);
|
398
|
-
}
|
399
|
-
}
|
400
|
-
|
401
|
-
if (!s.iframeTarget) {
|
402
|
-
// add iframe to doc and submit the form
|
403
|
-
$io.appendTo('body');
|
404
|
-
io.attachEvent ? io.attachEvent('onload', cb) : io.addEventListener('load', cb, false);
|
405
|
-
}
|
406
|
-
setTimeout(checkState,15);
|
407
542
|
form.submit();
|
543
|
+
} catch(err) {
|
544
|
+
// just in case form has element with name/id of 'submit'
|
545
|
+
var submitFn = document.createElement('form').submit;
|
546
|
+
submitFn.apply(form);
|
408
547
|
}
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
$(extraInputs).remove();
|
548
|
+
}
|
549
|
+
finally {
|
550
|
+
// reset attrs and remove "extra" input elements
|
551
|
+
form.setAttribute('action',a);
|
552
|
+
if(t) {
|
553
|
+
form.setAttribute('target', t);
|
554
|
+
} else {
|
555
|
+
$form.removeAttr('target');
|
418
556
|
}
|
557
|
+
$(extraInputs).remove();
|
419
558
|
}
|
559
|
+
}
|
420
560
|
|
421
|
-
|
422
|
-
|
561
|
+
if (s.forceSync) {
|
562
|
+
doSubmit();
|
563
|
+
}
|
564
|
+
else {
|
565
|
+
setTimeout(doSubmit, 10); // this lets dom updates render
|
566
|
+
}
|
567
|
+
|
568
|
+
var data, doc, domCheckCount = 50, callbackProcessed;
|
569
|
+
|
570
|
+
function cb(e) {
|
571
|
+
if (xhr.aborted || callbackProcessed) {
|
572
|
+
return;
|
423
573
|
}
|
424
|
-
|
425
|
-
|
574
|
+
|
575
|
+
doc = getDoc(io);
|
576
|
+
if(!doc) {
|
577
|
+
log('cannot access response document');
|
578
|
+
e = SERVER_ABORT;
|
579
|
+
}
|
580
|
+
if (e === CLIENT_TIMEOUT_ABORT && xhr) {
|
581
|
+
xhr.abort('timeout');
|
582
|
+
deferred.reject(xhr, 'timeout');
|
583
|
+
return;
|
584
|
+
}
|
585
|
+
else if (e == SERVER_ABORT && xhr) {
|
586
|
+
xhr.abort('server abort');
|
587
|
+
deferred.reject(xhr, 'error', 'server abort');
|
588
|
+
return;
|
426
589
|
}
|
427
590
|
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
if (xhr.aborted || callbackProcessed) {
|
432
|
-
return;
|
433
|
-
}
|
434
|
-
try {
|
435
|
-
doc = getDoc(io);
|
436
|
-
}
|
437
|
-
catch(ex) {
|
438
|
-
log('cannot access response document: ', ex);
|
439
|
-
e = SERVER_ABORT;
|
440
|
-
}
|
441
|
-
if (e === CLIENT_TIMEOUT_ABORT && xhr) {
|
442
|
-
xhr.abort('timeout');
|
443
|
-
return;
|
444
|
-
}
|
445
|
-
else if (e == SERVER_ABORT && xhr) {
|
446
|
-
xhr.abort('server abort');
|
591
|
+
if (!doc || doc.location.href == s.iframeSrc) {
|
592
|
+
// response not received yet
|
593
|
+
if (!timedOut)
|
447
594
|
return;
|
595
|
+
}
|
596
|
+
if (io.detachEvent)
|
597
|
+
io.detachEvent('onload', cb);
|
598
|
+
else
|
599
|
+
io.removeEventListener('load', cb, false);
|
600
|
+
|
601
|
+
var status = 'success', errMsg;
|
602
|
+
try {
|
603
|
+
if (timedOut) {
|
604
|
+
throw 'timeout';
|
448
605
|
}
|
449
606
|
|
450
|
-
|
451
|
-
|
452
|
-
|
607
|
+
var isXml = s.dataType == 'xml' || doc.XMLDocument || $.isXMLDoc(doc);
|
608
|
+
log('isXml='+isXml);
|
609
|
+
if (!isXml && window.opera && (doc.body === null || !doc.body.innerHTML)) {
|
610
|
+
if (--domCheckCount) {
|
611
|
+
// in some browsers (Opera) the iframe DOM is not always traversable when
|
612
|
+
// the onload callback fires, so we loop a bit to accommodate
|
613
|
+
log('requeing onLoad callback, DOM not available');
|
614
|
+
setTimeout(cb, 250);
|
453
615
|
return;
|
454
|
-
}
|
455
|
-
io.detachEvent ? io.detachEvent('onload', cb) : io.removeEventListener('load', cb, false);
|
456
|
-
|
457
|
-
var status = 'success', errMsg;
|
458
|
-
try {
|
459
|
-
if (timedOut) {
|
460
|
-
throw 'timeout';
|
461
616
|
}
|
617
|
+
// let this fall through because server response could be an empty document
|
618
|
+
//log('Could not access iframe DOM after mutiple tries.');
|
619
|
+
//throw 'DOMException: not available';
|
620
|
+
}
|
462
621
|
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
622
|
+
//log('response detected');
|
623
|
+
var docRoot = doc.body ? doc.body : doc.documentElement;
|
624
|
+
xhr.responseText = docRoot ? docRoot.innerHTML : null;
|
625
|
+
xhr.responseXML = doc.XMLDocument ? doc.XMLDocument : doc;
|
626
|
+
if (isXml)
|
627
|
+
s.dataType = 'xml';
|
628
|
+
xhr.getResponseHeader = function(header){
|
629
|
+
var headers = {'content-type': s.dataType};
|
630
|
+
return headers[header];
|
631
|
+
};
|
632
|
+
// support for XHR 'status' & 'statusText' emulation :
|
633
|
+
if (docRoot) {
|
634
|
+
xhr.status = Number( docRoot.getAttribute('status') ) || xhr.status;
|
635
|
+
xhr.statusText = docRoot.getAttribute('statusText') || xhr.statusText;
|
636
|
+
}
|
477
637
|
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
// support for XHR 'status' & 'statusText' emulation :
|
489
|
-
if (docRoot) {
|
490
|
-
xhr.status = Number( docRoot.getAttribute('status') ) || xhr.status;
|
491
|
-
xhr.statusText = docRoot.getAttribute('statusText') || xhr.statusText;
|
638
|
+
var dt = (s.dataType || '').toLowerCase();
|
639
|
+
var scr = /(json|script|text)/.test(dt);
|
640
|
+
if (scr || s.textarea) {
|
641
|
+
// see if user embedded response in textarea
|
642
|
+
var ta = doc.getElementsByTagName('textarea')[0];
|
643
|
+
if (ta) {
|
644
|
+
xhr.responseText = ta.value;
|
645
|
+
// support for XHR 'status' & 'statusText' emulation :
|
646
|
+
xhr.status = Number( ta.getAttribute('status') ) || xhr.status;
|
647
|
+
xhr.statusText = ta.getAttribute('statusText') || xhr.statusText;
|
492
648
|
}
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
if (ta) {
|
500
|
-
xhr.responseText = ta.value;
|
501
|
-
// support for XHR 'status' & 'statusText' emulation :
|
502
|
-
xhr.status = Number( ta.getAttribute('status') ) || xhr.status;
|
503
|
-
xhr.statusText = ta.getAttribute('statusText') || xhr.statusText;
|
649
|
+
else if (scr) {
|
650
|
+
// account for browsers injecting pre around json response
|
651
|
+
var pre = doc.getElementsByTagName('pre')[0];
|
652
|
+
var b = doc.getElementsByTagName('body')[0];
|
653
|
+
if (pre) {
|
654
|
+
xhr.responseText = pre.textContent ? pre.textContent : pre.innerText;
|
504
655
|
}
|
505
|
-
else if (
|
506
|
-
|
507
|
-
var pre = doc.getElementsByTagName('pre')[0];
|
508
|
-
var b = doc.getElementsByTagName('body')[0];
|
509
|
-
if (pre) {
|
510
|
-
xhr.responseText = pre.textContent ? pre.textContent : pre.innerText;
|
511
|
-
}
|
512
|
-
else if (b) {
|
513
|
-
xhr.responseText = b.textContent ? b.textContent : b.innerText;
|
514
|
-
}
|
656
|
+
else if (b) {
|
657
|
+
xhr.responseText = b.textContent ? b.textContent : b.innerText;
|
515
658
|
}
|
516
659
|
}
|
517
|
-
else if (dt == 'xml' && !xhr.responseXML && xhr.responseText != null) {
|
518
|
-
xhr.responseXML = toXml(xhr.responseText);
|
519
|
-
}
|
520
|
-
|
521
|
-
try {
|
522
|
-
data = httpData(xhr, dt, s);
|
523
|
-
}
|
524
|
-
catch (e) {
|
525
|
-
status = 'parsererror';
|
526
|
-
xhr.error = errMsg = (e || status);
|
527
|
-
}
|
528
660
|
}
|
529
|
-
|
530
|
-
|
531
|
-
status = 'error';
|
532
|
-
xhr.error = errMsg = (e || status);
|
661
|
+
else if (dt == 'xml' && !xhr.responseXML && xhr.responseText) {
|
662
|
+
xhr.responseXML = toXml(xhr.responseText);
|
533
663
|
}
|
534
664
|
|
535
|
-
|
536
|
-
|
537
|
-
status = null;
|
538
|
-
}
|
539
|
-
|
540
|
-
if (xhr.status) { // we've set xhr.status
|
541
|
-
status = (xhr.status >= 200 && xhr.status < 300 || xhr.status === 304) ? 'success' : 'error';
|
542
|
-
}
|
543
|
-
|
544
|
-
// ordering of these callbacks/triggers is odd, but that's how $.ajax does it
|
545
|
-
if (status === 'success') {
|
546
|
-
s.success && s.success.call(s.context, data, 'success', xhr);
|
547
|
-
g && $.event.trigger("ajaxSuccess", [xhr, s]);
|
665
|
+
try {
|
666
|
+
data = httpData(xhr, dt, s);
|
548
667
|
}
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
s.error && s.error.call(s.context, xhr, status, errMsg);
|
553
|
-
g && $.event.trigger("ajaxError", [xhr, s, errMsg]);
|
668
|
+
catch (err) {
|
669
|
+
status = 'parsererror';
|
670
|
+
xhr.error = errMsg = (err || status);
|
554
671
|
}
|
672
|
+
}
|
673
|
+
catch (err) {
|
674
|
+
log('error caught: ',err);
|
675
|
+
status = 'error';
|
676
|
+
xhr.error = errMsg = (err || status);
|
677
|
+
}
|
555
678
|
|
556
|
-
|
679
|
+
if (xhr.aborted) {
|
680
|
+
log('upload aborted');
|
681
|
+
status = null;
|
682
|
+
}
|
557
683
|
|
558
|
-
|
559
|
-
|
560
|
-
|
684
|
+
if (xhr.status) { // we've set xhr.status
|
685
|
+
status = (xhr.status >= 200 && xhr.status < 300 || xhr.status === 304) ? 'success' : 'error';
|
686
|
+
}
|
561
687
|
|
562
|
-
|
688
|
+
// ordering of these callbacks/triggers is odd, but that's how $.ajax does it
|
689
|
+
if (status === 'success') {
|
690
|
+
if (s.success)
|
691
|
+
s.success.call(s.context, data, 'success', xhr);
|
692
|
+
deferred.resolve(xhr.responseText, 'success', xhr);
|
693
|
+
if (g)
|
694
|
+
$.event.trigger("ajaxSuccess", [xhr, s]);
|
695
|
+
}
|
696
|
+
else if (status) {
|
697
|
+
if (errMsg === undefined)
|
698
|
+
errMsg = xhr.statusText;
|
699
|
+
if (s.error)
|
700
|
+
s.error.call(s.context, xhr, status, errMsg);
|
701
|
+
deferred.reject(xhr, 'error', errMsg);
|
702
|
+
if (g)
|
703
|
+
$.event.trigger("ajaxError", [xhr, s, errMsg]);
|
704
|
+
}
|
563
705
|
|
564
|
-
|
565
|
-
|
566
|
-
clearTimeout(timeoutHandle);
|
706
|
+
if (g)
|
707
|
+
$.event.trigger("ajaxComplete", [xhr, s]);
|
567
708
|
|
568
|
-
|
569
|
-
|
570
|
-
if (!s.iframeTarget)
|
571
|
-
$io.remove();
|
572
|
-
xhr.responseXML = null;
|
573
|
-
}, 100);
|
709
|
+
if (g && ! --$.active) {
|
710
|
+
$.event.trigger("ajaxStop");
|
574
711
|
}
|
575
712
|
|
576
|
-
|
577
|
-
|
578
|
-
doc = new ActiveXObject('Microsoft.XMLDOM');
|
579
|
-
doc.async = 'false';
|
580
|
-
doc.loadXML(s);
|
581
|
-
}
|
582
|
-
else {
|
583
|
-
doc = (new DOMParser()).parseFromString(s, 'text/xml');
|
584
|
-
}
|
585
|
-
return (doc && doc.documentElement && doc.documentElement.nodeName != 'parsererror') ? doc : null;
|
586
|
-
};
|
587
|
-
var parseJSON = $.parseJSON || function(s) {
|
588
|
-
return window['eval']('(' + s + ')');
|
589
|
-
};
|
713
|
+
if (s.complete)
|
714
|
+
s.complete.call(s.context, xhr, status);
|
590
715
|
|
591
|
-
|
716
|
+
callbackProcessed = true;
|
717
|
+
if (s.timeout)
|
718
|
+
clearTimeout(timeoutHandle);
|
592
719
|
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
|
599
|
-
}
|
600
|
-
if (s && s.dataFilter) {
|
601
|
-
data = s.dataFilter(data, type);
|
602
|
-
}
|
603
|
-
if (typeof data === 'string') {
|
604
|
-
if (type === 'json' || !type && ct.indexOf('json') >= 0) {
|
605
|
-
data = parseJSON(data);
|
606
|
-
} else if (type === "script" || !type && ct.indexOf("javascript") >= 0) {
|
607
|
-
$.globalEval(data);
|
608
|
-
}
|
609
|
-
}
|
610
|
-
return data;
|
611
|
-
};
|
720
|
+
// clean up
|
721
|
+
setTimeout(function() {
|
722
|
+
if (!s.iframeTarget)
|
723
|
+
$io.remove();
|
724
|
+
xhr.responseXML = null;
|
725
|
+
}, 100);
|
612
726
|
}
|
613
|
-
};
|
614
727
|
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
|
619
|
-
|
620
|
-
* 1: This method will include coordinates for <input type="image" /> elements (if the element
|
621
|
-
* is used to submit the form).
|
622
|
-
* 2. This method will include the submit element's name/value data (for the element that was
|
623
|
-
* used to submit the form).
|
624
|
-
* 3. This method binds the submit() method to the form for you.
|
625
|
-
*
|
626
|
-
* The options argument for ajaxForm works exactly as it does for ajaxSubmit. ajaxForm merely
|
627
|
-
* passes the options argument along after properly binding events for submit elements and
|
628
|
-
* the form itself.
|
629
|
-
*/
|
630
|
-
$.fn.ajaxForm = function(options) {
|
631
|
-
options = options || {};
|
632
|
-
options.delegation = options.delegation && $.isFunction($.fn.on);
|
633
|
-
|
634
|
-
// in jQuery 1.3+ we can fix mistakes with the ready state
|
635
|
-
if (!options.delegation && this.length === 0) {
|
636
|
-
var o = { s: this.selector, c: this.context };
|
637
|
-
if (!$.isReady && o.s) {
|
638
|
-
log('DOM not ready, queuing ajaxForm');
|
639
|
-
$(function() {
|
640
|
-
$(o.s,o.c).ajaxForm(options);
|
641
|
-
});
|
642
|
-
return this;
|
728
|
+
var toXml = $.parseXML || function(s, doc) { // use parseXML if available (jQuery 1.5+)
|
729
|
+
if (window.ActiveXObject) {
|
730
|
+
doc = new ActiveXObject('Microsoft.XMLDOM');
|
731
|
+
doc.async = 'false';
|
732
|
+
doc.loadXML(s);
|
643
733
|
}
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
734
|
+
else {
|
735
|
+
doc = (new DOMParser()).parseFromString(s, 'text/xml');
|
736
|
+
}
|
737
|
+
return (doc && doc.documentElement && doc.documentElement.nodeName != 'parsererror') ? doc : null;
|
738
|
+
};
|
739
|
+
var parseJSON = $.parseJSON || function(s) {
|
740
|
+
/*jslint evil:true */
|
741
|
+
return window['eval']('(' + s + ')');
|
742
|
+
};
|
743
|
+
|
744
|
+
var httpData = function( xhr, type, s ) { // mostly lifted from jq1.4.4
|
745
|
+
|
746
|
+
var ct = xhr.getResponseHeader('content-type') || '',
|
747
|
+
xml = type === 'xml' || !type && ct.indexOf('xml') >= 0,
|
748
|
+
data = xml ? xhr.responseXML : xhr.responseText;
|
648
749
|
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
.
|
750
|
+
if (xml && data.documentElement.nodeName === 'parsererror') {
|
751
|
+
if ($.error)
|
752
|
+
$.error('parsererror');
|
753
|
+
}
|
754
|
+
if (s && s.dataFilter) {
|
755
|
+
data = s.dataFilter(data, type);
|
756
|
+
}
|
757
|
+
if (typeof data === 'string') {
|
758
|
+
if (type === 'json' || !type && ct.indexOf('json') >= 0) {
|
759
|
+
data = parseJSON(data);
|
760
|
+
} else if (type === "script" || !type && ct.indexOf("javascript") >= 0) {
|
761
|
+
$.globalEval(data);
|
762
|
+
}
|
763
|
+
}
|
764
|
+
return data;
|
765
|
+
};
|
766
|
+
|
767
|
+
return deferred;
|
768
|
+
}
|
769
|
+
};
|
770
|
+
|
771
|
+
/**
|
772
|
+
* ajaxForm() provides a mechanism for fully automating form submission.
|
773
|
+
*
|
774
|
+
* The advantages of using this method instead of ajaxSubmit() are:
|
775
|
+
*
|
776
|
+
* 1: This method will include coordinates for <input type="image" /> elements (if the element
|
777
|
+
* is used to submit the form).
|
778
|
+
* 2. This method will include the submit element's name/value data (for the element that was
|
779
|
+
* used to submit the form).
|
780
|
+
* 3. This method binds the submit() method to the form for you.
|
781
|
+
*
|
782
|
+
* The options argument for ajaxForm works exactly as it does for ajaxSubmit. ajaxForm merely
|
783
|
+
* passes the options argument along after properly binding events for submit elements and
|
784
|
+
* the form itself.
|
785
|
+
*/
|
786
|
+
$.fn.ajaxForm = function(options) {
|
787
|
+
options = options || {};
|
788
|
+
options.delegation = options.delegation && $.isFunction($.fn.on);
|
789
|
+
|
790
|
+
// in jQuery 1.3+ we can fix mistakes with the ready state
|
791
|
+
if (!options.delegation && this.length === 0) {
|
792
|
+
var o = { s: this.selector, c: this.context };
|
793
|
+
if (!$.isReady && o.s) {
|
794
|
+
log('DOM not ready, queuing ajaxForm');
|
795
|
+
$(function() {
|
796
|
+
$(o.s,o.c).ajaxForm(options);
|
797
|
+
});
|
655
798
|
return this;
|
656
799
|
}
|
800
|
+
// is your DOM ready? http://docs.jquery.com/Tutorials:Introducing_$(document).ready()
|
801
|
+
log('terminating; zero elements found by selector' + ($.isReady ? '' : ' (DOM not ready)'));
|
802
|
+
return this;
|
803
|
+
}
|
657
804
|
|
658
|
-
|
659
|
-
|
660
|
-
.
|
661
|
-
|
805
|
+
if ( options.delegation ) {
|
806
|
+
$(document)
|
807
|
+
.off('submit.form-plugin', this.selector, doAjaxSubmit)
|
808
|
+
.off('click.form-plugin', this.selector, captureSubmittingElement)
|
809
|
+
.on('submit.form-plugin', this.selector, options, doAjaxSubmit)
|
810
|
+
.on('click.form-plugin', this.selector, options, captureSubmittingElement);
|
811
|
+
return this;
|
812
|
+
}
|
662
813
|
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
|
814
|
+
return this.ajaxFormUnbind()
|
815
|
+
.bind('submit.form-plugin', options, doAjaxSubmit)
|
816
|
+
.bind('click.form-plugin', options, captureSubmittingElement);
|
817
|
+
};
|
818
|
+
|
819
|
+
// private event handlers
|
820
|
+
function doAjaxSubmit(e) {
|
821
|
+
/*jshint validthis:true */
|
822
|
+
var options = e.data;
|
823
|
+
if (!e.isDefaultPrevented()) { // if event has been canceled, don't proceed
|
824
|
+
e.preventDefault();
|
825
|
+
$(this).ajaxSubmit(options);
|
826
|
+
}
|
827
|
+
}
|
828
|
+
|
829
|
+
function captureSubmittingElement(e) {
|
830
|
+
/*jshint validthis:true */
|
831
|
+
var target = e.target;
|
832
|
+
var $el = $(target);
|
833
|
+
if (!($el.is("[type=submit],[type=image]"))) {
|
834
|
+
// is this a child element of the submit el? (ex: a span within a button)
|
835
|
+
var t = $el.closest('[type=submit]');
|
836
|
+
if (t.length === 0) {
|
837
|
+
return;
|
669
838
|
}
|
839
|
+
target = t[0];
|
670
840
|
}
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
|
689
|
-
} else if (typeof $.fn.offset == 'function') {
|
690
|
-
var offset = $el.offset();
|
691
|
-
form.clk_x = e.pageX - offset.left;
|
692
|
-
form.clk_y = e.pageY - offset.top;
|
693
|
-
} else {
|
694
|
-
form.clk_x = e.pageX - target.offsetLeft;
|
695
|
-
form.clk_y = e.pageY - target.offsetTop;
|
696
|
-
}
|
697
|
-
}
|
698
|
-
// clear form vars
|
699
|
-
setTimeout(function() { form.clk = form.clk_x = form.clk_y = null; }, 100);
|
700
|
-
};
|
841
|
+
var form = this;
|
842
|
+
form.clk = target;
|
843
|
+
if (target.type == 'image') {
|
844
|
+
if (e.offsetX !== undefined) {
|
845
|
+
form.clk_x = e.offsetX;
|
846
|
+
form.clk_y = e.offsetY;
|
847
|
+
} else if (typeof $.fn.offset == 'function') {
|
848
|
+
var offset = $el.offset();
|
849
|
+
form.clk_x = e.pageX - offset.left;
|
850
|
+
form.clk_y = e.pageY - offset.top;
|
851
|
+
} else {
|
852
|
+
form.clk_x = e.pageX - target.offsetLeft;
|
853
|
+
form.clk_y = e.pageY - target.offsetTop;
|
854
|
+
}
|
855
|
+
}
|
856
|
+
// clear form vars
|
857
|
+
setTimeout(function() { form.clk = form.clk_x = form.clk_y = null; }, 100);
|
858
|
+
}
|
701
859
|
|
702
860
|
|
703
861
|
// ajaxFormUnbind unbinds the event handlers that were bound by ajaxForm
|
704
|
-
|
705
|
-
|
706
|
-
|
862
|
+
$.fn.ajaxFormUnbind = function() {
|
863
|
+
return this.unbind('submit.form-plugin click.form-plugin');
|
864
|
+
};
|
865
|
+
|
866
|
+
/**
|
867
|
+
* formToArray() gathers form element data into an array of objects that can
|
868
|
+
* be passed to any of the following ajax functions: $.get, $.post, or load.
|
869
|
+
* Each object in the array has both a 'name' and 'value' property. An example of
|
870
|
+
* an array for a simple login form might be:
|
871
|
+
*
|
872
|
+
* [ { name: 'username', value: 'jresig' }, { name: 'password', value: 'secret' } ]
|
873
|
+
*
|
874
|
+
* It is this array that is passed to pre-submit callback functions provided to the
|
875
|
+
* ajaxSubmit() and ajaxForm() methods.
|
876
|
+
*/
|
877
|
+
$.fn.formToArray = function(semantic, elements) {
|
878
|
+
var a = [];
|
879
|
+
if (this.length === 0) {
|
880
|
+
return a;
|
881
|
+
}
|
707
882
|
|
708
|
-
|
709
|
-
|
710
|
-
|
711
|
-
|
712
|
-
|
713
|
-
*
|
714
|
-
* [ { name: 'username', value: 'jresig' }, { name: 'password', value: 'secret' } ]
|
715
|
-
*
|
716
|
-
* It is this array that is passed to pre-submit callback functions provided to the
|
717
|
-
* ajaxSubmit() and ajaxForm() methods.
|
718
|
-
*/
|
719
|
-
$.fn.formToArray = function(semantic) {
|
720
|
-
var a = [];
|
721
|
-
if (this.length === 0) {
|
722
|
-
return a;
|
723
|
-
}
|
724
|
-
|
725
|
-
var form = this[0];
|
726
|
-
var els = semantic ? form.getElementsByTagName('*') : form.elements;
|
727
|
-
if (!els) {
|
728
|
-
return a;
|
729
|
-
}
|
730
|
-
|
731
|
-
var i,j,n,v,el,max,jmax;
|
732
|
-
for(i=0, max=els.length; i < max; i++) {
|
733
|
-
el = els[i];
|
734
|
-
n = el.name;
|
735
|
-
if (!n) {
|
736
|
-
continue;
|
737
|
-
}
|
738
|
-
|
739
|
-
if (semantic && form.clk && el.type == "image") {
|
740
|
-
// handle image inputs on the fly when semantic == true
|
741
|
-
if(!el.disabled && form.clk == el) {
|
742
|
-
a.push({name: n, value: $(el).val(), type: el.type });
|
743
|
-
a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
|
744
|
-
}
|
745
|
-
continue;
|
746
|
-
}
|
883
|
+
var form = this[0];
|
884
|
+
var els = semantic ? form.getElementsByTagName('*') : form.elements;
|
885
|
+
if (!els) {
|
886
|
+
return a;
|
887
|
+
}
|
747
888
|
|
748
|
-
|
749
|
-
|
750
|
-
|
751
|
-
|
752
|
-
|
753
|
-
|
754
|
-
else if (v !== null && typeof v != 'undefined') {
|
755
|
-
a.push({name: n, value: v, type: el.type});
|
756
|
-
}
|
889
|
+
var i,j,n,v,el,max,jmax;
|
890
|
+
for(i=0, max=els.length; i < max; i++) {
|
891
|
+
el = els[i];
|
892
|
+
n = el.name;
|
893
|
+
if (!n || el.disabled) {
|
894
|
+
continue;
|
757
895
|
}
|
758
896
|
|
759
|
-
if (
|
760
|
-
//
|
761
|
-
|
762
|
-
|
763
|
-
if (n && !input.disabled && input.type == 'image') {
|
764
|
-
a.push({name: n, value: $input.val()});
|
897
|
+
if (semantic && form.clk && el.type == "image") {
|
898
|
+
// handle image inputs on the fly when semantic == true
|
899
|
+
if(form.clk == el) {
|
900
|
+
a.push({name: n, value: $(el).val(), type: el.type });
|
765
901
|
a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
|
766
902
|
}
|
903
|
+
continue;
|
767
904
|
}
|
768
|
-
return a;
|
769
|
-
};
|
770
905
|
|
771
|
-
|
772
|
-
|
773
|
-
|
774
|
-
|
775
|
-
|
776
|
-
|
777
|
-
return $.param(this.formToArray(semantic));
|
778
|
-
};
|
779
|
-
|
780
|
-
/**
|
781
|
-
* Serializes all field elements in the jQuery object into a query string.
|
782
|
-
* This method will return a string in the format: name1=value1&name2=value2
|
783
|
-
*/
|
784
|
-
$.fn.fieldSerialize = function(successful) {
|
785
|
-
var a = [];
|
786
|
-
this.each(function() {
|
787
|
-
var n = this.name;
|
788
|
-
if (!n) {
|
789
|
-
return;
|
906
|
+
v = $.fieldValue(el, true);
|
907
|
+
if (v && v.constructor == Array) {
|
908
|
+
if (elements)
|
909
|
+
elements.push(el);
|
910
|
+
for(j=0, jmax=v.length; j < jmax; j++) {
|
911
|
+
a.push({name: n, value: v[j]});
|
790
912
|
}
|
791
|
-
|
792
|
-
|
793
|
-
|
794
|
-
|
913
|
+
}
|
914
|
+
else if (feature.fileapi && el.type == 'file') {
|
915
|
+
if (elements)
|
916
|
+
elements.push(el);
|
917
|
+
var files = el.files;
|
918
|
+
if (files.length) {
|
919
|
+
for (j=0; j < files.length; j++) {
|
920
|
+
a.push({name: n, value: files[j], type: el.type});
|
795
921
|
}
|
796
922
|
}
|
797
|
-
else
|
798
|
-
|
923
|
+
else {
|
924
|
+
// #180
|
925
|
+
a.push({ name: n, value: '', type: el.type });
|
799
926
|
}
|
800
|
-
});
|
801
|
-
//hand off to jQuery.param for proper encoding
|
802
|
-
return $.param(a);
|
803
|
-
};
|
804
|
-
|
805
|
-
/**
|
806
|
-
* Returns the value(s) of the element in the matched set. For example, consider the following form:
|
807
|
-
*
|
808
|
-
* <form><fieldset>
|
809
|
-
* <input name="A" type="text" />
|
810
|
-
* <input name="A" type="text" />
|
811
|
-
* <input name="B" type="checkbox" value="B1" />
|
812
|
-
* <input name="B" type="checkbox" value="B2"/>
|
813
|
-
* <input name="C" type="radio" value="C1" />
|
814
|
-
* <input name="C" type="radio" value="C2" />
|
815
|
-
* </fieldset></form>
|
816
|
-
*
|
817
|
-
* var v = $(':text').fieldValue();
|
818
|
-
* // if no values are entered into the text inputs
|
819
|
-
* v == ['','']
|
820
|
-
* // if values entered into the text inputs are 'foo' and 'bar'
|
821
|
-
* v == ['foo','bar']
|
822
|
-
*
|
823
|
-
* var v = $(':checkbox').fieldValue();
|
824
|
-
* // if neither checkbox is checked
|
825
|
-
* v === undefined
|
826
|
-
* // if both checkboxes are checked
|
827
|
-
* v == ['B1', 'B2']
|
828
|
-
*
|
829
|
-
* var v = $(':radio').fieldValue();
|
830
|
-
* // if neither radio is checked
|
831
|
-
* v === undefined
|
832
|
-
* // if first radio is checked
|
833
|
-
* v == ['C1']
|
834
|
-
*
|
835
|
-
* The successful argument controls whether or not the field element must be 'successful'
|
836
|
-
* (per http://www.w3.org/TR/html4/interact/forms.html#successful-controls).
|
837
|
-
* The default value of the successful argument is true. If this value is false the value(s)
|
838
|
-
* for each element is returned.
|
839
|
-
*
|
840
|
-
* Note: This method *always* returns an array. If no valid value can be determined the
|
841
|
-
* array will be empty, otherwise it will contain one or more values.
|
842
|
-
*/
|
843
|
-
$.fn.fieldValue = function(successful) {
|
844
|
-
for (var val=[], i=0, max=this.length; i < max; i++) {
|
845
|
-
var el = this[i];
|
846
|
-
var v = $.fieldValue(el, successful);
|
847
|
-
if (v === null || typeof v == 'undefined' || (v.constructor == Array && !v.length)) {
|
848
|
-
continue;
|
849
|
-
}
|
850
|
-
v.constructor == Array ? $.merge(val, v) : val.push(v);
|
851
927
|
}
|
852
|
-
|
853
|
-
|
854
|
-
|
855
|
-
|
856
|
-
* Returns the value of the field element.
|
857
|
-
*/
|
858
|
-
$.fieldValue = function(el, successful) {
|
859
|
-
var n = el.name, t = el.type, tag = el.tagName.toLowerCase();
|
860
|
-
if (successful === undefined) {
|
861
|
-
successful = true;
|
928
|
+
else if (v !== null && typeof v != 'undefined') {
|
929
|
+
if (elements)
|
930
|
+
elements.push(el);
|
931
|
+
a.push({name: n, value: v, type: el.type, required: el.required});
|
862
932
|
}
|
933
|
+
}
|
863
934
|
|
864
|
-
|
865
|
-
|
866
|
-
|
867
|
-
|
868
|
-
|
935
|
+
if (!semantic && form.clk) {
|
936
|
+
// input type=='image' are not found in elements array! handle it here
|
937
|
+
var $input = $(form.clk), input = $input[0];
|
938
|
+
n = input.name;
|
939
|
+
if (n && !input.disabled && input.type == 'image') {
|
940
|
+
a.push({name: n, value: $input.val()});
|
941
|
+
a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
|
869
942
|
}
|
943
|
+
}
|
944
|
+
return a;
|
945
|
+
};
|
870
946
|
|
871
|
-
|
872
|
-
|
873
|
-
|
874
|
-
|
875
|
-
|
876
|
-
|
877
|
-
|
878
|
-
|
879
|
-
|
880
|
-
|
881
|
-
|
882
|
-
|
883
|
-
|
884
|
-
|
885
|
-
|
886
|
-
|
887
|
-
|
888
|
-
|
889
|
-
|
890
|
-
|
947
|
+
/**
|
948
|
+
* Serializes form data into a 'submittable' string. This method will return a string
|
949
|
+
* in the format: name1=value1&name2=value2
|
950
|
+
*/
|
951
|
+
$.fn.formSerialize = function(semantic) {
|
952
|
+
//hand off to jQuery.param for proper encoding
|
953
|
+
return $.param(this.formToArray(semantic));
|
954
|
+
};
|
955
|
+
|
956
|
+
/**
|
957
|
+
* Serializes all field elements in the jQuery object into a query string.
|
958
|
+
* This method will return a string in the format: name1=value1&name2=value2
|
959
|
+
*/
|
960
|
+
$.fn.fieldSerialize = function(successful) {
|
961
|
+
var a = [];
|
962
|
+
this.each(function() {
|
963
|
+
var n = this.name;
|
964
|
+
if (!n) {
|
965
|
+
return;
|
966
|
+
}
|
967
|
+
var v = $.fieldValue(this, successful);
|
968
|
+
if (v && v.constructor == Array) {
|
969
|
+
for (var i=0,max=v.length; i < max; i++) {
|
970
|
+
a.push({name: n, value: v[i]});
|
891
971
|
}
|
892
|
-
return a;
|
893
972
|
}
|
894
|
-
|
895
|
-
|
973
|
+
else if (v !== null && typeof v != 'undefined') {
|
974
|
+
a.push({name: this.name, value: v});
|
975
|
+
}
|
976
|
+
});
|
977
|
+
//hand off to jQuery.param for proper encoding
|
978
|
+
return $.param(a);
|
979
|
+
};
|
896
980
|
|
897
|
-
|
898
|
-
|
899
|
-
|
900
|
-
|
901
|
-
|
902
|
-
|
903
|
-
|
904
|
-
|
905
|
-
|
906
|
-
|
907
|
-
|
908
|
-
|
909
|
-
|
981
|
+
/**
|
982
|
+
* Returns the value(s) of the element in the matched set. For example, consider the following form:
|
983
|
+
*
|
984
|
+
* <form><fieldset>
|
985
|
+
* <input name="A" type="text" />
|
986
|
+
* <input name="A" type="text" />
|
987
|
+
* <input name="B" type="checkbox" value="B1" />
|
988
|
+
* <input name="B" type="checkbox" value="B2"/>
|
989
|
+
* <input name="C" type="radio" value="C1" />
|
990
|
+
* <input name="C" type="radio" value="C2" />
|
991
|
+
* </fieldset></form>
|
992
|
+
*
|
993
|
+
* var v = $('input[type=text]').fieldValue();
|
994
|
+
* // if no values are entered into the text inputs
|
995
|
+
* v == ['','']
|
996
|
+
* // if values entered into the text inputs are 'foo' and 'bar'
|
997
|
+
* v == ['foo','bar']
|
998
|
+
*
|
999
|
+
* var v = $('input[type=checkbox]').fieldValue();
|
1000
|
+
* // if neither checkbox is checked
|
1001
|
+
* v === undefined
|
1002
|
+
* // if both checkboxes are checked
|
1003
|
+
* v == ['B1', 'B2']
|
1004
|
+
*
|
1005
|
+
* var v = $('input[type=radio]').fieldValue();
|
1006
|
+
* // if neither radio is checked
|
1007
|
+
* v === undefined
|
1008
|
+
* // if first radio is checked
|
1009
|
+
* v == ['C1']
|
1010
|
+
*
|
1011
|
+
* The successful argument controls whether or not the field element must be 'successful'
|
1012
|
+
* (per http://www.w3.org/TR/html4/interact/forms.html#successful-controls).
|
1013
|
+
* The default value of the successful argument is true. If this value is false the value(s)
|
1014
|
+
* for each element is returned.
|
1015
|
+
*
|
1016
|
+
* Note: This method *always* returns an array. If no valid value can be determined the
|
1017
|
+
* array will be empty, otherwise it will contain one or more values.
|
1018
|
+
*/
|
1019
|
+
$.fn.fieldValue = function(successful) {
|
1020
|
+
for (var val=[], i=0, max=this.length; i < max; i++) {
|
1021
|
+
var el = this[i];
|
1022
|
+
var v = $.fieldValue(el, successful);
|
1023
|
+
if (v === null || typeof v == 'undefined' || (v.constructor == Array && !v.length)) {
|
1024
|
+
continue;
|
1025
|
+
}
|
1026
|
+
if (v.constructor == Array)
|
1027
|
+
$.merge(val, v);
|
1028
|
+
else
|
1029
|
+
val.push(v);
|
1030
|
+
}
|
1031
|
+
return val;
|
1032
|
+
};
|
910
1033
|
|
911
|
-
|
912
|
-
|
913
|
-
|
914
|
-
|
915
|
-
|
916
|
-
|
917
|
-
|
918
|
-
|
919
|
-
this.value = '';
|
920
|
-
}
|
921
|
-
else if (t == 'checkbox' || t == 'radio') {
|
922
|
-
this.checked = false;
|
923
|
-
}
|
924
|
-
else if (tag == 'select') {
|
925
|
-
this.selectedIndex = -1;
|
926
|
-
}
|
927
|
-
});
|
928
|
-
};
|
1034
|
+
/**
|
1035
|
+
* Returns the value of the field element.
|
1036
|
+
*/
|
1037
|
+
$.fieldValue = function(el, successful) {
|
1038
|
+
var n = el.name, t = el.type, tag = el.tagName.toLowerCase();
|
1039
|
+
if (successful === undefined) {
|
1040
|
+
successful = true;
|
1041
|
+
}
|
929
1042
|
|
930
|
-
|
931
|
-
|
932
|
-
|
933
|
-
|
934
|
-
|
935
|
-
|
936
|
-
|
937
|
-
|
938
|
-
|
1043
|
+
if (successful && (!n || el.disabled || t == 'reset' || t == 'button' ||
|
1044
|
+
(t == 'checkbox' || t == 'radio') && !el.checked ||
|
1045
|
+
(t == 'submit' || t == 'image') && el.form && el.form.clk != el ||
|
1046
|
+
tag == 'select' && el.selectedIndex == -1)) {
|
1047
|
+
return null;
|
1048
|
+
}
|
1049
|
+
|
1050
|
+
if (tag == 'select') {
|
1051
|
+
var index = el.selectedIndex;
|
1052
|
+
if (index < 0) {
|
1053
|
+
return null;
|
1054
|
+
}
|
1055
|
+
var a = [], ops = el.options;
|
1056
|
+
var one = (t == 'select-one');
|
1057
|
+
var max = (one ? index+1 : ops.length);
|
1058
|
+
for(var i=(one ? index : 0); i < max; i++) {
|
1059
|
+
var op = ops[i];
|
1060
|
+
if (op.selected) {
|
1061
|
+
var v = op.value;
|
1062
|
+
if (!v) { // extra pain for IE...
|
1063
|
+
v = (op.attributes && op.attributes['value'] && !(op.attributes['value'].specified)) ? op.text : op.value;
|
1064
|
+
}
|
1065
|
+
if (one) {
|
1066
|
+
return v;
|
1067
|
+
}
|
1068
|
+
a.push(v);
|
939
1069
|
}
|
940
|
-
}
|
941
|
-
|
1070
|
+
}
|
1071
|
+
return a;
|
1072
|
+
}
|
1073
|
+
return $(el).val();
|
1074
|
+
};
|
1075
|
+
|
1076
|
+
/**
|
1077
|
+
* Clears the form data. Takes the following actions on the form's input fields:
|
1078
|
+
* - input text fields will have their 'value' property set to the empty string
|
1079
|
+
* - select elements will have their 'selectedIndex' property set to -1
|
1080
|
+
* - checkbox and radio inputs will have their 'checked' property set to false
|
1081
|
+
* - inputs of type submit, button, reset, and hidden will *not* be effected
|
1082
|
+
* - button elements will *not* be effected
|
1083
|
+
*/
|
1084
|
+
$.fn.clearForm = function(includeHidden) {
|
1085
|
+
return this.each(function() {
|
1086
|
+
$('input,select,textarea', this).clearFields(includeHidden);
|
1087
|
+
});
|
1088
|
+
};
|
1089
|
+
|
1090
|
+
/**
|
1091
|
+
* Clears the selected form elements.
|
1092
|
+
*/
|
1093
|
+
$.fn.clearFields = $.fn.clearInputs = function(includeHidden) {
|
1094
|
+
var re = /^(?:color|date|datetime|email|month|number|password|range|search|tel|text|time|url|week)$/i; // 'hidden' is not in this list
|
1095
|
+
return this.each(function() {
|
1096
|
+
var t = this.type, tag = this.tagName.toLowerCase();
|
1097
|
+
if (re.test(t) || tag == 'textarea') {
|
1098
|
+
this.value = '';
|
1099
|
+
}
|
1100
|
+
else if (t == 'checkbox' || t == 'radio') {
|
1101
|
+
this.checked = false;
|
1102
|
+
}
|
1103
|
+
else if (tag == 'select') {
|
1104
|
+
this.selectedIndex = -1;
|
1105
|
+
}
|
1106
|
+
else if (t == "file") {
|
1107
|
+
if (/MSIE/.test(navigator.userAgent)) {
|
1108
|
+
$(this).replaceWith($(this).clone(true));
|
1109
|
+
} else {
|
1110
|
+
$(this).val('');
|
1111
|
+
}
|
1112
|
+
}
|
1113
|
+
else if (includeHidden) {
|
1114
|
+
// includeHidden can be the value true, or it can be a selector string
|
1115
|
+
// indicating a special test; for example:
|
1116
|
+
// $('#myForm').clearForm('.special:hidden')
|
1117
|
+
// the above would clean hidden inputs that have the class of 'special'
|
1118
|
+
if ( (includeHidden === true && /hidden/.test(t)) ||
|
1119
|
+
(typeof includeHidden == 'string' && $(this).is(includeHidden)) )
|
1120
|
+
this.value = '';
|
1121
|
+
}
|
1122
|
+
});
|
1123
|
+
};
|
942
1124
|
|
943
|
-
|
944
|
-
|
945
|
-
|
946
|
-
|
947
|
-
|
948
|
-
|
1125
|
+
/**
|
1126
|
+
* Resets the form data. Causes all form elements to be reset to their original value.
|
1127
|
+
*/
|
1128
|
+
$.fn.resetForm = function() {
|
1129
|
+
return this.each(function() {
|
1130
|
+
// guard against an input with the name of 'reset'
|
1131
|
+
// note that IE reports the reset function as an 'object'
|
1132
|
+
if (typeof this.reset == 'function' || (typeof this.reset == 'object' && !this.reset.nodeType)) {
|
1133
|
+
this.reset();
|
949
1134
|
}
|
950
|
-
|
951
|
-
|
952
|
-
});
|
953
|
-
};
|
1135
|
+
});
|
1136
|
+
};
|
954
1137
|
|
955
|
-
|
956
|
-
|
957
|
-
|
958
|
-
|
959
|
-
|
960
|
-
|
961
|
-
|
962
|
-
|
963
|
-
|
964
|
-
|
965
|
-
|
966
|
-
|
967
|
-
|
968
|
-
|
969
|
-
|
970
|
-
|
971
|
-
|
972
|
-
|
973
|
-
|
974
|
-
|
1138
|
+
/**
|
1139
|
+
* Enables or disables any matching elements.
|
1140
|
+
*/
|
1141
|
+
$.fn.enable = function(b) {
|
1142
|
+
if (b === undefined) {
|
1143
|
+
b = true;
|
1144
|
+
}
|
1145
|
+
return this.each(function() {
|
1146
|
+
this.disabled = !b;
|
1147
|
+
});
|
1148
|
+
};
|
1149
|
+
|
1150
|
+
/**
|
1151
|
+
* Checks/unchecks any matching checkboxes or radio buttons and
|
1152
|
+
* selects/deselects and matching option elements.
|
1153
|
+
*/
|
1154
|
+
$.fn.selected = function(select) {
|
1155
|
+
if (select === undefined) {
|
1156
|
+
select = true;
|
1157
|
+
}
|
1158
|
+
return this.each(function() {
|
1159
|
+
var t = this.type;
|
1160
|
+
if (t == 'checkbox' || t == 'radio') {
|
1161
|
+
this.checked = select;
|
1162
|
+
}
|
1163
|
+
else if (this.tagName.toLowerCase() == 'option') {
|
1164
|
+
var $sel = $(this).parent('select');
|
1165
|
+
if (select && $sel[0] && $sel[0].type == 'select-one') {
|
1166
|
+
// deselect all other options
|
1167
|
+
$sel.find('option').selected(false);
|
975
1168
|
}
|
976
|
-
|
977
|
-
|
1169
|
+
this.selected = select;
|
1170
|
+
}
|
1171
|
+
});
|
1172
|
+
};
|
978
1173
|
|
979
1174
|
// expose debug var
|
980
|
-
|
1175
|
+
$.fn.ajaxSubmit.debug = false;
|
981
1176
|
|
982
1177
|
// helper fn for console logging
|
983
|
-
|
984
|
-
|
985
|
-
|
986
|
-
|
987
|
-
|
988
|
-
|
989
|
-
|
990
|
-
|
991
|
-
|
992
|
-
|
993
|
-
|
1178
|
+
function log() {
|
1179
|
+
if (!$.fn.ajaxSubmit.debug)
|
1180
|
+
return;
|
1181
|
+
var msg = '[jquery.form] ' + Array.prototype.join.call(arguments,'');
|
1182
|
+
if (window.console && window.console.log) {
|
1183
|
+
window.console.log(msg);
|
1184
|
+
}
|
1185
|
+
else if (window.opera && window.opera.postError) {
|
1186
|
+
window.opera.postError(msg);
|
1187
|
+
}
|
1188
|
+
}
|
994
1189
|
|
995
1190
|
})(jQuery);
|