|
6 | 6 | </head>
|
7 | 7 | <body>
|
8 | 8 |
|
| 9 | +<!-- |
| 10 | + By default, we assume Ajax uploads are not supported. |
| 11 | + Later we'll detect support and change this message if found. |
| 12 | +--> |
9 | 13 | <p id="support-notice">Your browser does not support Ajax uploads :-(<br/>The form will be submitted as normal.</p>
|
10 | 14 |
|
| 15 | +<!-- The form starts --> |
11 | 16 | <form action="/" method="post" enctype="multipart/form-data" id="form-id">
|
12 |
| - <p><input id="file-id" type="file" name="our-file" /> <input type="button" value="Upload" id="upload-button-id" disabled="disabled" /></p> |
| 17 | + |
| 18 | + <!-- The file to upload --> |
| 19 | + <p><input id="file-id" type="file" name="our-file" /> |
| 20 | + |
| 21 | + <!-- |
| 22 | + Also by default, we disable the upload button. |
| 23 | + If Ajax uploads are supported we'll enable it. |
| 24 | + --> |
| 25 | + <input type="button" value="Upload" id="upload-button-id" disabled="disabled" /></p> |
| 26 | + |
| 27 | + <!-- A different field, just for the sake of the example --> |
13 | 28 | <p><label>Some other field: <input name="other-field" type="text" id="other-field-id" /></label></p>
|
| 29 | + |
| 30 | + <!-- And finally a submit button --> |
14 | 31 | <p><input type="submit" value="Submit" /></p>
|
| 32 | + |
15 | 33 | <script>
|
| 34 | +// Function that will allow us to know if Ajax uploads are supported |
16 | 35 | function supportAjaxUploadWithProgress() {
|
17 | 36 | return supportFileAPI() && supportAjaxUploadProgressEvents() && supportFormData();
|
18 | 37 |
|
| 38 | + // Is the File API supported? |
19 | 39 | function supportFileAPI() {
|
20 | 40 | var fi = document.createElement('INPUT');
|
21 | 41 | fi.type = 'file';
|
22 | 42 | return 'files' in fi;
|
23 | 43 | };
|
24 | 44 |
|
| 45 | + // Are progress events supported? |
25 | 46 | function supportAjaxUploadProgressEvents() {
|
26 | 47 | var xhr = new XMLHttpRequest();
|
27 | 48 | return !! (xhr && ('upload' in xhr) && ('onprogress' in xhr.upload));
|
28 | 49 | };
|
29 | 50 |
|
| 51 | + // Is FormData supported? |
30 | 52 | function supportFormData() {
|
31 | 53 | return !! window.FormData;
|
32 | 54 | }
|
33 | 55 | }
|
34 | 56 |
|
| 57 | +// Actually confirm support |
35 | 58 | if (supportAjaxUploadWithProgress()) {
|
| 59 | + // Ajax uploads are supported! |
| 60 | + // Change the support message and enable the upload button |
36 | 61 | var notice = document.getElementById('support-notice');
|
37 | 62 | var uploadBtn = document.getElementById('upload-button-id');
|
38 | 63 | notice.innerHTML = "Your browser supports HTML uploads. Go try me! :-)";
|
39 | 64 | uploadBtn.removeAttribute('disabled');
|
40 | 65 |
|
| 66 | + // Init the Ajax form submission |
41 | 67 | initFullFormAjaxUpload();
|
| 68 | + |
| 69 | + // Init the single-field file upload |
42 | 70 | initFileOnlyAjaxUpload();
|
43 | 71 | }
|
44 | 72 |
|
45 | 73 | function initFullFormAjaxUpload() {
|
46 | 74 | var form = document.getElementById('form-id');
|
47 | 75 | form.onsubmit = function() {
|
| 76 | + // FormData receives the whole form |
48 | 77 | var formData = new FormData(form);
|
| 78 | + |
| 79 | + // We send the data where the form wanted |
49 | 80 | var action = form.getAttribute('action');
|
50 | 81 |
|
| 82 | + // Code common to both variants |
51 | 83 | sendXHRequest(formData, action);
|
52 | 84 |
|
| 85 | + // Avoid normal form submission |
53 | 86 | return false;
|
54 | 87 | }
|
55 | 88 | }
|
|
58 | 91 | var uploadBtn = document.getElementById('upload-button-id');
|
59 | 92 | uploadBtn.onclick = function (evt) {
|
60 | 93 | var formData = new FormData();
|
| 94 | + |
| 95 | + // Since this is the file only, we send it to a specific location |
61 | 96 | var action = '/upload';
|
| 97 | + |
| 98 | + // FormData only has the file |
62 | 99 | var fileInput = document.getElementById('file-id');
|
63 | 100 | var file = fileInput.files[0];
|
64 | 101 | formData.append('our-file', file);
|
65 | 102 |
|
| 103 | + // Code common to both variants |
66 | 104 | sendXHRequest(formData, action);
|
67 |
| - |
68 |
| - return false; |
69 | 105 | }
|
70 | 106 | }
|
71 | 107 |
|
| 108 | +// Once the FormData instance is ready and we know |
| 109 | +// where to send the data, the code is the same |
| 110 | +// for both variants of this technique |
72 | 111 | function sendXHRequest(formData, uri) {
|
| 112 | + // Get an XMLHttpRequest instance |
73 | 113 | var xhr = new XMLHttpRequest();
|
| 114 | + |
| 115 | + // Set up events |
74 | 116 | xhr.upload.addEventListener('loadstart', onloadstartHandler, false);
|
75 | 117 | xhr.upload.addEventListener('progress', onprogressHandler, false);
|
76 | 118 | xhr.upload.addEventListener('load', onloadHandler, false);
|
77 | 119 | xhr.addEventListener('readystatechange', onreadystatechangeHandler, false);
|
| 120 | + |
| 121 | + // Set up request |
78 | 122 | xhr.open('POST', uri, true);
|
| 123 | + |
| 124 | + // Fire! |
79 | 125 | xhr.send(formData);
|
80 | 126 | }
|
81 | 127 |
|
| 128 | +// Handle the start of the transmission |
82 | 129 | function onloadstartHandler(evt) {
|
83 | 130 | var div = document.getElementById('upload-status');
|
84 | 131 | div.innerHTML = 'Upload started!';
|
85 | 132 | }
|
86 | 133 |
|
| 134 | +// Handle the end of the transmission |
87 | 135 | function onloadHandler(evt) {
|
88 | 136 | var div = document.getElementById('upload-status');
|
89 | 137 | div.innerHTML = 'Upload successful!';
|
90 | 138 | }
|
91 | 139 |
|
| 140 | +// Handle the progress |
92 | 141 | function onprogressHandler(evt) {
|
93 | 142 | var div = document.getElementById('progress');
|
94 | 143 | var percent = evt.loaded/evt.total*100;
|
95 | 144 | div.innerHTML = 'Progress: ' + percent + '%';
|
96 | 145 | }
|
97 |
| - |
| 146 | + |
| 147 | +// Handle the response from the server |
98 | 148 | function onreadystatechangeHandler(evt) {
|
99 | 149 | var status = null;
|
100 | 150 |
|
|
111 | 161 | }
|
112 | 162 | }
|
113 | 163 | </script>
|
| 164 | + |
| 165 | + <!-- Placeholders for messages set by event handlers --> |
114 | 166 | <p id="upload-status"></p>
|
115 | 167 | <p id="progress"></p>
|
116 | 168 | <pre id="result"></pre>
|
| 169 | + |
117 | 170 | </form>
|
118 | 171 | </body>
|
119 | 172 | </html>
|
0 commit comments