Contact Form 7 - Version 3.1.2

Version Description

  • Auto-generate .htaccess file in the CAPTCHAs temporary folder to hide answer files in it.
  • Make sure all fields given by form-tags are in the posted_data property.
  • Fix the RTL style sheet for admin pages.
  • Bug fixed: names of uploaded files dont appear in mail body.
  • The jQuery Form Plugin (jquery.form.js) has been updated to 3.08.
  • Translations for German, Hungarian, Slovene, and Lithuanian have been updated.
Download this release

Release Info

Developer takayukister
Plugin Icon 128x128 Contact Form 7
Version 3.1.2
Comparing to
See all releases

Code changes from version 3.1.1 to 3.1.2

admin/styles-rtl.css CHANGED
@@ -2,17 +2,25 @@ ul.subsubsub li.addnew {
2
margin-left: 0;
3
margin-right: 0.5em;
4
}
5
div.save-contact-form {
6
direction: rtl;
7
}
8
div.actions-link {
9
right: auto;
10
left: 0;
11
}
12
div.tg-pane table caption {
13
text-align: right;
14
}
15
div.tg-dropdown {
16
left: auto;
17
right: 0;
18
}
2
margin-left: 0;
3
margin-right: 0.5em;
4
}
5
+
6
div.save-contact-form {
7
direction: rtl;
8
}
9
+
10
div.actions-link {
11
right: auto;
12
left: 0;
13
}
14
+
15
div.tg-pane table caption {
16
text-align: right;
17
}
18
+
19
div.tg-dropdown {
20
left: auto;
21
right: 0;
22
+ }
23
+
24
+ div.wrap div.cf7com-links {
25
+ text-align: left;
26
}
includes/classes.php CHANGED
@@ -222,11 +222,10 @@ class WPCF7_ContactForm {
222
continue;
223
224
$name = $fe['name'];
225
226
- if ( ! isset( $_POST[$name] ) )
227
- continue;
228
-
229
- $value = $_POST[$name];
230
231
$pipes = $fe['pipes'];
232
222
continue;
223
224
$name = $fe['name'];
225
+ $value = '';
226
227
+ if ( isset( $posted_data[$name] ) )
228
+ $value = $posted_data[$name];
229
230
$pipes = $fe['pipes'];
231
includes/controller.php CHANGED
@@ -231,7 +231,7 @@ function wpcf7_enqueue_scripts() {
231
// so we need to deregister it and re-register the latest one
232
wp_deregister_script( 'jquery-form' );
233
wp_register_script( 'jquery-form', wpcf7_plugin_url( 'jquery.form.js' ),
234
- array( 'jquery' ), '2.96', true );
235
236
$in_footer = true;
237
if ( 'header' === WPCF7_LOAD_JS )
231
// so we need to deregister it and re-register the latest one
232
wp_deregister_script( 'jquery-form' );
233
wp_register_script( 'jquery-form', wpcf7_plugin_url( 'jquery.form.js' ),
234
+ array( 'jquery' ), '3.08', true );
235
236
$in_footer = true;
237
if ( 'header' === WPCF7_LOAD_JS )
jquery.form.js CHANGED
@@ -1,629 +1,664 @@
1
/*!
2
* jQuery Form Plugin
3
- * version: 2.96 (16-FEB-2012)
4
* @requires jQuery v1.3.2 or later
5
*
6
* Examples and documentation at: http://malsup.com/jquery/form/
7
* Dual licensed under the MIT and GPL licenses:
8
- * http://www.opensource.org/licenses/mit-license.php
9
- * http://www.gnu.org/licenses/gpl.html
10
*/
11
;(function($) {
12
13
/*
14
- Usage Note:
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
- }
60
-
61
- var method, action, url, $form = this;
62
-
63
- if (typeof options == 'function') {
64
- options = { success: options };
65
- }
66
-
67
- method = this.attr('method');
68
- action = this.attr('action');
69
- url = (typeof action === 'string') ? $.trim(action) : '';
70
- url = url || window.location.href || '';
71
- if (url) {
72
- // clean url (don't include hash vaue)
73
- url = (url.match(/^([^#]+)/)||[])[1];
74
- }
75
-
76
- options = $.extend(true, {
77
- url: url,
78
- success: $.ajaxSettings.success,
79
- type: method || 'GET',
80
- iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank'
81
- }, options);
82
-
83
- // hook for manipulating the form data before it is extracted;
84
- // convenient for use with rich editors like tinyMCE or FCKEditor
85
- var veto = {};
86
- this.trigger('form-pre-serialize', [this, options, veto]);
87
- if (veto.veto) {
88
- log('ajaxSubmit: submit vetoed via form-pre-serialize trigger');
89
- return this;
90
- }
91
-
92
- // provide opportunity to alter form data before it is serialized
93
- if (options.beforeSerialize && options.beforeSerialize(this, options) === false) {
94
- log('ajaxSubmit: submit aborted via beforeSerialize callback');
95
- return this;
96
- }
97
-
98
- var traditional = options.traditional;
99
- if ( traditional === undefined ) {
100
- traditional = $.ajaxSettings.traditional;
101
- }
102
-
103
- var qx,n,v,a = this.formToArray(options.semantic);
104
- if (options.data) {
105
- options.extraData = options.data;
106
- qx = $.param(options.data, traditional);
107
- }
108
-
109
- // give pre-submit callback an opportunity to abort the submit
110
- if (options.beforeSubmit && options.beforeSubmit(a, this, options) === false) {
111
- log('ajaxSubmit: submit aborted via beforeSubmit callback');
112
- return this;
113
- }
114
-
115
- // fire vetoable 'validate' event
116
- this.trigger('form-submit-validate', [a, this, options, veto]);
117
- if (veto.veto) {
118
- log('ajaxSubmit: submit vetoed via form-submit-validate trigger');
119
- return this;
120
- }
121
-
122
- var q = $.param(a, traditional);
123
- if (qx) {
124
- q = ( q ? (q + '&' + qx) : qx );
125
- }
126
- if (options.type.toUpperCase() == 'GET') {
127
- options.url += (options.url.indexOf('?') >= 0 ? '&' : '?') + q;
128
- options.data = null; // data is null for 'get'
129
- }
130
- else {
131
- options.data = q; // data is the query string for 'post'
132
- }
133
-
134
- var callbacks = [];
135
- if (options.resetForm) {
136
- callbacks.push(function() { $form.resetForm(); });
137
- }
138
- if (options.clearForm) {
139
- callbacks.push(function() { $form.clearForm(options.includeHidden); });
140
- }
141
-
142
- // perform a load on the target only if dataType is not provided
143
- if (!options.dataType && options.target) {
144
- var oldSuccess = options.success || function(){};
145
- callbacks.push(function(data) {
146
- var fn = options.replaceTarget ? 'replaceWith' : 'html';
147
- $(options.target)[fn](data).each(oldSuccess, arguments);
148
- });
149
- }
150
- else if (options.success) {
151
- callbacks.push(options.success);
152
- }
153
-
154
- options.success = function(data, status, xhr) { // jQuery 1.4+ passes xhr as 3rd arg
155
- var context = options.context || options; // jQuery 1.4+ supports scope context
156
- for (var i=0, max=callbacks.length; i < max; i++) {
157
- callbacks[i].apply(context, [data, status, xhr || $form, $form]);
158
- }
159
- };
160
-
161
- // are there files to upload?
162
- var fileInputs = $('input:file:enabled[value]', this); // [value] (issue #113)
163
- var hasFileInputs = fileInputs.length > 0;
164
- var mp = 'multipart/form-data';
165
- var multipart = ($form.attr('enctype') == mp || $form.attr('encoding') == mp);
166
-
167
- var fileAPI = !!(hasFileInputs && fileInputs.get(0).files && window.FormData);
168
- log("fileAPI :" + fileAPI);
169
- var shouldUseFrame = (hasFileInputs || multipart) && !fileAPI;
170
-
171
- // options.iframe allows user to force iframe mode
172
- // 06-NOV-09: now defaulting to iframe mode if file input is detected
173
- if (options.iframe !== false && (options.iframe || shouldUseFrame)) {
174
- // hack to fix Safari hang (thanks to Tim Molendijk for this)
175
- // see: http://groups.google.com/group/jquery-dev/browse_thread/thread/36395b7ab510dd5d
176
- if (options.closeKeepAlive) {
177
- $.get(options.closeKeepAlive, function() {
178
- fileUploadIframe(a);
179
- });
180
- }
181
- else {
182
- fileUploadIframe(a);
183
- }
184
- }
185
- else if ((hasFileInputs || multipart) && fileAPI) {
186
- options.progress = options.progress || $.noop;
187
- fileUploadXhr(a);
188
- }
189
- else {
190
- $.ajax(options);
191
- }
192
-
193
- // fire 'notify' event
194
- this.trigger('form-submit-notify', [this, options]);
195
- return this;
196
-
197
- // XMLHttpRequest Level 2 file uploads (big hat tip to francois2metz)
198
- function fileUploadXhr(a) {
199
- var formdata = new FormData();
200
-
201
- for (var i=0; i < a.length; i++) {
202
- if (a[i].type == 'file')
203
- continue;
204
- formdata.append(a[i].name, a[i].value);
205
- }
206
-
207
- $form.find('input:file:enabled').each(function(){
208
- var name = $(this).attr('name'), files = this.files;
209
- if (name) {
210
- for (var i=0; i < files.length; i++)
211
- formdata.append(name, files[i]);
212
- }
213
- });
214
-
215
- if (options.extraData) {
216
- for (var k in options.extraData)
217
- formdata.append(k, options.extraData[k])
218
- }
219
-
220
- options.data = null;
221
-
222
- var s = $.extend(true, {}, $.ajaxSettings, options, {
223
- contentType: false,
224
- processData: false,
225
- cache: false,
226
- type: 'POST'
227
- });
228
-
229
- //s.context = s.context || s;
230
-
231
- s.data = null;
232
- var beforeSend = s.beforeSend;
233
- s.beforeSend = function(xhr, o) {
234
- o.data = formdata;
235
- if(xhr.upload) { // unfortunately, jQuery doesn't expose this prop (http://bugs.jquery.com/ticket/10190)
236
- xhr.upload.onprogress = function(event) {
237
- o.progress(event.position, event.total);
238
- };
239
}
240
- if(beforeSend)
241
- beforeSend.call(o, xhr, options);
242
- };
243
- $.ajax(s);
244
- }
245
-
246
- // private function for handling file uploads (hat tip to YAHOO!)
247
- function fileUploadIframe(a) {
248
- var form = $form[0], el, i, s, g, id, $io, io, xhr, sub, n, timedOut, timeoutHandle;
249
- var useProp = !!$.fn.prop;
250
-
251
- if (a) {
252
- if ( useProp ) {
253
- // ensure that every serialized input is still enabled
254
- for (i=0; i < a.length; i++) {
255
- el = $(form[a[i].name]);
256
- el.prop('disabled', false);
257
- }
258
- } else {
259
- for (i=0; i < a.length; i++) {
260
- el = $(form[a[i].name]);
261
- el.removeAttr('disabled');
262
- }
263
- };
264
- }
265
-
266
- if ($(':input[name=submit],:input[id=submit]', form).length) {
267
- // if there is an input with a name or id of 'submit' then we won't be
268
- // able to invoke the submit fn on the form (at least not x-browser)
269
- alert('Error: Form elements must not have name or id of "submit".');
270
- return;
271
- }
272
-
273
- s = $.extend(true, {}, $.ajaxSettings, options);
274
- s.context = s.context || s;
275
- id = 'jqFormIO' + (new Date().getTime());
276
- if (s.iframeTarget) {
277
- $io = $(s.iframeTarget);
278
- n = $io.attr('name');
279
- if (n == null)
280
- $io.attr('name', id);
281
- else
282
- id = n;
283
- }
284
- else {
285
- $io = $('<iframe name="' + id + '" src="'+ s.iframeSrc +'" />');
286
- $io.css({ position: 'absolute', top: '-1000px', left: '-1000px' });
287
- }
288
- io = $io[0];
289
-
290
-
291
- xhr = { // mock object
292
- aborted: 0,
293
- responseText: null,
294
- responseXML: null,
295
- status: 0,
296
- statusText: 'n/a',
297
- getAllResponseHeaders: function() {},
298
- getResponseHeader: function() {},
299
- setRequestHeader: function() {},
300
- abort: function(status) {
301
- var e = (status === 'timeout' ? 'timeout' : 'aborted');
302
- log('aborting upload... ' + e);
303
- this.aborted = 1;
304
- $io.attr('src', s.iframeSrc); // abort op in progress
305
- xhr.error = e;
306
- s.error && s.error.call(s.context, xhr, e, status);
307
- g && $.event.trigger("ajaxError", [xhr, s, e]);
308
- s.complete && s.complete.call(s.context, xhr, e);
309
- }
310
- };
311
-
312
- g = s.global;
313
- // trigger ajax global events so that activity/block indicators work like normal
314
- if (g && ! $.active++) {
315
- $.event.trigger("ajaxStart");
316
- }
317
- if (g) {
318
- $.event.trigger("ajaxSend", [xhr, s]);
319
- }
320
-
321
- if (s.beforeSend && s.beforeSend.call(s.context, xhr, s) === false) {
322
- if (s.global) {
323
- $.active--;
324
- }
325
- return;
326
- }
327
- if (xhr.aborted) {
328
- return;
329
- }
330
-
331
- // add submitting element to data if we know it
332
- sub = form.clk;
333
- if (sub) {
334
- n = sub.name;
335
- if (n && !sub.disabled) {
336
- s.extraData = s.extraData || {};
337
- s.extraData[n] = sub.value;
338
- if (sub.type == "image") {
339
- s.extraData[n+'.x'] = form.clk_x;
340
- s.extraData[n+'.y'] = form.clk_y;
341
- }
342
- }
343
- }
344
-
345
- var CLIENT_TIMEOUT_ABORT = 1;
346
- var SERVER_ABORT = 2;
347
-
348
- function getDoc(frame) {
349
- var doc = frame.contentWindow ? frame.contentWindow.document : frame.contentDocument ? frame.contentDocument : frame.document;
350
- return doc;
351
- }
352
-
353
- // Rails CSRF hack (thanks to Yvan Barthelemy)
354
- var csrf_token = $('meta[name=csrf-token]').attr('content');
355
- var csrf_param = $('meta[name=csrf-param]').attr('content');
356
- if (csrf_param && csrf_token) {
357
- s.extraData = s.extraData || {};
358
- s.extraData[csrf_param] = csrf_token;
359
- }
360
-
361
- // take a breath so that pending repaints get some cpu time before the upload starts
362
- function doSubmit() {
363
- // make sure form attrs are set
364
- var t = $form.attr('target'), a = $form.attr('action');
365
-
366
- // update form attrs in IE friendly way
367
- form.setAttribute('target',id);
368
- if (!method) {
369
- form.setAttribute('method', 'POST');
370
- }
371
- if (a != s.url) {
372
- form.setAttribute('action', s.url);
373
- }
374
-
375
- // ie borks in some cases when setting encoding
376
- if (! s.skipEncodingOverride && (!method || /post/i.test(method))) {
377
- $form.attr({
378
- encoding: 'multipart/form-data',
379
- enctype: 'multipart/form-data'
380
- });
381
- }
382
-
383
- // support timout
384
- if (s.timeout) {
385
- timeoutHandle = setTimeout(function() { timedOut = true; cb(CLIENT_TIMEOUT_ABORT); }, s.timeout);
386
- }
387
-
388
- // look for server aborts
389
- function checkState() {
390
- try {
391
- var state = getDoc(io).readyState;
392
- log('state = ' + state);
393
- if (state.toLowerCase() == 'uninitialized')
394
- setTimeout(checkState,50);
395
- }
396
- catch(e) {
397
- log('Server abort: ' , e, ' (', e.name, ')');
398
- cb(SERVER_ABORT);
399
- timeoutHandle && clearTimeout(timeoutHandle);
400
- timeoutHandle = undefined;
401
- }
402
- }
403
-
404
- // add "extra" data to form if provided in options
405
- var extraInputs = [];
406
- try {
407
- if (s.extraData) {
408
- for (var n in s.extraData) {
409
- extraInputs.push(
410
- $('<input type="hidden" name="'+n+'">').attr('value',s.extraData[n])
411
- .appendTo(form)[0]);
412
- }
413
- }
414
-
415
- if (!s.iframeTarget) {
416
- // add iframe to doc and submit the form
417
- $io.appendTo('body');
418
- io.attachEvent ? io.attachEvent('onload', cb) : io.addEventListener('load', cb, false);
419
- }
420
- setTimeout(checkState,15);
421
- form.submit();
422
- }
423
- finally {
424
- // reset attrs and remove "extra" input elements
425
- form.setAttribute('action',a);
426
- if(t) {
427
- form.setAttribute('target', t);
428
- } else {
429
- $form.removeAttr('target');
430
- }
431
- $(extraInputs).remove();
432
- }
433
- }
434
-
435
- if (s.forceSync) {
436
- doSubmit();
437
- }
438
- else {
439
- setTimeout(doSubmit, 10); // this lets dom updates render
440
- }
441
-
442
- var data, doc, domCheckCount = 50, callbackProcessed;
443
-
444
- function cb(e) {
445
- if (xhr.aborted || callbackProcessed) {
446
- return;
447
- }
448
- try {
449
- doc = getDoc(io);
450
- }
451
- catch(ex) {
452
- log('cannot access response document: ', ex);
453
- e = SERVER_ABORT;
454
- }
455
- if (e === CLIENT_TIMEOUT_ABORT && xhr) {
456
- xhr.abort('timeout');
457
- return;
458
- }
459
- else if (e == SERVER_ABORT && xhr) {
460
- xhr.abort('server abort');
461
- return;
462
- }
463
-
464
- if (!doc || doc.location.href == s.iframeSrc) {
465
- // response not received yet
466
- if (!timedOut)
467
- return;
468
- }
469
- io.detachEvent ? io.detachEvent('onload', cb) : io.removeEventListener('load', cb, false);
470
-
471
- var status = 'success', errMsg;
472
- try {
473
- if (timedOut) {
474
- throw 'timeout';
475
- }
476
-
477
- var isXml = s.dataType == 'xml' || doc.XMLDocument || $.isXMLDoc(doc);
478
- log('isXml='+isXml);
479
- if (!isXml && window.opera && (doc.body == null || doc.body.innerHTML == '')) {
480
- if (--domCheckCount) {
481
- // in some browsers (Opera) the iframe DOM is not always traversable when
482
- // the onload callback fires, so we loop a bit to accommodate
483
- log('requeing onLoad callback, DOM not available');
484
- setTimeout(cb, 250);
485
- return;
486
- }
487
- // let this fall through because server response could be an empty document
488
- //log('Could not access iframe DOM after mutiple tries.');
489
- //throw 'DOMException: not available';
490
- }
491
-
492
- //log('response detected');
493
- var docRoot = doc.body ? doc.body : doc.documentElement;
494
- xhr.responseText = docRoot ? docRoot.innerHTML : null;
495
- xhr.responseXML = doc.XMLDocument ? doc.XMLDocument : doc;
496
- if (isXml)
497
- s.dataType = 'xml';
498
- xhr.getResponseHeader = function(header){
499
- var headers = {'content-type': s.dataType};
500
- return headers[header];
501
- };
502
- // support for XHR 'status' & 'statusText' emulation :
503
- if (docRoot) {
504
- xhr.status = Number( docRoot.getAttribute('status') ) || xhr.status;
505
- xhr.statusText = docRoot.getAttribute('statusText') || xhr.statusText;
506
- }
507
-
508
- var dt = (s.dataType || '').toLowerCase();
509
- var scr = /(json|script|text)/.test(dt);
510
- if (scr || s.textarea) {
511
- // see if user embedded response in textarea
512
- var ta = doc.getElementsByTagName('textarea')[0];
513
- if (ta) {
514
- xhr.responseText = ta.value;
515
- // support for XHR 'status' & 'statusText' emulation :
516
- xhr.status = Number( ta.getAttribute('status') ) || xhr.status;
517
- xhr.statusText = ta.getAttribute('statusText') || xhr.statusText;
518
- }
519
- else if (scr) {
520
- // account for browsers injecting pre around json response
521
- var pre = doc.getElementsByTagName('pre')[0];
522
- var b = doc.getElementsByTagName('body')[0];
523
- if (pre) {
524
- xhr.responseText = pre.textContent ? pre.textContent : pre.innerText;
525
- }
526
- else if (b) {
527
- xhr.responseText = b.textContent ? b.textContent : b.innerText;
528
- }
529
- }
530
- }
531
- else if (dt == 'xml' && !xhr.responseXML && xhr.responseText != null) {
532
- xhr.responseXML = toXml(xhr.responseText);
533
- }
534
-
535
- try {
536
- data = httpData(xhr, dt, s);
537
- }
538
- catch (e) {
539
- status = 'parsererror';
540
- xhr.error = errMsg = (e || status);
541
- }
542
- }
543
- catch (e) {
544
- log('error caught: ',e);
545
- status = 'error';
546
- xhr.error = errMsg = (e || status);
547
- }
548
-
549
- if (xhr.aborted) {
550
- log('upload aborted');
551
- status = null;
552
- }
553
-
554
- if (xhr.status) { // we've set xhr.status
555
- status = (xhr.status >= 200 && xhr.status < 300 || xhr.status === 304) ? 'success' : 'error';
556
- }
557
-
558
- // ordering of these callbacks/triggers is odd, but that's how $.ajax does it
559
- if (status === 'success') {
560
- s.success && s.success.call(s.context, data, 'success', xhr);
561
- g && $.event.trigger("ajaxSuccess", [xhr, s]);
562
- }
563
- else if (status) {
564
- if (errMsg == undefined)
565
- errMsg = xhr.statusText;
566
- s.error && s.error.call(s.context, xhr, status, errMsg);
567
- g && $.event.trigger("ajaxError", [xhr, s, errMsg]);
568
- }
569
-
570
- g && $.event.trigger("ajaxComplete", [xhr, s]);
571
-
572
- if (g && ! --$.active) {
573
- $.event.trigger("ajaxStop");
574
- }
575
-
576
- s.complete && s.complete.call(s.context, xhr, status);
577
-
578
- callbackProcessed = true;
579
- if (s.timeout)
580
- clearTimeout(timeoutHandle);
581
-
582
- // clean up
583
- setTimeout(function() {
584
- if (!s.iframeTarget)
585
- $io.remove();
586
- xhr.responseXML = null;
587
- }, 100);
588
- }
589
-
590
- var toXml = $.parseXML || function(s, doc) { // use parseXML if available (jQuery 1.5+)
591
- if (window.ActiveXObject) {
592
- doc = new ActiveXObject('Microsoft.XMLDOM');
593
- doc.async = 'false';
594
- doc.loadXML(s);
595
- }
596
- else {
597
- doc = (new DOMParser()).parseFromString(s, 'text/xml');
598
- }
599
- return (doc && doc.documentElement && doc.documentElement.nodeName != 'parsererror') ? doc : null;
600
- };
601
- var parseJSON = $.parseJSON || function(s) {
602
- return window['eval']('(' + s + ')');
603
- };
604
-
605
- var httpData = function( xhr, type, s ) { // mostly lifted from jq1.4.4
606
-
607
- var ct = xhr.getResponseHeader('content-type') || '',
608
- xml = type === 'xml' || !type && ct.indexOf('xml') >= 0,
609
- data = xml ? xhr.responseXML : xhr.responseText;
610
-
611
- if (xml && data.documentElement.nodeName === 'parsererror') {
612
- $.error && $.error('parsererror');
613
- }
614
- if (s && s.dataFilter) {
615
- data = s.dataFilter(data, type);
616
- }
617
- if (typeof data === 'string') {
618
- if (type === 'json' || !type && ct.indexOf('json') >= 0) {
619
- data = parseJSON(data);
620
- } else if (type === "script" || !type && ct.indexOf("javascript") >= 0) {
621
- $.globalEval(data);
622
- }
623
- }
624
- return data;
625
- };
626
- }
627
};
628
629
/**
@@ -632,9 +667,9 @@ $.fn.ajaxSubmit = function(options) {
632
* The advantages of using this method instead of ajaxSubmit() are:
633
*
634
* 1: This method will include coordinates for <input type="image" /> elements (if the element
635
- * is used to submit the form).
636
* 2. This method will include the submit element's name/value data (for the element that was
637
- * used to submit the form).
638
* 3. This method binds the submit() method to the form for you.
639
*
640
* The options argument for ajaxForm works exactly as it does for ajaxSubmit. ajaxForm merely
@@ -642,81 +677,83 @@ $.fn.ajaxSubmit = function(options) {
642
* the form itself.
643
*/
644
$.fn.ajaxForm = function(options) {
645
- options = options || {};
646
- options.delegation = options.delegation && $.isFunction($.fn.on);
647
-
648
- // in jQuery 1.3+ we can fix mistakes with the ready state
649
- if (!options.delegation && this.length === 0) {
650
- var o = { s: this.selector, c: this.context };
651
- if (!$.isReady && o.s) {
652
- log('DOM not ready, queuing ajaxForm');
653
- $(function() {
654
- $(o.s,o.c).ajaxForm(options);
655
- });
656
- return this;
657
- }
658
- // is your DOM ready? http://docs.jquery.com/Tutorials:Introducing_$(document).ready()
659
- log('terminating; zero elements found by selector' + ($.isReady ? '' : ' (DOM not ready)'));
660
- return this;
661
- }
662
-
663
- if ( options.delegation ) {
664
- $(document)
665
- .off('submit.form-plugin', this.selector, doAjaxSubmit)
666
- .off('click.form-plugin', this.selector, captureSubmittingElement)
667
- .on('submit.form-plugin', this.selector, options, doAjaxSubmit)
668
- .on('click.form-plugin', this.selector, options, captureSubmittingElement);
669
- return this;
670
- }
671
-
672
- return this.ajaxFormUnbind()
673
- .bind('submit.form-plugin', options, doAjaxSubmit)
674
- .bind('click.form-plugin', options, captureSubmittingElement);
675
};
676
677
- // private event handlers
678
function doAjaxSubmit(e) {
679
- var options = e.data;
680
- if (!e.isDefaultPrevented()) { // if event has been canceled, don't proceed
681
- e.preventDefault();
682
- $(this).ajaxSubmit(options);
683
- }
684
}
685
-
686
function captureSubmittingElement(e) {
687
- var target = e.target;
688
- var $el = $(target);
689
- if (!($el.is(":submit,input:image"))) {
690
- // is this a child element of the submit el? (ex: a span within a button)
691
- var t = $el.closest(':submit');
692
- if (t.length == 0) {
693
- return;
694
- }
695
- target = t[0];
696
- }
697
- var form = this;
698
- form.clk = target;
699
- if (target.type == 'image') {
700
- if (e.offsetX != undefined) {
701
- form.clk_x = e.offsetX;
702
- form.clk_y = e.offsetY;
703
- } else if (typeof $.fn.offset == 'function') {
704
- var offset = $el.offset();
705
- form.clk_x = e.pageX - offset.left;
706
- form.clk_y = e.pageY - offset.top;
707
- } else {
708
- form.clk_x = e.pageX - target.offsetLeft;
709
- form.clk_y = e.pageY - target.offsetTop;
710
- }
711
- }
712
- // clear form vars
713
- setTimeout(function() { form.clk = form.clk_x = form.clk_y = null; }, 100);
714
- };
715
716
717
// ajaxFormUnbind unbinds the event handlers that were bound by ajaxForm
718
$.fn.ajaxFormUnbind = function() {
719
- return this.unbind('submit.form-plugin click.form-plugin');
720
};
721
722
/**
@@ -730,56 +767,68 @@ $.fn.ajaxFormUnbind = function() {
730
* It is this array that is passed to pre-submit callback functions provided to the
731
* ajaxSubmit() and ajaxForm() methods.
732
*/
733
- $.fn.formToArray = function(semantic) {
734
- var a = [];
735
- if (this.length === 0) {
736
- return a;
737
- }
738
-
739
- var form = this[0];
740
- var els = semantic ? form.getElementsByTagName('*') : form.elements;
741
- if (!els) {
742
- return a;
743
- }
744
-
745
- var i,j,n,v,el,max,jmax;
746
- for(i=0, max=els.length; i < max; i++) {
747
- el = els[i];
748
- n = el.name;
749
- if (!n) {
750
- continue;
751
- }
752
-
753
- if (semantic && form.clk && el.type == "image") {
754
- // handle image inputs on the fly when semantic == true
755
- if(!el.disabled && form.clk == el) {
756
- a.push({name: n, value: $(el).val(), type: el.type });
757
- a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
758
- }
759
- continue;
760
- }
761
-
762
- v = $.fieldValue(el, true);
763
- if (v && v.constructor == Array) {
764
- for(j=0, jmax=v.length; j < jmax; j++) {
765
- a.push({name: n, value: v[j]});
766
- }
767
- }
768
- else if (v !== null && typeof v != 'undefined') {
769
- a.push({name: n, value: v, type: el.type});
770
- }
771
- }
772
-
773
- if (!semantic && form.clk) {
774
- // input type=='image' are not found in elements array! handle it here
775
- var $input = $(form.clk), input = $input[0];
776
- n = input.name;
777
- if (n && !input.disabled && input.type == 'image') {
778
- a.push({name: n, value: $input.val()});
779
- a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
780
- }
781
- }
782
- return a;
783
};
784
785
/**
@@ -787,8 +836,8 @@ $.fn.formToArray = function(semantic) {
787
* in the format: name1=value1&amp;name2=value2
788
*/
789
$.fn.formSerialize = function(semantic) {
790
- //hand off to jQuery.param for proper encoding
791
- return $.param(this.formToArray(semantic));
792
};
793
794
/**
@@ -796,36 +845,36 @@ $.fn.formSerialize = function(semantic) {
796
* This method will return a string in the format: name1=value1&amp;name2=value2
797
*/
798
$.fn.fieldSerialize = function(successful) {
799
- var a = [];
800
- this.each(function() {
801
- var n = this.name;
802
- if (!n) {
803
- return;
804
- }
805
- var v = $.fieldValue(this, successful);
806
- if (v && v.constructor == Array) {
807
- for (var i=0,max=v.length; i < max; i++) {
808
- a.push({name: n, value: v[i]});
809
- }
810
- }
811
- else if (v !== null && typeof v != 'undefined') {
812
- a.push({name: this.name, value: v});
813
- }
814
- });
815
- //hand off to jQuery.param for proper encoding
816
- return $.param(a);
817
};
818
819
/**
820
* Returns the value(s) of the element in the matched set. For example, consider the following form:
821
*
822
* <form><fieldset>
823
- * <input name="A" type="text" />
824
- * <input name="A" type="text" />
825
- * <input name="B" type="checkbox" value="B1" />
826
- * <input name="B" type="checkbox" value="B2"/>
827
- * <input name="C" type="radio" value="C1" />
828
- * <input name="C" type="radio" value="C2" />
829
* </fieldset></form>
830
*
831
* var v = $(':text').fieldValue();
@@ -852,60 +901,63 @@ $.fn.fieldSerialize = function(successful) {
852
* for each element is returned.
853
*
854
* Note: This method *always* returns an array. If no valid value can be determined the
855
- * array will be empty, otherwise it will contain one or more values.
856
*/
857
$.fn.fieldValue = function(successful) {
858
- for (var val=[], i=0, max=this.length; i < max; i++) {
859
- var el = this[i];
860
- var v = $.fieldValue(el, successful);
861
- if (v === null || typeof v == 'undefined' || (v.constructor == Array && !v.length)) {
862
- continue;
863
- }
864
- v.constructor == Array ? $.merge(val, v) : val.push(v);
865
- }
866
- return val;
867
};
868
869
/**
870
* Returns the value of the field element.
871
*/
872
$.fieldValue = function(el, successful) {
873
- var n = el.name, t = el.type, tag = el.tagName.toLowerCase();
874
- if (successful === undefined) {
875
- successful = true;
876
- }
877
-
878
- if (successful && (!n || el.disabled || t == 'reset' || t == 'button' ||
879
- (t == 'checkbox' || t == 'radio') && !el.checked ||
880
- (t == 'submit' || t == 'image') && el.form && el.form.clk != el ||
881
- tag == 'select' && el.selectedIndex == -1)) {
882
- return null;
883
- }
884
-
885
- if (tag == 'select') {
886
- var index = el.selectedIndex;
887
- if (index < 0) {
888
- return null;
889
- }
890
- var a = [], ops = el.options;
891
- var one = (t == 'select-one');
892
- var max = (one ? index+1 : ops.length);
893
- for(var i=(one ? index : 0); i < max; i++) {
894
- var op = ops[i];
895
- if (op.selected) {
896
- var v = op.value;
897
- if (!v) { // extra pain for IE...
898
- v = (op.attributes && op.attributes['value'] && !(op.attributes['value'].specified)) ? op.text : op.value;
899
- }
900
- if (one) {
901
- return v;
902
- }
903
- a.push(v);
904
- }
905
- }
906
- return a;
907
- }
908
- return $(el).val();
909
};
910
911
/**
@@ -917,53 +969,62 @@ $.fieldValue = function(el, successful) {
917
* - button elements will *not* be effected
918
*/
919
$.fn.clearForm = function(includeHidden) {
920
- return this.each(function() {
921
- $('input,select,textarea', this).clearFields(includeHidden);
922
- });
923
};
924
925
/**
926
* Clears the selected form elements.
927
*/
928
$.fn.clearFields = $.fn.clearInputs = function(includeHidden) {
929
- var re = /^(?:color|date|datetime|email|month|number|password|range|search|tel|text|time|url|week)#x2F;i; // 'hidden' is not in this list
930
- return this.each(function() {
931
- var t = this.type, tag = this.tagName.toLowerCase();
932
- if (re.test(t) || tag == 'textarea' || (includeHidden && /hidden/.test(t)) ) {
933
- this.value = '';
934
- }
935
- else if (t == 'checkbox' || t == 'radio') {
936
- this.checked = false;
937
- }
938
- else if (tag == 'select') {
939
- this.selectedIndex = -1;
940
- }
941
- });
942
};
943
944
/**
945
* Resets the form data. Causes all form elements to be reset to their original value.
946
*/
947
$.fn.resetForm = function() {
948
- return this.each(function() {
949
- // guard against an input with the name of 'reset'
950
- // note that IE reports the reset function as an 'object'
951
- if (typeof this.reset == 'function' || (typeof this.reset == 'object' && !this.reset.nodeType)) {
952
- this.reset();
953
- }
954
- });
955
};
956
957
/**
958
* Enables or disables any matching elements.
959
*/
960
$.fn.enable = function(b) {
961
- if (b === undefined) {
962
- b = true;
963
- }
964
- return this.each(function() {
965
- this.disabled = !b;
966
- });
967
};
968
969
/**
@@ -971,23 +1032,23 @@ $.fn.enable = function(b) {
971
* selects/deselects and matching option elements.
972
*/
973
$.fn.selected = function(select) {
974
- if (select === undefined) {
975
- select = true;
976
- }
977
- return this.each(function() {
978
- var t = this.type;
979
- if (t == 'checkbox' || t == 'radio') {
980
- this.checked = select;
981
- }
982
- else if (this.tagName.toLowerCase() == 'option') {
983
- var $sel = $(this).parent('select');
984
- if (select && $sel[0] && $sel[0].type == 'select-one') {
985
- // deselect all other options
986
- $sel.find('option').selected(false);
987
- }
988
- this.selected = select;
989
- }
990
- });
991
};
992
993
// expose debug var
@@ -995,15 +1056,15 @@ $.fn.ajaxSubmit.debug = false;
995
996
// helper fn for console logging
997
function log() {
998
- if (!$.fn.ajaxSubmit.debug)
999
- return;
1000
- var msg = '[jquery.form] ' + Array.prototype.join.call(arguments,'');
1001
- if (window.console && window.console.log) {
1002
- window.console.log(msg);
1003
- }
1004
- else if (window.opera && window.opera.postError) {
1005
- window.opera.postError(msg);
1006
- }
1007
- };
1008
1009
})(jQuery);
1
/*!
2
* jQuery Form Plugin
3
+ * version: 3.08 (07-APR-2012)
4
* @requires jQuery v1.3.2 or later
5
*
6
* Examples and documentation at: http://malsup.com/jquery/form/
7
+ * Project repository: https://github.com/malsup/form
8
* Dual licensed under the MIT and GPL licenses:
9
+ * http://malsup.github.com/mit-license.txt
10
+ * http://malsup.github.com/gpl-license-v2.txt
11
*/
12
+ /*global ActiveXObject alert */
13
;(function($) {
14
+ "use strict";
15
16
/*
17
+ Usage Note:
18
+ -----------
19
+ Do not use both ajaxSubmit and ajaxForm on the same form. These
20
+ functions are mutually exclusive. Use ajaxSubmit if you want
21
+ to bind your own submit handler to the form. For example,
22
+
23
+ $(document).ready(function() {
24
+ $('#myForm').bind('submit', function(e) {
25
+ e.preventDefault(); // <-- important
26
+ $(this).ajaxSubmit({
27
+ target: '#output'
28
+ });
29
+ });
30
+ });
31
+
32
+ Use ajaxForm when you want the plugin to manage all the event binding
33
+ for you. For example,
34
+
35
+ $(document).ready(function() {
36
+ $('#myForm').ajaxForm({
37
+ target: '#output'
38
+ });
39
+ });
40
+
41
+ You can also use ajaxForm with delegation (requires jQuery v1.7+), so the
42
+ form does not have to exist when you invoke ajaxForm:
43
+
44
+ $('#myForm').ajaxForm({
45
+ delegation: true,
46
+ target: '#output'
47
+ });
48
+
49
+ When using ajaxForm, the ajaxSubmit function will be invoked for you
50
+ at the appropriate time.
51
*/
52
53
+ /**
54
+ * Feature detection
55
+ */
56
+ var feature = {};
57
+ feature.fileapi = $("<input type='file'/>").get(0).files !== undefined;
58
+ feature.formdata = window.FormData !== undefined;
59
+
60
/**
61
* ajaxSubmit() provides a mechanism for immediately submitting
62
* an HTML form using AJAX.
63
*/
64
$.fn.ajaxSubmit = function(options) {
65
+ /*jshint scripturl:true */
66
+
67
+ // fast fail if nothing selected (http://dev.jquery.com/ticket/2752)
68
+ if (!this.length) {
69
+ log('ajaxSubmit: skipping submit process - no element selected');
70
+ return this;
71
+ }
72
+
73
+ var method, action, url, $form = this;
74
+
75
+ if (typeof options == 'function') {
76
+ options = { success: options };
77
+ }
78
+
79
+ method = this.attr('method');
80
+ action = this.attr('action');
81
+ url = (typeof action === 'string') ? $.trim(action) : '';
82
+ url = url || window.location.href || '';
83
+ if (url) {
84
+ // clean url (don't include hash vaue)
85
+ url = (url.match(/^([^#]+)/)||[])[1];
86
+ }
87
+
88
+ options = $.extend(true, {
89
+ url: url,
90
+ success: $.ajaxSettings.success,
91
+ type: method || 'GET',
92
+ iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank'
93
+ }, options);
94
+
95
+ // hook for manipulating the form data before it is extracted;
96
+ // convenient for use with rich editors like tinyMCE or FCKEditor
97
+ var veto = {};
98
+ this.trigger('form-pre-serialize', [this, options, veto]);
99
+ if (veto.veto) {
100
+ log('ajaxSubmit: submit vetoed via form-pre-serialize trigger');
101
+ return this;
102
+ }
103
+
104
+ // provide opportunity to alter form data before it is serialized
105
+ if (options.beforeSerialize && options.beforeSerialize(this, options) === false) {
106
+ log('ajaxSubmit: submit aborted via beforeSerialize callback');
107
+ return this;
108
+ }
109
+
110
+ var traditional = options.traditional;
111
+ if ( traditional === undefined ) {
112
+ traditional = $.ajaxSettings.traditional;
113
+ }
114
+
115
+ var elements = [];
116
+ var qx, a = this.formToArray(options.semantic, elements);
117
+ if (options.data) {
118
+ options.extraData = options.data;
119
+ qx = $.param(options.data, traditional);
120
+ }
121
+
122
+ // give pre-submit callback an opportunity to abort the submit
123
+ if (options.beforeSubmit && options.beforeSubmit(a, this, options) === false) {
124
+ log('ajaxSubmit: submit aborted via beforeSubmit callback');
125
+ return this;
126
+ }
127
+
128
+ // fire vetoable 'validate' event
129
+ this.trigger('form-submit-validate', [a, this, options, veto]);
130
+ if (veto.veto) {
131
+ log('ajaxSubmit: submit vetoed via form-submit-validate trigger');
132
+ return this;
133
+ }
134
+
135
+ var q = $.param(a, traditional);
136
+ if (qx) {
137
+ q = ( q ? (q + '&' + qx) : qx );
138
+ }
139
+ if (options.type.toUpperCase() == 'GET') {
140
+ options.url += (options.url.indexOf('?') >= 0 ? '&' : '?') + q;
141
+ options.data = null; // data is null for 'get'
142
+ }
143
+ else {
144
+ options.data = q; // data is the query string for 'post'
145
+ }
146
+
147
+ var callbacks = [];
148
+ if (options.resetForm) {
149
+ callbacks.push(function() { $form.resetForm(); });
150
+ }
151
+ if (options.clearForm) {
152
+ callbacks.push(function() { $form.clearForm(options.includeHidden); });
153
+ }
154
+
155
+ // perform a load on the target only if dataType is not provided
156
+ if (!options.dataType && options.target) {
157
+ var oldSuccess = options.success || function(){};
158
+ callbacks.push(function(data) {
159
+ var fn = options.replaceTarget ? 'replaceWith' : 'html';
160
+ $(options.target)[fn](data).each(oldSuccess, arguments);
161
+ });
162
+ }
163
+ else if (options.success) {
164
+ callbacks.push(options.success);
165
+ }
166
+
167
+ options.success = function(data, status, xhr) { // jQuery 1.4+ passes xhr as 3rd arg
168
+ var context = options.context || options; // jQuery 1.4+ supports scope context
169
+ for (var i=0, max=callbacks.length; i < max; i++) {
170
+ callbacks[i].apply(context, [data, status, xhr || $form, $form]);
171
+ }
172
+ };
173
+
174
+ // are there files to upload?
175
+ var fileInputs = $('input:file:enabled[value]', this); // [value] (issue #113)
176
+ var hasFileInputs = fileInputs.length > 0;
177
+ var mp = 'multipart/form-data';
178
+ var multipart = ($form.attr('enctype') == mp || $form.attr('encoding') == mp);
179
+
180
+ var fileAPI = feature.fileapi && feature.formdata;
181
+ log("fileAPI :" + fileAPI);
182
+ var shouldUseFrame = (hasFileInputs || multipart) && !fileAPI;
183
+
184
+ // options.iframe allows user to force iframe mode
185
+ // 06-NOV-09: now defaulting to iframe mode if file input is detected
186
+ if (options.iframe !== false && (options.iframe || shouldUseFrame)) {
187
+ // hack to fix Safari hang (thanks to Tim Molendijk for this)
188
+ // see: http://groups.google.com/group/jquery-dev/browse_thread/thread/36395b7ab510dd5d
189
+ if (options.closeKeepAlive) {
190
+ $.get(options.closeKeepAlive, function() {
191
+ fileUploadIframe(a);
192
+ });
193
+ }
194
+ else {
195
+ fileUploadIframe(a);
196
}
197
+ }
198
+ else if ((hasFileInputs || multipart) && fileAPI) {
199
+ fileUploadXhr(a);
200
+ }
201
+ else {
202
+ $.ajax(options);
203
+ }
204
+
205
+ // clear element array
206
+ for (var k=0; k < elements.length; k++)
207
+ elements[k] = null;
208
+
209
+ // fire 'notify' event
210
+ this.trigger('form-submit-notify', [this, options]);
211
+ return this;
212
+
213
+ // XMLHttpRequest Level 2 file uploads (big hat tip to francois2metz)
214
+ function fileUploadXhr(a) {
215
+ var formdata = new FormData();
216
+
217
+ for (var i=0; i < a.length; i++) {
218
+ formdata.append(a[i].name, a[i].value);
219
+ }
220
+
221
+ if (options.extraData) {
222
+ for (var p in options.extraData)
223
+ if (options.extraData.hasOwnProperty(p))
224
+ formdata.append(p, options.extraData[p]);
225
+ }
226
+
227
+ options.data = null;
228
+
229
+ var s = $.extend(true, {}, $.ajaxSettings, options, {
230
+ contentType: false,
231
+ processData: false,
232
+ cache: false,
233
+ type: 'POST'
234
+ });
235
+
236
+ if (options.uploadProgress) {
237
+ // workaround because jqXHR does not expose upload property
238
+ s.xhr = function() {
239
+ var xhr = jQuery.ajaxSettings.xhr();
240
+ if (xhr.upload) {
241
+ xhr.upload.onprogress = function(event) {
242
+ var percent = 0;
243
+ var position = event.loaded || event.position; /*event.position is deprecated*/
244
+ var total = event.total;
245
+ if (event.lengthComputable) {
246
+ percent = Math.ceil(position / total * 100);
247
+ }
248
+ options.uploadProgress(event, position, total, percent);
249
+ };
250
+ }
251
+ return xhr;
252
+ };
253
+ }
254
+
255
+ s.data = null;
256
+ var beforeSend = s.beforeSend;
257
+ s.beforeSend = function(xhr, o) {
258
+ o.data = formdata;
259
+ if(beforeSend)
260
+ beforeSend.call(o, xhr, options);
261
+ };
262
+ $.ajax(s);
263
+ }
264
+
265
+ // private function for handling file uploads (hat tip to YAHOO!)
266
+ function fileUploadIframe(a) {
267
+ var form = $form[0], el, i, s, g, id, $io, io, xhr, sub, n, timedOut, timeoutHandle;
268
+ var useProp = !!$.fn.prop;
269
+
270
+ if ($(':input[name=submit],:input[id=submit]', form).length) {
271
+ // if there is an input with a name or id of 'submit' then we won't be
272
+ // able to invoke the submit fn on the form (at least not x-browser)
273
+ alert('Error: Form elements must not have name or id of "submit".');
274
+ return;
275
+ }
276
+
277
+ if (a) {
278
+ // ensure that every serialized input is still enabled
279
+ for (i=0; i < elements.length; i++) {
280
+ el = $(elements[i]);
281
+ if ( useProp )
282
+ el.prop('disabled', false);
283
+ else
284
+ el.removeAttr('disabled');
285
+ }
286
+ }
287
+
288
+ s = $.extend(true, {}, $.ajaxSettings, options);
289
+ s.context = s.context || s;
290
+ id = 'jqFormIO' + (new Date().getTime());
291
+ if (s.iframeTarget) {
292
+ $io = $(s.iframeTarget);
293
+ n = $io.attr('name');
294
+ if (!n)
295
+ $io.attr('name', id);
296
+ else
297
+ id = n;
298
+ }
299
+ else {
300
+ $io = $('<iframe name="' + id + '" src="'+ s.iframeSrc +'" />');
301
+ $io.css({ position: 'absolute', top: '-1000px', left: '-1000px' });
302
+ }
303
+ io = $io[0];
304
+
305
+
306
+ xhr = { // mock object
307
+ aborted: 0,
308
+ responseText: null,
309
+ responseXML: null,
310
+ status: 0,
311
+ statusText: 'n/a',
312
+ getAllResponseHeaders: function() {},
313
+ getResponseHeader: function() {},
314
+ setRequestHeader: function() {},
315
+ abort: function(status) {
316
+ var e = (status === 'timeout' ? 'timeout' : 'aborted');
317
+ log('aborting upload... ' + e);
318
+ this.aborted = 1;
319
+ $io.attr('src', s.iframeSrc); // abort op in progress
320
+ xhr.error = e;
321
+ if (s.error)
322
+ s.error.call(s.context, xhr, e, status);
323
+ if (g)
324
+ $.event.trigger("ajaxError", [xhr, s, e]);
325
+ if (s.complete)
326
+ s.complete.call(s.context, xhr, e);
327
+ }
328
+ };
329
+
330
+ g = s.global;
331
+ // trigger ajax global events so that activity/block indicators work like normal
332
+ if (g && 0 === $.active++) {
333
+ $.event.trigger("ajaxStart");
334
+ }
335
+ if (g) {
336
+ $.event.trigger("ajaxSend", [xhr, s]);
337
+ }
338
+
339
+ if (s.beforeSend && s.beforeSend.call(s.context, xhr, s) === false) {
340
+ if (s.global) {
341
+ $.active--;
342
+ }
343
+ return;
344
+ }
345
+ if (xhr.aborted) {
346
+ return;
347
+ }
348
+
349
+ // add submitting element to data if we know it
350
+ sub = form.clk;
351
+ if (sub) {
352
+ n = sub.name;
353
+ if (n && !sub.disabled) {
354
+ s.extraData = s.extraData || {};
355
+ s.extraData[n] = sub.value;
356
+ if (sub.type == "image") {
357
+ s.extraData[n+'.x'] = form.clk_x;
358
+ s.extraData[n+'.y'] = form.clk_y;
359
+ }
360
+ }
361
+ }
362
+
363
+ var CLIENT_TIMEOUT_ABORT = 1;
364
+ var SERVER_ABORT = 2;
365
+
366
+ function getDoc(frame) {
367
+ var doc = frame.contentWindow ? frame.contentWindow.document : frame.contentDocument ? frame.contentDocument : frame.document;
368
+ return doc;
369
+ }
370
+
371
+ // Rails CSRF hack (thanks to Yvan Barthelemy)
372
+ var csrf_token = $('meta[name=csrf-token]').attr('content');
373
+ var csrf_param = $('meta[name=csrf-param]').attr('content');
374
+ if (csrf_param && csrf_token) {
375
+ s.extraData = s.extraData || {};
376
+ s.extraData[csrf_param] = csrf_token;
377
+ }
378
+
379
+ // take a breath so that pending repaints get some cpu time before the upload starts
380
+ function doSubmit() {
381
+ // make sure form attrs are set
382
+ var t = $form.attr('target'), a = $form.attr('action');
383
+
384
+ // update form attrs in IE friendly way
385
+ form.setAttribute('target',id);
386
+ if (!method) {
387
+ form.setAttribute('method', 'POST');
388
+ }
389
+ if (a != s.url) {
390
+ form.setAttribute('action', s.url);
391
+ }
392
+
393
+ // ie borks in some cases when setting encoding
394
+ if (! s.skipEncodingOverride && (!method || /post/i.test(method))) {
395
+ $form.attr({
396
+ encoding: 'multipart/form-data',
397
+ enctype: 'multipart/form-data'
398
+ });
399
+ }
400
+
401
+ // support timout
402
+ if (s.timeout) {
403
+ timeoutHandle = setTimeout(function() { timedOut = true; cb(CLIENT_TIMEOUT_ABORT); }, s.timeout);
404
+ }
405
+
406
+ // look for server aborts
407
+ function checkState() {
408
+ try {
409
+ var state = getDoc(io).readyState;
410
+ log('state = ' + state);
411
+ if (state && state.toLowerCase() == 'uninitialized')
412
+ setTimeout(checkState,50);
413
+ }
414
+ catch(e) {
415
+ log('Server abort: ' , e, ' (', e.name, ')');
416
+ cb(SERVER_ABORT);
417
+ if (timeoutHandle)
418
+ clearTimeout(timeoutHandle);
419
+ timeoutHandle = undefined;
420
+ }
421
+ }
422
+
423
+ // add "extra" data to form if provided in options
424
+ var extraInputs = [];
425
+ try {
426
+ if (s.extraData) {
427
+ for (var n in s.extraData) {
428
+ if (s.extraData.hasOwnProperty(n)) {
429
+ extraInputs.push(
430
+ $('<input type="hidden" name="'+n+'">').attr('value',s.extraData[n])
431
+ .appendTo(form)[0]);
432
+ }
433
+ }
434
+ }
435
+
436
+ if (!s.iframeTarget) {
437
+ // add iframe to doc and submit the form
438
+ $io.appendTo('body');
439
+ if (io.attachEvent)
440
+ io.attachEvent('onload', cb);
441
+ else
442
+ io.addEventListener('load', cb, false);
443
+ }
444
+ setTimeout(checkState,15);
445
+ form.submit();
446
+ }
447
+ finally {
448
+ // reset attrs and remove "extra" input elements
449
+ form.setAttribute('action',a);
450
+ if(t) {
451
+ form.setAttribute('target', t);
452
+ } else {
453
+ $form.removeAttr('target');
454
+ }
455
+ $(extraInputs).remove();
456
+ }
457
+ }
458
+
459
+ if (s.forceSync) {
460
+ doSubmit();
461
+ }
462
+ else {
463
+ setTimeout(doSubmit, 10); // this lets dom updates render
464
+ }
465
+
466
+ var data, doc, domCheckCount = 50, callbackProcessed;
467
+
468
+ function cb(e) {
469
+ if (xhr.aborted || callbackProcessed) {
470
+ return;
471
+ }
472
+ try {
473
+ doc = getDoc(io);
474
+ }
475
+ catch(ex) {
476
+ log('cannot access response document: ', ex);
477
+ e = SERVER_ABORT;
478
+ }
479
+ if (e === CLIENT_TIMEOUT_ABORT && xhr) {
480
+ xhr.abort('timeout');
481
+ return;
482
+ }
483
+ else if (e == SERVER_ABORT && xhr) {
484
+ xhr.abort('server abort');
485
+ return;
486
+ }
487
+
488
+ if (!doc || doc.location.href == s.iframeSrc) {
489
+ // response not received yet
490
+ if (!timedOut)
491
+ return;
492
+ }
493
+ if (io.detachEvent)
494
+ io.detachEvent('onload', cb);
495
+ else
496
+ io.removeEventListener('load', cb, false);
497
+
498
+ var status = 'success', errMsg;
499
+ try {
500
+ if (timedOut) {
501
+ throw 'timeout';
502
+ }
503
+
504
+ var isXml = s.dataType == 'xml' || doc.XMLDocument || $.isXMLDoc(doc);
505
+ log('isXml='+isXml);
506
+ if (!isXml && window.opera && (doc.body === null || !doc.body.innerHTML)) {
507
+ if (--domCheckCount) {
508
+ // in some browsers (Opera) the iframe DOM is not always traversable when
509
+ // the onload callback fires, so we loop a bit to accommodate
510
+ log('requeing onLoad callback, DOM not available');
511
+ setTimeout(cb, 250);
512
+ return;
513
+ }
514
+ // let this fall through because server response could be an empty document
515
+ //log('Could not access iframe DOM after mutiple tries.');
516
+ //throw 'DOMException: not available';
517
+ }
518
+
519
+ //log('response detected');
520
+ var docRoot = doc.body ? doc.body : doc.documentElement;
521
+ xhr.responseText = docRoot ? docRoot.innerHTML : null;
522
+ xhr.responseXML = doc.XMLDocument ? doc.XMLDocument : doc;
523
+ if (isXml)
524
+ s.dataType = 'xml';
525
+ xhr.getResponseHeader = function(header){
526
+ var headers = {'content-type': s.dataType};
527
+ return headers[header];
528
+ };
529
+ // support for XHR 'status' & 'statusText' emulation :
530
+ if (docRoot) {
531
+ xhr.status = Number( docRoot.getAttribute('status') ) || xhr.status;
532
+ xhr.statusText = docRoot.getAttribute('statusText') || xhr.statusText;
533
+ }
534
+
535
+ var dt = (s.dataType || '').toLowerCase();
536
+ var scr = /(json|script|text)/.test(dt);
537
+ if (scr || s.textarea) {
538
+ // see if user embedded response in textarea
539
+ var ta = doc.getElementsByTagName('textarea')[0];
540
+ if (ta) {
541
+ xhr.responseText = ta.value;
542
+ // support for XHR 'status' & 'statusText' emulation :
543
+ xhr.status = Number( ta.getAttribute('status') ) || xhr.status;
544
+ xhr.statusText = ta.getAttribute('statusText') || xhr.statusText;
545
+ }
546
+ else if (scr) {
547
+ // account for browsers injecting pre around json response
548
+ var pre = doc.getElementsByTagName('pre')[0];
549
+ var b = doc.getElementsByTagName('body')[0];
550
+ if (pre) {
551
+ xhr.responseText = pre.textContent ? pre.textContent : pre.innerText;
552
+ }
553
+ else if (b) {
554
+ xhr.responseText = b.textContent ? b.textContent : b.innerText;
555
+ }
556
+ }
557
+ }
558
+ else if (dt == 'xml' && !xhr.responseXML && xhr.responseText) {
559
+ xhr.responseXML = toXml(xhr.responseText);
560
+ }
561
+
562
+ try {
563
+ data = httpData(xhr, dt, s);
564
+ }
565
+ catch (e) {
566
+ status = 'parsererror';
567
+ xhr.error = errMsg = (e || status);
568
+ }
569
+ }
570
+ catch (e) {
571
+ log('error caught: ',e);
572
+ status = 'error';
573
+ xhr.error = errMsg = (e || status);
574
+ }
575
+
576
+ if (xhr.aborted) {
577
+ log('upload aborted');
578
+ status = null;
579
+ }
580
+
581
+ if (xhr.status) { // we've set xhr.status
582
+ status = (xhr.status >= 200 && xhr.status < 300 || xhr.status === 304) ? 'success' : 'error';
583
+ }
584
+
585
+ // ordering of these callbacks/triggers is odd, but that's how $.ajax does it
586
+ if (status === 'success') {
587
+ if (s.success)
588
+ s.success.call(s.context, data, 'success', xhr);
589
+ if (g)
590
+ $.event.trigger("ajaxSuccess", [xhr, s]);
591
+ }
592
+ else if (status) {
593
+ if (errMsg === undefined)
594
+ errMsg = xhr.statusText;
595
+ if (s.error)
596
+ s.error.call(s.context, xhr, status, errMsg);
597
+ if (g)
598
+ $.event.trigger("ajaxError", [xhr, s, errMsg]);
599
+ }
600
+
601
+ if (g)
602
+ $.event.trigger("ajaxComplete", [xhr, s]);
603
+
604
+ if (g && ! --$.active) {
605
+ $.event.trigger("ajaxStop");
606
+ }
607
+
608
+ if (s.complete)
609
+ s.complete.call(s.context, xhr, status);
610
+
611
+ callbackProcessed = true;
612
+ if (s.timeout)
613
+ clearTimeout(timeoutHandle);
614
+
615
+ // clean up
616
+ setTimeout(function() {
617
+ if (!s.iframeTarget)
618
+ $io.remove();
619
+ xhr.responseXML = null;
620
+ }, 100);
621
+ }
622
+
623
+ var toXml = $.parseXML || function(s, doc) { // use parseXML if available (jQuery 1.5+)
624
+ if (window.ActiveXObject) {
625
+ doc = new ActiveXObject('Microsoft.XMLDOM');
626
+ doc.async = 'false';
627
+ doc.loadXML(s);
628
+ }
629
+ else {
630
+ doc = (new DOMParser()).parseFromString(s, 'text/xml');
631
+ }
632
+ return (doc && doc.documentElement && doc.documentElement.nodeName != 'parsererror') ? doc : null;
633
+ };
634
+ var parseJSON = $.parseJSON || function(s) {
635
+ /*jslint evil:true */
636
+ return window['eval']('(' + s + ')');
637
+ };
638
+
639
+ var httpData = function( xhr, type, s ) { // mostly lifted from jq1.4.4
640
+
641
+ var ct = xhr.getResponseHeader('content-type') || '',
642
+ xml = type === 'xml' || !type && ct.indexOf('xml') >= 0,
643
+ data = xml ? xhr.responseXML : xhr.responseText;
644
+
645
+ if (xml && data.documentElement.nodeName === 'parsererror') {
646
+ if ($.error)
647
+ $.error('parsererror');
648
+ }
649
+ if (s && s.dataFilter) {
650
+ data = s.dataFilter(data, type);
651
+ }
652
+ if (typeof data === 'string') {
653
+ if (type === 'json' || !type && ct.indexOf('json') >= 0) {
654
+ data = parseJSON(data);
655
+ } else if (type === "script" || !type && ct.indexOf("javascript") >= 0) {
656
+ $.globalEval(data);
657
+ }
658
+ }
659
+ return data;
660
+ };
661
+ }
662
};
663
664
/**
667
* The advantages of using this method instead of ajaxSubmit() are:
668
*
669
* 1: This method will include coordinates for <input type="image" /> elements (if the element
670
+ * is used to submit the form).
671
* 2. This method will include the submit element's name/value data (for the element that was
672
+ * used to submit the form).
673
* 3. This method binds the submit() method to the form for you.
674
*
675
* The options argument for ajaxForm works exactly as it does for ajaxSubmit. ajaxForm merely
677
* the form itself.
678
*/
679
$.fn.ajaxForm = function(options) {
680
+ options = options || {};
681
+ options.delegation = options.delegation && $.isFunction($.fn.on);
682
+
683
+ // in jQuery 1.3+ we can fix mistakes with the ready state
684
+ if (!options.delegation && this.length === 0) {
685
+ var o = { s: this.selector, c: this.context };
686
+ if (!$.isReady && o.s) {
687
+ log('DOM not ready, queuing ajaxForm');
688
+ $(function() {
689
+ $(o.s,o.c).ajaxForm(options);
690
+ });
691
+ return this;
692
+ }
693
+ // is your DOM ready? http://docs.jquery.com/Tutorials:Introducing_$(document).ready()
694
+ log('terminating; zero elements found by selector' + ($.isReady ? '' : ' (DOM not ready)'));
695
+ return this;
696
+ }
697
+
698
+ if ( options.delegation ) {
699
+ $(document)
700
+ .off('submit.form-plugin', this.selector, doAjaxSubmit)
701
+ .off('click.form-plugin', this.selector, captureSubmittingElement)
702
+ .on('submit.form-plugin', this.selector, options, doAjaxSubmit)
703
+ .on('click.form-plugin', this.selector, options, captureSubmittingElement);
704
+ return this;
705
+ }
706
+
707
+ return this.ajaxFormUnbind()
708
+ .bind('submit.form-plugin', options, doAjaxSubmit)
709
+ .bind('click.form-plugin', options, captureSubmittingElement);
710
};
711
712
+ // private event handlers
713
function doAjaxSubmit(e) {
714
+ /*jshint validthis:true */
715
+ var options = e.data;
716
+ if (!e.isDefaultPrevented()) { // if event has been canceled, don't proceed
717
+ e.preventDefault();
718
+ $(this).ajaxSubmit(options);
719
+ }
720
}
721
+
722
function captureSubmittingElement(e) {
723
+ /*jshint validthis:true */
724
+ var target = e.target;
725
+ var $el = $(target);
726
+ if (!($el.is(":submit,input:image"))) {
727
+ // is this a child element of the submit el? (ex: a span within a button)
728
+ var t = $el.closest(':submit');
729
+ if (t.length === 0) {
730
+ return;
731
+ }
732
+ target = t[0];
733
+ }
734
+ var form = this;
735
+ form.clk = target;
736
+ if (target.type == 'image') {
737
+ if (e.offsetX !== undefined) {
738
+ form.clk_x = e.offsetX;
739
+ form.clk_y = e.offsetY;
740
+ } else if (typeof $.fn.offset == 'function') {
741
+ var offset = $el.offset();
742
+ form.clk_x = e.pageX - offset.left;
743
+ form.clk_y = e.pageY - offset.top;
744
+ } else {
745
+ form.clk_x = e.pageX - target.offsetLeft;
746
+ form.clk_y = e.pageY - target.offsetTop;
747
+ }
748
+ }
749
+ // clear form vars
750
+ setTimeout(function() { form.clk = form.clk_x = form.clk_y = null; }, 100);
751
+ }
752
753
754
// ajaxFormUnbind unbinds the event handlers that were bound by ajaxForm
755
$.fn.ajaxFormUnbind = function() {
756
+ return this.unbind('submit.form-plugin click.form-plugin');
757
};
758
759
/**
767
* It is this array that is passed to pre-submit callback functions provided to the
768
* ajaxSubmit() and ajaxForm() methods.
769
*/
770
+ $.fn.formToArray = function(semantic, elements) {
771
+ var a = [];
772
+ if (this.length === 0) {
773
+ return a;
774
+ }
775
+
776
+ var form = this[0];
777
+ var els = semantic ? form.getElementsByTagName('*') : form.elements;
778
+ if (!els) {
779
+ return a;
780
+ }
781
+
782
+ var i,j,n,v,el,max,jmax;
783
+ for(i=0, max=els.length; i < max; i++) {
784
+ el = els[i];
785
+ n = el.name;
786
+ if (!n) {
787
+ continue;
788
+ }
789
+
790
+ if (semantic && form.clk && el.type == "image") {
791
+ // handle image inputs on the fly when semantic == true
792
+ if(!el.disabled && form.clk == el) {
793
+ a.push({name: n, value: $(el).val(), type: el.type });
794
+ a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
795
+ }
796
+ continue;
797
+ }
798
+
799
+ v = $.fieldValue(el, true);
800
+ if (v && v.constructor == Array) {
801
+ if (elements)
802
+ elements.push(el);
803
+ for(j=0, jmax=v.length; j < jmax; j++) {
804
+ a.push({name: n, value: v[j]});
805
+ }
806
+ }
807
+ else if (feature.fileapi && el.type == 'file' && !el.disabled) {
808
+ if (elements)
809
+ elements.push(el);
810
+ var files = el.files;
811
+ for (j=0; j < files.length; j++) {
812
+ a.push({name: n, value: files[j], type: el.type});
813
+ }
814
+ }
815
+ else if (v !== null && typeof v != 'undefined') {
816
+ if (elements)
817
+ elements.push(el);
818
+ a.push({name: n, value: v, type: el.type, required: el.required});
819
+ }
820
+ }
821
+
822
+ if (!semantic && form.clk) {
823
+ // input type=='image' are not found in elements array! handle it here
824
+ var $input = $(form.clk), input = $input[0];
825
+ n = input.name;
826
+ if (n && !input.disabled && input.type == 'image') {
827
+ a.push({name: n, value: $input.val()});
828
+ a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
829
+ }
830
+ }
831
+ return a;
832
};
833
834
/**
836
* in the format: name1=value1&amp;name2=value2
837
*/
838
$.fn.formSerialize = function(semantic) {
839
+ //hand off to jQuery.param for proper encoding
840
+ return $.param(this.formToArray(semantic));
841
};
842
843
/**
845
* This method will return a string in the format: name1=value1&amp;name2=value2
846
*/
847
$.fn.fieldSerialize = function(successful) {
848
+ var a = [];
849
+ this.each(function() {
850
+ var n = this.name;
851
+ if (!n) {
852
+ return;
853
+ }
854
+ var v = $.fieldValue(this, successful);
855
+ if (v && v.constructor == Array) {
856
+ for (var i=0,max=v.length; i < max; i++) {
857
+ a.push({name: n, value: v[i]});
858
+ }
859
+ }
860
+ else if (v !== null && typeof v != 'undefined') {
861
+ a.push({name: this.name, value: v});
862
+ }
863
+ });
864
+ //hand off to jQuery.param for proper encoding
865
+ return $.param(a);
866
};
867
868
/**
869
* Returns the value(s) of the element in the matched set. For example, consider the following form:
870
*
871
* <form><fieldset>
872
+ * <input name="A" type="text" />
873
+ * <input name="A" type="text" />
874
+ * <input name="B" type="checkbox" value="B1" />
875
+ * <input name="B" type="checkbox" value="B2"/>
876
+ * <input name="C" type="radio" value="C1" />
877
+ * <input name="C" type="radio" value="C2" />
878
* </fieldset></form>
879
*
880
* var v = $(':text').fieldValue();
901
* for each element is returned.
902
*
903
* Note: This method *always* returns an array. If no valid value can be determined the
904
+ * array will be empty, otherwise it will contain one or more values.
905
*/
906
$.fn.fieldValue = function(successful) {
907
+ for (var val=[], i=0, max=this.length; i < max; i++) {
908
+ var el = this[i];
909
+ var v = $.fieldValue(el, successful);
910
+ if (v === null || typeof v == 'undefined' || (v.constructor == Array && !v.length)) {
911
+ continue;
912
+ }
913
+ if (v.constructor == Array)
914
+ $.merge(val, v);
915
+ else
916
+ val.push(v);
917
+ }
918
+ return val;
919
};
920
921
/**
922
* Returns the value of the field element.
923
*/
924
$.fieldValue = function(el, successful) {
925
+ var n = el.name, t = el.type, tag = el.tagName.toLowerCase();
926
+ if (successful === undefined) {
927
+ successful = true;
928
+ }
929
+
930
+ if (successful && (!n || el.disabled || t == 'reset' || t == 'button' ||
931
+ (t == 'checkbox' || t == 'radio') && !el.checked ||
932
+ (t == 'submit' || t == 'image') && el.form && el.form.clk != el ||
933
+ tag == 'select' && el.selectedIndex == -1)) {
934
+ return null;
935
+ }
936
+
937
+ if (tag == 'select') {
938
+ var index = el.selectedIndex;
939
+ if (index < 0) {
940
+ return null;
941
+ }
942
+ var a = [], ops = el.options;
943
+ var one = (t == 'select-one');
944
+ var max = (one ? index+1 : ops.length);
945
+ for(var i=(one ? index : 0); i < max; i++) {
946
+ var op = ops[i];
947
+ if (op.selected) {
948
+ var v = op.value;
949
+ if (!v) { // extra pain for IE...
950
+ v = (op.attributes && op.attributes['value'] && !(op.attributes['value'].specified)) ? op.text : op.value;
951
+ }
952
+ if (one) {
953
+ return v;
954
+ }
955
+ a.push(v);
956
+ }
957
+ }
958
+ return a;
959
+ }
960
+ return $(el).val();
961
};
962
963
/**
969
* - button elements will *not* be effected
970
*/
971
$.fn.clearForm = function(includeHidden) {
972
+ return this.each(function() {
973
+ $('input,select,textarea', this).clearFields(includeHidden);
974
+ });
975
};
976
977
/**
978
* Clears the selected form elements.
979
*/
980
$.fn.clearFields = $.fn.clearInputs = function(includeHidden) {
981
+ var re = /^(?:color|date|datetime|email|month|number|password|range|search|tel|text|time|url|week)#x2F;i; // 'hidden' is not in this list
982
+ return this.each(function() {
983
+ var t = this.type, tag = this.tagName.toLowerCase();
984
+ if (re.test(t) || tag == 'textarea') {
985
+ this.value = '';
986
+ }
987
+ else if (t == 'checkbox' || t == 'radio') {
988
+ this.checked = false;
989
+ }
990
+ else if (tag == 'select') {
991
+ this.selectedIndex = -1;
992
+ }
993
+ else if (includeHidden) {
994
+ // includeHidden can be the valud true, or it can be a selector string
995
+ // indicating a special test; for example:
996
+ // $('#myForm').clearForm('.special:hidden')
997
+ // the above would clean hidden inputs that have the class of 'special'
998
+ if ( (includeHidden === true && /hidden/.test(t)) ||
999
+ (typeof includeHidden == 'string' && $(this).is(includeHidden)) )
1000
+ this.value = '';
1001
+ }
1002
+ });
1003
};
1004
1005
/**
1006
* Resets the form data. Causes all form elements to be reset to their original value.
1007
*/
1008
$.fn.resetForm = function() {
1009
+ return this.each(function() {
1010
+ // guard against an input with the name of 'reset'
1011
+ // note that IE reports the reset function as an 'object'
1012
+ if (typeof this.reset == 'function' || (typeof this.reset == 'object' && !this.reset.nodeType)) {
1013
+ this.reset();
1014
+ }
1015
+ });
1016
};
1017
1018
/**
1019
* Enables or disables any matching elements.
1020
*/
1021
$.fn.enable = function(b) {
1022
+ if (b === undefined) {
1023
+ b = true;
1024
+ }
1025
+ return this.each(function() {
1026
+ this.disabled = !b;
1027
+ });
1028
};
1029
1030
/**
1032
* selects/deselects and matching option elements.
1033
*/
1034
$.fn.selected = function(select) {
1035
+ if (select === undefined) {
1036
+ select = true;
1037
+ }
1038
+ return this.each(function() {
1039
+ var t = this.type;
1040
+ if (t == 'checkbox' || t == 'radio') {
1041
+ this.checked = select;
1042
+ }
1043
+ else if (this.tagName.toLowerCase() == 'option') {
1044
+ var $sel = $(this).parent('select');
1045
+ if (select && $sel[0] && $sel[0].type == 'select-one') {
1046
+ // deselect all other options
1047
+ $sel.find('option').selected(false);
1048
+ }
1049
+ this.selected = select;
1050
+ }
1051
+ });
1052
};
1053
1054
// expose debug var
1056
1057
// helper fn for console logging
1058
function log() {
1059
+ if (!$.fn.ajaxSubmit.debug)
1060
+ return;
1061
+ var msg = '[jquery.form] ' + Array.prototype.join.call(arguments,'');
1062
+ if (window.console && window.console.log) {
1063
+ window.console.log(msg);
1064
+ }
1065
+ else if (window.opera && window.opera.postError) {
1066
+ window.opera.postError(msg);
1067
+ }
1068
+ }
1069
1070
})(jQuery);
languages/wpcf7-de_DE.mo CHANGED
Binary file
languages/wpcf7-hu_HU.mo CHANGED
Binary file
languages/wpcf7-lt_LT.mo CHANGED
Binary file
languages/wpcf7-sl_SI.mo CHANGED
Binary file
languages/wpcf7.pot CHANGED
@@ -2,8 +2,8 @@ msgid ""
2
msgstr ""
3
"Project-Id-Version: Contact Form 7\n"
4
"Report-Msgid-Bugs-To: \n"
5
- "POT-Creation-Date: 2012-02-22 15:57+0900\n"
6
- "PO-Revision-Date: 2012-02-22 15:58+0900\n"
7
"Last-Translator: Takayuki Miyoshi <takayukister@gmail.com>\n"
8
"Language-Team: \n"
9
"MIME-Version: 1.0\n"
@@ -220,7 +220,7 @@ msgstr ""
220
msgid "Message body:"
221
msgstr ""
222
223
- #: contact-form-7/includes/classes.php:665
224
msgid "Untitled"
225
msgstr ""
226
@@ -241,7 +241,7 @@ msgid "Sender's message was failed to send"
241
msgstr ""
242
243
#: contact-form-7/includes/functions.php:32
244
- #: contact-form-7/modules/akismet.php:106
245
msgid "Failed to send your message. Please try later or contact the administrator by another method."
246
msgstr ""
247
@@ -590,7 +590,7 @@ msgstr ""
590
msgid "Copy this code and paste it into the form left."
591
msgstr ""
592
593
- #: contact-form-7/modules/akismet.php:105
594
msgid "Akismet judged the sending activity as spamming"
595
msgstr ""
596
@@ -672,7 +672,7 @@ msgid "Radio buttons"
672
msgstr ""
673
674
#: contact-form-7/modules/checkbox.php:185
675
- #: contact-form-7/modules/file.php:236
676
#: contact-form-7/modules/select.php:148
677
#: contact-form-7/modules/text.php:175
678
#: contact-form-7/modules/textarea.php:136
@@ -708,59 +708,59 @@ msgstr ""
708
msgid "And, put this code into the Mail fields below."
709
msgstr ""
710
711
- #: contact-form-7/modules/file.php:200
712
msgid "Uploading a file fails for any reason"
713
msgstr ""
714
715
- #: contact-form-7/modules/file.php:201
716
msgid "Failed to upload file."
717
msgstr ""
718
719
- #: contact-form-7/modules/file.php:205
720
msgid "Uploaded file is not allowed file type"
721
msgstr ""
722
723
- #: contact-form-7/modules/file.php:206
724
msgid "This file type is not allowed."
725
msgstr ""
726
727
- #: contact-form-7/modules/file.php:210
728
msgid "Uploaded file is too large"
729
msgstr ""
730
731
- #: contact-form-7/modules/file.php:211
732
msgid "This file is too large."
733
msgstr ""
734
735
- #: contact-form-7/modules/file.php:215
736
msgid "Uploading a file fails for PHP error"
737
msgstr ""
738
739
- #: contact-form-7/modules/file.php:216
740
msgid "Failed to upload file. Error occurred."
741
msgstr ""
742
743
- #: contact-form-7/modules/file.php:227
744
msgid "File upload"
745
msgstr ""
746
747
- #: contact-form-7/modules/file.php:250
748
msgid "File size limit"
749
msgstr ""
750
751
- #: contact-form-7/modules/file.php:250
752
msgid "bytes"
753
msgstr ""
754
755
- #: contact-form-7/modules/file.php:253
756
msgid "Acceptable file types"
757
msgstr ""
758
759
- #: contact-form-7/modules/file.php:260
760
msgid "And, put this code into the File Attachments field below."
761
msgstr ""
762
763
- #: contact-form-7/modules/file.php:285
764
#, php-format
765
msgid "This contact form contains file uploading fields, but the temporary folder for the files (%s) does not exist or is not writable. You can create the folder or change its permission manually."
766
msgstr ""
2
msgstr ""
3
"Project-Id-Version: Contact Form 7\n"
4
"Report-Msgid-Bugs-To: \n"
5
+ "POT-Creation-Date: 2012-04-12 22:04+0900\n"
6
+ "PO-Revision-Date: 2012-04-12 22:04+0900\n"
7
"Last-Translator: Takayuki Miyoshi <takayukister@gmail.com>\n"
8
"Language-Team: \n"
9
"MIME-Version: 1.0\n"
220
msgid "Message body:"
221
msgstr ""
222
223
+ #: contact-form-7/includes/classes.php:664
224
msgid "Untitled"
225
msgstr ""
226
241
msgstr ""
242
243
#: contact-form-7/includes/functions.php:32
244
+ #: contact-form-7/modules/akismet.php:109
245
msgid "Failed to send your message. Please try later or contact the administrator by another method."
246
msgstr ""
247
590
msgid "Copy this code and paste it into the form left."
591
msgstr ""
592
593
+ #: contact-form-7/modules/akismet.php:108
594
msgid "Akismet judged the sending activity as spamming"
595
msgstr ""
596
672
msgstr ""
673
674
#: contact-form-7/modules/checkbox.php:185
675
+ #: contact-form-7/modules/file.php:237
676
#: contact-form-7/modules/select.php:148
677
#: contact-form-7/modules/text.php:175
678
#: contact-form-7/modules/textarea.php:136
708
msgid "And, put this code into the Mail fields below."
709
msgstr ""
710
711
+ #: contact-form-7/modules/file.php:201
712
msgid "Uploading a file fails for any reason"
713
msgstr ""
714
715
+ #: contact-form-7/modules/file.php:202
716
msgid "Failed to upload file."
717
msgstr ""
718
719
+ #: contact-form-7/modules/file.php:206
720
msgid "Uploaded file is not allowed file type"
721
msgstr ""
722
723
+ #: contact-form-7/modules/file.php:207
724
msgid "This file type is not allowed."
725
msgstr ""
726
727
+ #: contact-form-7/modules/file.php:211
728
msgid "Uploaded file is too large"
729
msgstr ""
730
731
+ #: contact-form-7/modules/file.php:212
732
msgid "This file is too large."
733
msgstr ""
734
735
+ #: contact-form-7/modules/file.php:216
736
msgid "Uploading a file fails for PHP error"
737
msgstr ""
738
739
+ #: contact-form-7/modules/file.php:217
740
msgid "Failed to upload file. Error occurred."
741
msgstr ""
742
743
+ #: contact-form-7/modules/file.php:228
744
msgid "File upload"
745
msgstr ""
746
747
+ #: contact-form-7/modules/file.php:251
748
msgid "File size limit"
749
msgstr ""
750
751
+ #: contact-form-7/modules/file.php:251
752
msgid "bytes"
753
msgstr ""
754
755
+ #: contact-form-7/modules/file.php:254
756
msgid "Acceptable file types"
757
msgstr ""
758
759
+ #: contact-form-7/modules/file.php:261
760
msgid "And, put this code into the File Attachments field below."
761
msgstr ""
762
763
+ #: contact-form-7/modules/file.php:286
764
#, php-format
765
msgid "This contact form contains file uploading fields, but the temporary folder for the files (%s) does not exist or is not writable. You can create the folder or change its permission manually."
766
msgstr ""
modules/akismet.php CHANGED
@@ -20,7 +20,10 @@ function wpcf7_akismet( $spam ) {
20
$fes = wpcf7_scan_shortcode();
21
22
foreach ( $fes as $fe ) {
23
- if ( ! isset( $fe['name'] ) || ! is_array( $fe['options'] ) )
24
continue;
25
26
if ( preg_grep( '%^akismet:author$%', $fe['options'] ) ) {
20
$fes = wpcf7_scan_shortcode();
21
22
foreach ( $fes as $fe ) {
23
+ if ( ! isset( $fe['name'] ) || ! isset( $_POST[$fe['name']] ) )
24
+ continue;
25
+
26
+ if ( ! is_array( $fe['options'] ) )
27
continue;
28
29
if ( preg_grep( '%^akismet:author$%', $fe['options'] ) ) {
modules/captcha.php CHANGED
@@ -314,10 +314,31 @@ function wpcf7_init_captcha() {
314
315
if ( ! is_object( $wpcf7_captcha ) )
316
$wpcf7_captcha = new ReallySimpleCaptcha();
317
- $captcha =& $wpcf7_captcha;
318
319
- $captcha->tmp_dir = trailingslashit( wpcf7_captcha_tmp_dir() );
320
- wp_mkdir_p( $captcha->tmp_dir );
321
return true;
322
}
323
@@ -340,39 +361,38 @@ function wpcf7_generate_captcha( $options = null ) {
340
341
if ( ! wpcf7_init_captcha() )
342
return false;
343
- $captcha =& $wpcf7_captcha;
344
345
- if ( ! is_dir( $captcha->tmp_dir ) || ! is_writable( $captcha->tmp_dir ) )
346
return false;
347
348
$img_type = imagetypes();
349
if ( $img_type & IMG_PNG )
350
- $captcha->img_type = 'png';
351
elseif ( $img_type & IMG_GIF )
352
- $captcha->img_type = 'gif';
353
elseif ( $img_type & IMG_JPG )
354
- $captcha->img_type = 'jpeg';
355
else
356
return false;
357
358
if ( is_array( $options ) ) {
359
if ( isset( $options['img_size'] ) )
360
- $captcha->img_size = $options['img_size'];
361
if ( isset( $options['base'] ) )
362
- $captcha->base = $options['base'];
363
if ( isset( $options['font_size'] ) )
364
- $captcha->font_size = $options['font_size'];
365
if ( isset( $options['font_char_width'] ) )
366
- $captcha->font_char_width = $options['font_char_width'];
367
if ( isset( $options['fg'] ) )
368
- $captcha->fg = $options['fg'];
369
if ( isset( $options['bg'] ) )
370
- $captcha->bg = $options['bg'];
371
}
372
373
$prefix = mt_rand();
374
- $captcha_word = $captcha->generate_random_word();
375
- return $captcha->generate_image( $prefix, $captcha_word );
376
}
377
378
function wpcf7_check_captcha( $prefix, $response ) {
@@ -380,9 +400,8 @@ function wpcf7_check_captcha( $prefix, $response ) {
380
381
if ( ! wpcf7_init_captcha() )
382
return false;
383
- $captcha =& $wpcf7_captcha;
384
385
- return $captcha->check( $prefix, $response );
386
}
387
388
function wpcf7_remove_captcha( $prefix ) {
@@ -390,12 +409,11 @@ function wpcf7_remove_captcha( $prefix ) {
390
391
if ( ! wpcf7_init_captcha() )
392
return false;
393
- $captcha =& $wpcf7_captcha;
394
395
if ( preg_match( '/[^0-9]/', $prefix ) ) // Contact Form 7 generates $prefix with mt_rand()
396
return false;
397
398
- $captcha->remove( $prefix );
399
}
400
401
function wpcf7_cleanup_captcha_files() {
@@ -403,10 +421,9 @@ function wpcf7_cleanup_captcha_files() {
403
404
if ( ! wpcf7_init_captcha() )
405
return false;
406
- $captcha =& $wpcf7_captcha;
407
408
- if ( is_callable( array( $captcha, 'cleanup' ) ) )
409
- return $captcha->cleanup();
410
411
$dir = trailingslashit( wpcf7_captcha_tmp_dir() );
412
@@ -415,7 +432,7 @@ function wpcf7_cleanup_captcha_files() {
415
416
if ( $handle = @opendir( $dir ) ) {
417
while ( false !== ( $file = readdir( $handle ) ) ) {
418
- if ( ! preg_match( '/^[0-9]+\.(php|png|gif|jpeg)#x2F;', $file ) )
419
continue;
420
421
$stat = @stat( $dir . $file );
314
315
if ( ! is_object( $wpcf7_captcha ) )
316
$wpcf7_captcha = new ReallySimpleCaptcha();
317
318
+ $dir = trailingslashit( wpcf7_captcha_tmp_dir() );
319
+
320
+ $wpcf7_captcha->tmp_dir = $dir;
321
+
322
+ if ( is_callable( array( $wpcf7_captcha, 'make_tmp_dir' ) ) )
323
+ return $wpcf7_captcha->make_tmp_dir();
324
+
325
+ if ( ! wp_mkdir_p( $dir ) )
326
+ return false;
327
+
328
+ $htaccess_file = $dir . '.htaccess';
329
+
330
+ if ( file_exists( $htaccess_file ) )
331
+ return true;
332
+
333
+ if ( $handle = @fopen( $htaccess_file, 'w' ) ) {
334
+ fwrite( $handle, 'Order deny,allow' . "\n" );
335
+ fwrite( $handle, 'Deny from all' . "\n" );
336
+ fwrite( $handle, '<Files ~ "^[0-9A-Za-z]+\\.(jpeg|gif|png)quot;>' . "\n" );
337
+ fwrite( $handle, ' Allow from all' . "\n" );
338
+ fwrite( $handle, '</Files>' . "\n" );
339
+ fclose( $handle );
340
+ }
341
+
342
return true;
343
}
344
361
362
if ( ! wpcf7_init_captcha() )
363
return false;
364
365
+ if ( ! is_dir( $wpcf7_captcha->tmp_dir ) || ! is_writable( $wpcf7_captcha->tmp_dir ) )
366
return false;
367
368
$img_type = imagetypes();
369
if ( $img_type & IMG_PNG )
370
+ $wpcf7_captcha->img_type = 'png';
371
elseif ( $img_type & IMG_GIF )
372
+ $wpcf7_captcha->img_type = 'gif';
373
elseif ( $img_type & IMG_JPG )
374
+ $wpcf7_captcha->img_type = 'jpeg';
375
else
376
return false;
377
378
if ( is_array( $options ) ) {
379
if ( isset( $options['img_size'] ) )
380
+ $wpcf7_captcha->img_size = $options['img_size'];
381
if ( isset( $options['base'] ) )
382
+ $wpcf7_captcha->base = $options['base'];
383
if ( isset( $options['font_size'] ) )
384
+ $wpcf7_captcha->font_size = $options['font_size'];
385
if ( isset( $options['font_char_width'] ) )
386
+ $wpcf7_captcha->font_char_width = $options['font_char_width'];
387
if ( isset( $options['fg'] ) )
388
+ $wpcf7_captcha->fg = $options['fg'];
389
if ( isset( $options['bg'] ) )
390
+ $wpcf7_captcha->bg = $options['bg'];
391
}
392
393
$prefix = mt_rand();
394
+ $captcha_word = $wpcf7_captcha->generate_random_word();
395
+ return $wpcf7_captcha->generate_image( $prefix, $captcha_word );
396
}
397
398
function wpcf7_check_captcha( $prefix, $response ) {
400
401
if ( ! wpcf7_init_captcha() )
402
return false;
403
404
+ return $wpcf7_captcha->check( $prefix, $response );
405
}
406
407
function wpcf7_remove_captcha( $prefix ) {
409
410
if ( ! wpcf7_init_captcha() )
411
return false;
412
413
if ( preg_match( '/[^0-9]/', $prefix ) ) // Contact Form 7 generates $prefix with mt_rand()
414
return false;
415
416
+ $wpcf7_captcha->remove( $prefix );
417
}
418
419
function wpcf7_cleanup_captcha_files() {
421
422
if ( ! wpcf7_init_captcha() )
423
return false;
424
425
+ if ( is_callable( array( $wpcf7_captcha, 'cleanup' ) ) )
426
+ return $wpcf7_captcha->cleanup();
427
428
$dir = trailingslashit( wpcf7_captcha_tmp_dir() );
429
432
433
if ( $handle = @opendir( $dir ) ) {
434
while ( false !== ( $file = readdir( $handle ) ) ) {
435
+ if ( ! preg_match( '/^[0-9]+\.(php|txt|png|gif|jpeg)#x2F;', $file ) )
436
continue;
437
438
$stat = @stat( $dir . $file );
modules/file.php CHANGED
@@ -180,11 +180,12 @@ function wpcf7_file_validation_filter( $result, $tag ) {
180
// Make sure the uploaded file is only readable for the owner process
181
@chmod( $new_file, 0400 );
182
183
- if ( $contact_form = wpcf7_get_current_contact_form() )
184
$contact_form->uploaded_files[$name] = $new_file;
185
186
- if ( ! isset( $_POST[$name] ) )
187
- $_POST[$name] = $filename;
188
189
return $result;
190
}
180
// Make sure the uploaded file is only readable for the owner process
181
@chmod( $new_file, 0400 );
182
183
+ if ( $contact_form = wpcf7_get_current_contact_form() ) {
184
$contact_form->uploaded_files[$name] = $new_file;
185
186
+ if ( empty( $contact_form->posted_data[$name] ) )
187
+ $contact_form->posted_data[$name] = $filename;
188
+ }
189
190
return $result;
191
}
readme.txt CHANGED
@@ -4,7 +4,7 @@ Donate link: http://contactform7.com/donate/
4
Tags: contact, form, contact form, feedback, email, ajax, captcha, akismet, multilingual
5
Requires at least: 3.2
6
Tested up to: 3.3.1
7
- Stable tag: 3.1.1
8
9
Just another contact form plugin. Simple but flexible.
10
@@ -57,7 +57,7 @@ It is hard to continue development and support for this plugin without contribut
57
* Japanese (ja) - [Takayuki Miyoshi](http://ideasilo.wordpress.com)
58
* Korean (ko_KR) - Seong Eun Lee, [Jong-In Kim](http://incommunity.codex.kr/wordpress/)
59
* Latvian (lv) - [Sandis Veinbergs](http://www.kleofass.lv/)
60
- * Lithuanian (lt_LT) - [Ernestas Kardzys](http://www.ernestas.info/)
61
* Macedonian (mk_MK) - [Darko](http://www.findermind.com/)
62
* Malay (ms_MY) - [Zairul Azmil](http://www.zairul.com/)
63
* Malayalam (ml_IN) - [RAHUL.S.A](http://www.infution.co.cc/)
@@ -71,7 +71,7 @@ It is hard to continue development and support for this plugin without contribut
71
* Serbian (sr_RS) - [Vedran](http://www.seorabbit.com/), [Aleksandar Urošević](http://blog.urosevic.net/)
72
* Sinhala (si_LK) - [Nitin Aggarwal](http://offshoreally.com/)
73
* Slovak (sk_SK) - [Patrik Bóna](http://www.mrhead.sk/)
74
- * Slovene (sl_SI) - [Mihael Simonič](http://smihael.bplaced.net)
75
* Spanish (es_ES) - [Jordi Sancho](http://www.qasolutions.net/blog), [Vladimir Prieto](http://vladimir.prie.to/), [Federico Mikaelian](http://www.fedemika.com.ar/), [Matias Baldanza](http://matiasbaldanza.com/), [Carlos Agnese](http://albumdecarlitos.com.ar/)
76
* Swedish (sv_SE) - [Fredrik Jonsson](http://www.fredda-o-ac.se/), [the Swedish community](http://wp-support.se/)
77
* Tagalog (tl) - [Rupert Agnew Lanuza](http://wheretobuy.com.ph/)
@@ -113,6 +113,15 @@ Do you have questions or issues with Contact Form 7? Use these support channels
113
114
== Changelog ==
115
116
= 3.1.1 =
117
118
* Introduce wpcf7_verify_nonce() and wpcf7_create_nonce() for front-end use. This fixes the wrong nonce issue on cached pages.
4
Tags: contact, form, contact form, feedback, email, ajax, captcha, akismet, multilingual
5
Requires at least: 3.2
6
Tested up to: 3.3.1
7
+ Stable tag: 3.1.2
8
9
Just another contact form plugin. Simple but flexible.
10
57
* Japanese (ja) - [Takayuki Miyoshi](http://ideasilo.wordpress.com)
58
* Korean (ko_KR) - Seong Eun Lee, [Jong-In Kim](http://incommunity.codex.kr/wordpress/)
59
* Latvian (lv) - [Sandis Veinbergs](http://www.kleofass.lv/)
60
+ * Lithuanian (lt_LT) - [Ernestas Kardzys](http://www.ernestas.info/), [Vincent G](http://www.host1free.com/)
61
* Macedonian (mk_MK) - [Darko](http://www.findermind.com/)
62
* Malay (ms_MY) - [Zairul Azmil](http://www.zairul.com/)
63
* Malayalam (ml_IN) - [RAHUL.S.A](http://www.infution.co.cc/)
71
* Serbian (sr_RS) - [Vedran](http://www.seorabbit.com/), [Aleksandar Urošević](http://blog.urosevic.net/)
72
* Sinhala (si_LK) - [Nitin Aggarwal](http://offshoreally.com/)
73
* Slovak (sk_SK) - [Patrik Bóna](http://www.mrhead.sk/)
74
+ * Slovene (sl_SI) - [Mihael Simonič](http://smihael.bplaced.net), Jani Roskar
75
* Spanish (es_ES) - [Jordi Sancho](http://www.qasolutions.net/blog), [Vladimir Prieto](http://vladimir.prie.to/), [Federico Mikaelian](http://www.fedemika.com.ar/), [Matias Baldanza](http://matiasbaldanza.com/), [Carlos Agnese](http://albumdecarlitos.com.ar/)
76
* Swedish (sv_SE) - [Fredrik Jonsson](http://www.fredda-o-ac.se/), [the Swedish community](http://wp-support.se/)
77
* Tagalog (tl) - [Rupert Agnew Lanuza](http://wheretobuy.com.ph/)
113
114
== Changelog ==
115
116
+ = 3.1.2 =
117
+
118
+ * Auto-generate .htaccess file in the CAPTCHA’s temporary folder to hide answer files in it.
119
+ * Make sure all fields given by form-tags are in the posted_data property.
120
+ * Fix the RTL style sheet for admin pages.
121
+ * Bug fixed: names of uploaded files don’t appear in mail body.
122
+ * The jQuery Form Plugin (jquery.form.js) has been updated to 3.08.
123
+ * Translations for German, Hungarian, Slovene, and Lithuanian have been updated.
124
+
125
= 3.1.1 =
126
127
* Introduce wpcf7_verify_nonce() and wpcf7_create_nonce() for front-end use. This fixes the wrong nonce issue on cached pages.
wp-contact-form-7.php CHANGED
@@ -7,7 +7,7 @@ Author: Takayuki Miyoshi
7
Author URI: http://ideasilo.wordpress.com/
8
Text Domain: wpcf7
9
Domain Path: /languages/
10
- Version: 3.1.1
11
*/
12
13
/* Copyright 2007-2012 Takayuki Miyoshi (email: takayukister at gmail.com)
@@ -27,7 +27,7 @@ Version: 3.1.1
27
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28
*/
29
30
- define( 'WPCF7_VERSION', '3.1.1' );
31
32
define( 'WPCF7_REQUIRED_WP_VERSION', '3.2' );
33
7
Author URI: http://ideasilo.wordpress.com/
8
Text Domain: wpcf7
9
Domain Path: /languages/
10
+ Version: 3.1.2
11
*/
12
13
/* Copyright 2007-2012 Takayuki Miyoshi (email: takayukister at gmail.com)
27
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28
*/
29
30
+ define( 'WPCF7_VERSION', '3.1.2' );
31
32
define( 'WPCF7_REQUIRED_WP_VERSION', '3.2' );
33