| OLD | NEW |
| (Empty) |
| 1 | |
| 2 | |
| 3 Polymer('core-ajax', { | |
| 4 /** | |
| 5 * Fired when a response is received. | |
| 6 * | |
| 7 * @event core-response | |
| 8 */ | |
| 9 | |
| 10 /** | |
| 11 * Fired when an error is received. | |
| 12 * | |
| 13 * @event core-error | |
| 14 */ | |
| 15 | |
| 16 /** | |
| 17 * Fired whenever a response or an error is received. | |
| 18 * | |
| 19 * @event core-complete | |
| 20 */ | |
| 21 | |
| 22 /** | |
| 23 * The URL target of the request. | |
| 24 * | |
| 25 * @attribute url | |
| 26 * @type string | |
| 27 * @default '' | |
| 28 */ | |
| 29 url: '', | |
| 30 | |
| 31 /** | |
| 32 * Specifies what data to store in the `response` property, and | |
| 33 * to deliver as `event.response` in `response` events. | |
| 34 * | |
| 35 * One of: | |
| 36 * | |
| 37 * `text`: uses `XHR.responseText`. | |
| 38 * | |
| 39 * `xml`: uses `XHR.responseXML`. | |
| 40 * | |
| 41 * `json`: uses `XHR.responseText` parsed as JSON. | |
| 42 * | |
| 43 * `arraybuffer`: uses `XHR.response`. | |
| 44 * | |
| 45 * `blob`: uses `XHR.response`. | |
| 46 * | |
| 47 * `document`: uses `XHR.response`. | |
| 48 * | |
| 49 * @attribute handleAs | |
| 50 * @type string | |
| 51 * @default 'text' | |
| 52 */ | |
| 53 handleAs: '', | |
| 54 | |
| 55 /** | |
| 56 * If true, automatically performs an Ajax request when either `url` or `par
ams` changes. | |
| 57 * | |
| 58 * @attribute auto | |
| 59 * @type boolean | |
| 60 * @default false | |
| 61 */ | |
| 62 auto: false, | |
| 63 | |
| 64 /** | |
| 65 * Parameters to send to the specified URL, as JSON. | |
| 66 * | |
| 67 * @attribute params | |
| 68 * @type string (JSON) | |
| 69 * @default '' | |
| 70 */ | |
| 71 params: '', | |
| 72 | |
| 73 /** | |
| 74 * The response for the current request, or null if it hasn't | |
| 75 * completed yet or the request resulted in error. | |
| 76 * | |
| 77 * @attribute response | |
| 78 * @type Object | |
| 79 * @default null | |
| 80 */ | |
| 81 response: null, | |
| 82 | |
| 83 /** | |
| 84 * The error for the current request, or null if it hasn't | |
| 85 * completed yet or the request resulted in success. | |
| 86 * | |
| 87 * @attribute error | |
| 88 * @type Object | |
| 89 * @default null | |
| 90 */ | |
| 91 error: null, | |
| 92 | |
| 93 /** | |
| 94 * Whether the current request is currently loading. | |
| 95 * | |
| 96 * @attribute loading | |
| 97 * @type boolean | |
| 98 * @default false | |
| 99 */ | |
| 100 loading: false, | |
| 101 | |
| 102 /** | |
| 103 * The progress of the current request. | |
| 104 * | |
| 105 * @attribute progress | |
| 106 * @type {loaded: number, total: number, lengthComputable: boolean} | |
| 107 * @default {} | |
| 108 */ | |
| 109 progress: null, | |
| 110 | |
| 111 /** | |
| 112 * The HTTP method to use such as 'GET', 'POST', 'PUT', or 'DELETE'. | |
| 113 * Default is 'GET'. | |
| 114 * | |
| 115 * @attribute method | |
| 116 * @type string | |
| 117 * @default '' | |
| 118 */ | |
| 119 method: '', | |
| 120 | |
| 121 /** | |
| 122 * HTTP request headers to send. | |
| 123 * | |
| 124 * Example: | |
| 125 * | |
| 126 * <core-ajax | |
| 127 * auto | |
| 128 * url="http://somesite.com" | |
| 129 * headers='{"X-Requested-With": "XMLHttpRequest"}' | |
| 130 * handleAs="json" | |
| 131 * on-core-response="{{handleResponse}}"></core-ajax> | |
| 132 * | |
| 133 * @attribute headers | |
| 134 * @type Object | |
| 135 * @default null | |
| 136 */ | |
| 137 headers: null, | |
| 138 | |
| 139 /** | |
| 140 * Optional raw body content to send when method === "POST". | |
| 141 * | |
| 142 * Example: | |
| 143 * | |
| 144 * <core-ajax method="POST" auto url="http://somesite.com" | |
| 145 * body='{"foo":1, "bar":2}'> | |
| 146 * </core-ajax> | |
| 147 * | |
| 148 * @attribute body | |
| 149 * @type Object | |
| 150 * @default null | |
| 151 */ | |
| 152 body: null, | |
| 153 | |
| 154 /** | |
| 155 * Content type to use when sending data. | |
| 156 * | |
| 157 * @attribute contentType | |
| 158 * @type string | |
| 159 * @default 'application/x-www-form-urlencoded' | |
| 160 */ | |
| 161 contentType: 'application/x-www-form-urlencoded', | |
| 162 | |
| 163 /** | |
| 164 * Set the withCredentials flag on the request. | |
| 165 * | |
| 166 * @attribute withCredentials | |
| 167 * @type boolean | |
| 168 * @default false | |
| 169 */ | |
| 170 withCredentials: false, | |
| 171 | |
| 172 /** | |
| 173 * Additional properties to send to core-xhr. | |
| 174 * | |
| 175 * Can be set to an object containing default properties | |
| 176 * to send as arguments to the `core-xhr.request()` method | |
| 177 * which implements the low-level communication. | |
| 178 * | |
| 179 * @property xhrArgs | |
| 180 * @type Object | |
| 181 * @default null | |
| 182 */ | |
| 183 xhrArgs: null, | |
| 184 | |
| 185 created: function() { | |
| 186 this.progress = {}; | |
| 187 }, | |
| 188 | |
| 189 ready: function() { | |
| 190 this.xhr = document.createElement('core-xhr'); | |
| 191 }, | |
| 192 | |
| 193 receive: function(response, xhr) { | |
| 194 if (this.isSuccess(xhr)) { | |
| 195 this.processResponse(xhr); | |
| 196 } else { | |
| 197 this.processError(xhr); | |
| 198 } | |
| 199 this.complete(xhr); | |
| 200 }, | |
| 201 | |
| 202 isSuccess: function(xhr) { | |
| 203 var status = xhr.status || 0; | |
| 204 return !status || (status >= 200 && status < 300); | |
| 205 }, | |
| 206 | |
| 207 processResponse: function(xhr) { | |
| 208 var response = this.evalResponse(xhr); | |
| 209 if (xhr === this.activeRequest) { | |
| 210 this.response = response; | |
| 211 } | |
| 212 this.fire('core-response', {response: response, xhr: xhr}); | |
| 213 }, | |
| 214 | |
| 215 processError: function(xhr) { | |
| 216 var response = xhr.status + ': ' + xhr.responseText; | |
| 217 if (xhr === this.activeRequest) { | |
| 218 this.error = response; | |
| 219 } | |
| 220 this.fire('core-error', {response: response, xhr: xhr}); | |
| 221 }, | |
| 222 | |
| 223 processProgress: function(progress, xhr) { | |
| 224 if (xhr !== this.activeRequest) { | |
| 225 return; | |
| 226 } | |
| 227 // We create a proxy object here because these fields | |
| 228 // on the progress event are readonly properties, which | |
| 229 // causes problems in common use cases (e.g. binding to | |
| 230 // <paper-progress> attributes). | |
| 231 var progressProxy = { | |
| 232 lengthComputable: progress.lengthComputable, | |
| 233 loaded: progress.loaded, | |
| 234 total: progress.total | |
| 235 } | |
| 236 this.progress = progressProxy; | |
| 237 }, | |
| 238 | |
| 239 complete: function(xhr) { | |
| 240 if (xhr === this.activeRequest) { | |
| 241 this.loading = false; | |
| 242 } | |
| 243 this.fire('core-complete', {response: xhr.status, xhr: xhr}); | |
| 244 }, | |
| 245 | |
| 246 evalResponse: function(xhr) { | |
| 247 return this[(this.handleAs || 'text') + 'Handler'](xhr); | |
| 248 }, | |
| 249 | |
| 250 xmlHandler: function(xhr) { | |
| 251 return xhr.responseXML; | |
| 252 }, | |
| 253 | |
| 254 textHandler: function(xhr) { | |
| 255 return xhr.responseText; | |
| 256 }, | |
| 257 | |
| 258 jsonHandler: function(xhr) { | |
| 259 var r = xhr.responseText; | |
| 260 try { | |
| 261 return JSON.parse(r); | |
| 262 } catch (x) { | |
| 263 console.warn('core-ajax caught an exception trying to parse response as
JSON:'); | |
| 264 console.warn('url:', this.url); | |
| 265 console.warn(x); | |
| 266 return r; | |
| 267 } | |
| 268 }, | |
| 269 | |
| 270 documentHandler: function(xhr) { | |
| 271 return xhr.response; | |
| 272 }, | |
| 273 | |
| 274 blobHandler: function(xhr) { | |
| 275 return xhr.response; | |
| 276 }, | |
| 277 | |
| 278 arraybufferHandler: function(xhr) { | |
| 279 return xhr.response; | |
| 280 }, | |
| 281 | |
| 282 urlChanged: function() { | |
| 283 if (!this.handleAs) { | |
| 284 var ext = String(this.url).split('.').pop(); | |
| 285 switch (ext) { | |
| 286 case 'json': | |
| 287 this.handleAs = 'json'; | |
| 288 break; | |
| 289 } | |
| 290 } | |
| 291 this.autoGo(); | |
| 292 }, | |
| 293 | |
| 294 paramsChanged: function() { | |
| 295 this.autoGo(); | |
| 296 }, | |
| 297 | |
| 298 bodyChanged: function() { | |
| 299 this.autoGo(); | |
| 300 }, | |
| 301 | |
| 302 autoChanged: function() { | |
| 303 this.autoGo(); | |
| 304 }, | |
| 305 | |
| 306 // TODO(sorvell): multiple side-effects could call autoGo | |
| 307 // during one micro-task, use a job to have only one action | |
| 308 // occur | |
| 309 autoGo: function() { | |
| 310 if (this.auto) { | |
| 311 this.goJob = this.job(this.goJob, this.go, 0); | |
| 312 } | |
| 313 }, | |
| 314 | |
| 315 /** | |
| 316 * Performs an Ajax request to the specified URL. | |
| 317 * | |
| 318 * @method go | |
| 319 */ | |
| 320 go: function() { | |
| 321 var args = this.xhrArgs || {}; | |
| 322 // TODO(sjmiles): we may want XHR to default to POST if body is set | |
| 323 args.body = this.body || args.body; | |
| 324 args.params = this.params || args.params; | |
| 325 if (args.params && typeof(args.params) == 'string') { | |
| 326 args.params = JSON.parse(args.params); | |
| 327 } | |
| 328 args.headers = this.headers || args.headers || {}; | |
| 329 if (args.headers && typeof(args.headers) == 'string') { | |
| 330 args.headers = JSON.parse(args.headers); | |
| 331 } | |
| 332 var hasContentType = Object.keys(args.headers).some(function (header) { | |
| 333 return header.toLowerCase() === 'content-type'; | |
| 334 }); | |
| 335 // No Content-Type should be specified if sending `FormData`. | |
| 336 // The UA must set the Content-Type w/ a calculated multipart boundary ID
. | |
| 337 if (args.body instanceof FormData) { | |
| 338 delete args.headers['Content-Type']; | |
| 339 } | |
| 340 else if (!hasContentType && this.contentType) { | |
| 341 args.headers['Content-Type'] = this.contentType; | |
| 342 } | |
| 343 if (this.handleAs === 'arraybuffer' || this.handleAs === 'blob' || | |
| 344 this.handleAs === 'document') { | |
| 345 args.responseType = this.handleAs; | |
| 346 } | |
| 347 args.withCredentials = this.withCredentials; | |
| 348 args.callback = this.receive.bind(this); | |
| 349 args.url = this.url; | |
| 350 args.method = this.method; | |
| 351 | |
| 352 this.response = this.error = this.progress = null; | |
| 353 this.activeRequest = args.url && this.xhr.request(args); | |
| 354 if (this.activeRequest) { | |
| 355 this.loading = true; | |
| 356 var activeRequest = this.activeRequest; | |
| 357 // IE < 10 doesn't support progress events. | |
| 358 if ('onprogress' in activeRequest) { | |
| 359 this.activeRequest.addEventListener( | |
| 360 'progress', | |
| 361 function(progress) { | |
| 362 this.processProgress(progress, activeRequest); | |
| 363 }.bind(this), false); | |
| 364 } else { | |
| 365 this.progress = { | |
| 366 lengthComputable: false, | |
| 367 } | |
| 368 } | |
| 369 } | |
| 370 return this.activeRequest; | |
| 371 } | |
| 372 | |
| 373 }); | |
| 374 | |
| OLD | NEW |