ajax-form.js
3.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
function replaceDocument(docString) {
var doc = document.open("text/html");
doc.write(docString);
doc.close();
}
function doAjaxSubmit(e) {
var form = $(this);
var btn = $(this.clk);
var method = (
btn.data('method') ||
form.data('method') ||
form.attr('method') || 'GET'
).toUpperCase();
if (method === 'GET') {
// GET requests can always use standard form submits.
return;
}
var contentType =
form.find('input[data-override="content-type"]').val() ||
form.find('select[data-override="content-type"] option:selected').text();
if (method === 'POST' && !contentType) {
// POST requests can use standard form submits, unless we have
// overridden the content type.
return;
}
// At this point we need to make an AJAX form submission.
e.preventDefault();
var url = form.attr('action');
var data;
if (contentType) {
data = form.find('[data-override="content"]').val() || ''
if (contentType === 'multipart/form-data') {
// We need to add a boundary parameter to the header
// We assume the first valid-looking boundary line in the body is correct
// regex is from RFC 2046 appendix A
var boundaryCharNoSpace = "0-9A-Z'()+_,-./:=?";
var boundaryChar = boundaryCharNoSpace + ' ';
var re = new RegExp('^--([' + boundaryChar + ']{0,69}[' + boundaryCharNoSpace + '])[\\s]*?$', 'im');
var boundary = data.match(re);
if (boundary !== null) {
contentType += '; boundary="' + boundary[1] + '"';
}
// Fix textarea.value EOL normalisation (multipart/form-data should use CR+NL, not NL)
data = data.replace(/\n/g, '\r\n');
}
} else {
contentType = form.attr('enctype') || form.attr('encoding')
if (contentType === 'multipart/form-data') {
if (!window.FormData) {
alert('Your browser does not support AJAX multipart form submissions');
return;
}
// Use the FormData API and allow the content type to be set automatically,
// so it includes the boundary string.
// See https://developer.mozilla.org/en-US/docs/Web/API/FormData/Using_FormData_Objects
contentType = false;
data = new FormData(form[0]);
} else {
contentType = 'application/x-www-form-urlencoded; charset=UTF-8'
data = form.serialize();
}
}
var ret = $.ajax({
url: url,
method: method,
data: data,
contentType: contentType,
processData: false,
headers: {
'Accept': 'text/html; q=1.0, */*'
},
});
ret.always(function(data, textStatus, jqXHR) {
if (textStatus != 'success') {
jqXHR = data;
}
var responseContentType = jqXHR.getResponseHeader("content-type") || "";
if (responseContentType.toLowerCase().indexOf('text/html') === 0) {
replaceDocument(jqXHR.responseText);
try {
// Modify the location and scroll to top, as if after page load.
history.replaceState({}, '', url);
scroll(0, 0);
} catch (err) {
// History API not supported, so redirect.
window.location = url;
}
} else {
// Not HTML content. We can't open this directly, so redirect.
window.location = url;
}
});
return ret;
}
function captureSubmittingElement(e) {
var target = e.target;
var form = this;
form.clk = target;
}
$.fn.ajaxForm = function() {
var options = {}
return this
.unbind('submit.form-plugin click.form-plugin')
.bind('submit.form-plugin', options, doAjaxSubmit)
.bind('click.form-plugin', options, captureSubmittingElement);
};