OLD | NEW |
1 <!-- | 1 <!-- |
2 Copyright (c) 2014 The Polymer Project Authors. All rights reserved. | 2 Copyright (c) 2014 The Polymer Project Authors. All rights reserved. |
3 This code may only be used under the BSD style license found at http://polymer.g
ithub.io/LICENSE.txt | 3 This code may only be used under the BSD style license found at http://polymer.g
ithub.io/LICENSE.txt |
4 The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt | 4 The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt |
5 The complete set of contributors may be found at http://polymer.github.io/CONTRI
BUTORS.txt | 5 The complete set of contributors may be found at http://polymer.github.io/CONTRI
BUTORS.txt |
6 Code distributed by Google as part of the polymer project is also | 6 Code distributed by Google as part of the polymer project is also |
7 subject to an additional IP rights grant found at http://polymer.github.io/PATEN
TS.txt | 7 subject to an additional IP rights grant found at http://polymer.github.io/PATEN
TS.txt |
8 --> | 8 --> |
9 | 9 |
10 <!-- | 10 <!-- |
11 @group Polymer Core Elements | 11 @group Polymer Core Elements |
12 | 12 |
13 The `core-ajax` element exposes `XMLHttpRequest` functionality. | 13 The `core-ajax` element exposes `XMLHttpRequest` functionality. |
14 | 14 |
15 <core-ajax | 15 <core-ajax |
16 auto | 16 auto |
17 url="http://gdata.youtube.com/feeds/api/videos/" | 17 url="http://gdata.youtube.com/feeds/api/videos/" |
18 params='{"alt":"json", "q":"chrome"}' | 18 params='{"alt":"json", "q":"chrome"}' |
19 handleAs="json" | 19 handleAs="json" |
20 on-core-response="{{handleResponse}}"></core-ajax> | 20 on-core-response="{{handleResponse}}"></core-ajax> |
21 | 21 |
22 With `auto` set to `true`, the element performs a request whenever | 22 With `auto` set to `true`, the element performs a request whenever |
23 its `url` or `params` properties are changed. | 23 its `url`, `params` or `body` properties are changed. |
24 | 24 |
25 Note: The `params` attribute must be double quoted JSON. | 25 Note: The `params` attribute must be double quoted JSON. |
26 | 26 |
27 You can trigger a request explicitly by calling `go` on the | 27 You can trigger a request explicitly by calling `go` on the |
28 element. | 28 element. |
29 | 29 |
30 @element core-ajax | 30 @element core-ajax |
31 @status beta | 31 @status beta |
32 @homepage github.io | 32 @homepage github.io |
33 --> | 33 --> |
34 <link rel="import" href="core-xhr.html"> | 34 <link rel="import" href="core-xhr.html"> |
35 <polymer-element name="core-ajax" hidden attributes="url handleAs auto params re
sponse error method headers body contentType withCredentials"> | 35 <polymer-element name="core-ajax" hidden attributes="url handleAs auto params re
sponse error method headers body contentType withCredentials progress loading"> |
36 <script> | 36 <script> |
37 | 37 |
38 Polymer('core-ajax', { | 38 Polymer('core-ajax', { |
39 /** | 39 /** |
40 * Fired when a response is received. | 40 * Fired when a response is received. |
41 * | 41 * |
42 * @event core-response | 42 * @event core-response |
43 */ | 43 */ |
44 | 44 |
45 /** | 45 /** |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
99 /** | 99 /** |
100 * Parameters to send to the specified URL, as JSON. | 100 * Parameters to send to the specified URL, as JSON. |
101 * | 101 * |
102 * @attribute params | 102 * @attribute params |
103 * @type string (JSON) | 103 * @type string (JSON) |
104 * @default '' | 104 * @default '' |
105 */ | 105 */ |
106 params: '', | 106 params: '', |
107 | 107 |
108 /** | 108 /** |
109 * The response for the most recently made request, or null if it hasn't | 109 * The response for the current request, or null if it hasn't |
110 * completed yet or the request resulted in error. | 110 * completed yet or the request resulted in error. |
111 * | 111 * |
112 * @attribute response | 112 * @attribute response |
113 * @type Object | 113 * @type Object |
114 * @default null | 114 * @default null |
115 */ | 115 */ |
116 response: null, | 116 response: null, |
117 | 117 |
118 /** | 118 /** |
119 * The error for the most recently made request, or null if it hasn't | 119 * The error for the current request, or null if it hasn't |
120 * completed yet or the request resulted in success. | 120 * completed yet or the request resulted in success. |
121 * | 121 * |
122 * @attribute error | 122 * @attribute error |
123 * @type Object | 123 * @type Object |
124 * @default null | 124 * @default null |
125 */ | 125 */ |
126 error: null, | 126 error: null, |
127 | 127 |
128 /** | 128 /** |
| 129 * Whether the current request is currently loading. |
| 130 * |
| 131 * @attribute loading |
| 132 * @type boolean |
| 133 * @default false |
| 134 */ |
| 135 loading: false, |
| 136 |
| 137 /** |
| 138 * The progress of the current request. |
| 139 * |
| 140 * @attribute progress |
| 141 * @type {loaded: number, total: number, lengthComputable: boolean} |
| 142 * @default {} |
| 143 */ |
| 144 progress: null, |
| 145 |
| 146 /** |
129 * The HTTP method to use such as 'GET', 'POST', 'PUT', or 'DELETE'. | 147 * The HTTP method to use such as 'GET', 'POST', 'PUT', or 'DELETE'. |
130 * Default is 'GET'. | 148 * Default is 'GET'. |
131 * | 149 * |
132 * @attribute method | 150 * @attribute method |
133 * @type string | 151 * @type string |
134 * @default '' | 152 * @default '' |
135 */ | 153 */ |
136 method: '', | 154 method: '', |
137 | 155 |
138 /** | 156 /** |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
192 * Can be set to an object containing default properties | 210 * Can be set to an object containing default properties |
193 * to send as arguments to the `core-xhr.request()` method | 211 * to send as arguments to the `core-xhr.request()` method |
194 * which implements the low-level communication. | 212 * which implements the low-level communication. |
195 * | 213 * |
196 * @property xhrArgs | 214 * @property xhrArgs |
197 * @type Object | 215 * @type Object |
198 * @default null | 216 * @default null |
199 */ | 217 */ |
200 xhrArgs: null, | 218 xhrArgs: null, |
201 | 219 |
| 220 created: function() { |
| 221 this.progress = {}; |
| 222 }, |
| 223 |
202 ready: function() { | 224 ready: function() { |
203 this.xhr = document.createElement('core-xhr'); | 225 this.xhr = document.createElement('core-xhr'); |
204 }, | 226 }, |
205 | 227 |
206 receive: function(response, xhr) { | 228 receive: function(response, xhr) { |
207 if (this.isSuccess(xhr)) { | 229 if (this.isSuccess(xhr)) { |
208 this.processResponse(xhr); | 230 this.processResponse(xhr); |
209 } else { | 231 } else { |
210 this.processError(xhr); | 232 this.processError(xhr); |
211 } | 233 } |
(...skipping 14 matching lines...) Expand all Loading... |
226 }, | 248 }, |
227 | 249 |
228 processError: function(xhr) { | 250 processError: function(xhr) { |
229 var response = xhr.status + ': ' + xhr.responseText; | 251 var response = xhr.status + ': ' + xhr.responseText; |
230 if (xhr === this.activeRequest) { | 252 if (xhr === this.activeRequest) { |
231 this.error = response; | 253 this.error = response; |
232 } | 254 } |
233 this.fire('core-error', {response: response, xhr: xhr}); | 255 this.fire('core-error', {response: response, xhr: xhr}); |
234 }, | 256 }, |
235 | 257 |
| 258 processProgress: function(progress, xhr) { |
| 259 if (xhr !== this.activeRequest) { |
| 260 return; |
| 261 } |
| 262 // We create a proxy object here because these fields |
| 263 // on the progress event are readonly properties, which |
| 264 // causes problems in common use cases (e.g. binding to |
| 265 // <paper-progress> attributes). |
| 266 var progressProxy = { |
| 267 lengthComputable: progress.lengthComputable, |
| 268 loaded: progress.loaded, |
| 269 total: progress.total |
| 270 } |
| 271 this.progress = progressProxy; |
| 272 }, |
| 273 |
236 complete: function(xhr) { | 274 complete: function(xhr) { |
| 275 if (xhr === this.activeRequest) { |
| 276 this.loading = false; |
| 277 } |
237 this.fire('core-complete', {response: xhr.status, xhr: xhr}); | 278 this.fire('core-complete', {response: xhr.status, xhr: xhr}); |
238 }, | 279 }, |
239 | 280 |
240 evalResponse: function(xhr) { | 281 evalResponse: function(xhr) { |
241 return this[(this.handleAs || 'text') + 'Handler'](xhr); | 282 return this[(this.handleAs || 'text') + 'Handler'](xhr); |
242 }, | 283 }, |
243 | 284 |
244 xmlHandler: function(xhr) { | 285 xmlHandler: function(xhr) { |
245 return xhr.responseXML; | 286 return xhr.responseXML; |
246 }, | 287 }, |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
282 break; | 323 break; |
283 } | 324 } |
284 } | 325 } |
285 this.autoGo(); | 326 this.autoGo(); |
286 }, | 327 }, |
287 | 328 |
288 paramsChanged: function() { | 329 paramsChanged: function() { |
289 this.autoGo(); | 330 this.autoGo(); |
290 }, | 331 }, |
291 | 332 |
| 333 bodyChanged: function() { |
| 334 this.autoGo(); |
| 335 }, |
| 336 |
292 autoChanged: function() { | 337 autoChanged: function() { |
293 this.autoGo(); | 338 this.autoGo(); |
294 }, | 339 }, |
295 | 340 |
296 // TODO(sorvell): multiple side-effects could call autoGo | 341 // TODO(sorvell): multiple side-effects could call autoGo |
297 // during one micro-task, use a job to have only one action | 342 // during one micro-task, use a job to have only one action |
298 // occur | 343 // occur |
299 autoGo: function() { | 344 autoGo: function() { |
300 if (this.auto) { | 345 if (this.auto) { |
301 this.goJob = this.job(this.goJob, this.go, 0); | 346 this.goJob = this.job(this.goJob, this.go, 0); |
(...skipping 13 matching lines...) Expand all Loading... |
315 if (args.params && typeof(args.params) == 'string') { | 360 if (args.params && typeof(args.params) == 'string') { |
316 args.params = JSON.parse(args.params); | 361 args.params = JSON.parse(args.params); |
317 } | 362 } |
318 args.headers = this.headers || args.headers || {}; | 363 args.headers = this.headers || args.headers || {}; |
319 if (args.headers && typeof(args.headers) == 'string') { | 364 if (args.headers && typeof(args.headers) == 'string') { |
320 args.headers = JSON.parse(args.headers); | 365 args.headers = JSON.parse(args.headers); |
321 } | 366 } |
322 var hasContentType = Object.keys(args.headers).some(function (header) { | 367 var hasContentType = Object.keys(args.headers).some(function (header) { |
323 return header.toLowerCase() === 'content-type'; | 368 return header.toLowerCase() === 'content-type'; |
324 }); | 369 }); |
325 if (!hasContentType && this.contentType) { | 370 // No Content-Type should be specified if sending `FormData`. |
| 371 // The UA must set the Content-Type w/ a calculated multipart boundary ID
. |
| 372 if (args.body instanceof FormData) { |
| 373 delete args.headers['Content-Type']; |
| 374 } |
| 375 else if (!hasContentType && this.contentType) { |
326 args.headers['Content-Type'] = this.contentType; | 376 args.headers['Content-Type'] = this.contentType; |
327 } | 377 } |
328 if (this.handleAs === 'arraybuffer' || this.handleAs === 'blob' || | 378 if (this.handleAs === 'arraybuffer' || this.handleAs === 'blob' || |
329 this.handleAs === 'document') { | 379 this.handleAs === 'document') { |
330 args.responseType = this.handleAs; | 380 args.responseType = this.handleAs; |
331 } | 381 } |
332 args.withCredentials = this.withCredentials; | 382 args.withCredentials = this.withCredentials; |
333 args.callback = this.receive.bind(this); | 383 args.callback = this.receive.bind(this); |
334 args.url = this.url; | 384 args.url = this.url; |
335 args.method = this.method; | 385 args.method = this.method; |
336 | 386 |
337 this.response = this.error = null; | 387 this.response = this.error = this.progress = null; |
338 this.activeRequest = args.url && this.xhr.request(args); | 388 this.activeRequest = args.url && this.xhr.request(args); |
| 389 if (this.activeRequest) { |
| 390 this.loading = true; |
| 391 var activeRequest = this.activeRequest; |
| 392 // IE < 10 doesn't support progress events. |
| 393 if ('onprogress' in activeRequest) { |
| 394 this.activeRequest.addEventListener( |
| 395 'progress', |
| 396 function(progress) { |
| 397 this.processProgress(progress, activeRequest); |
| 398 }.bind(this), false); |
| 399 } else { |
| 400 this.progress = { |
| 401 lengthComputable: false, |
| 402 } |
| 403 } |
| 404 } |
339 return this.activeRequest; | 405 return this.activeRequest; |
340 } | 406 } |
341 | 407 |
342 }); | 408 }); |
343 | 409 |
344 </script> | 410 </script> |
345 </polymer-element> | 411 </polymer-element> |
OLD | NEW |