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