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)$/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)$/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)$/', $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)$">' . "\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)$/', $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