1<!-- 2Copyright (c) 2014 The Polymer Project Authors. All rights reserved. 3This code may only be used under the BSD style license found at https://polymer.github.io/LICENSE.txt 4The complete set of authors may be found at https://polymer.github.io/AUTHORS.txt 5The complete set of contributors may be found at https://polymer.github.io/CONTRIBUTORS.txt 6Code distributed by Google as part of the polymer project is also 7subject to an additional IP rights grant found at https://polymer.github.io/PATENTS.txt 8--> 9 10<link rel="import" href="../polymer/polymer.html"> 11<link rel="import" href="google-js-api.html"> 12 13<!-- 14Element for loading a specific client Google API with the JavaScript client library. 15 16For loading `gapi.client` libraries 17 18##### Example 19 20 <google-client-loader id="shortener" 21 name="urlshortener" 22 version="v1"></google-client-loader> 23 24 <script> 25 var shortener = document.getElementById('shortener'); 26 shortener.addEventListener('google-api-load', function(event) { 27 var request = shortener.api.url.get({ 28 shortUrl: 'http://goo.gl/fbsS' 29 }); 30 request.execute(function(resp) { 31 console.log(resp); 32 }); 33 }); 34 </script> 35 36@demo 37--> 38 39<script> 40 (function() { 41 'use strict'; 42 43 // Stores whether the API client is done loading. 44 var _clientLoaded = false; 45 46 // Loaders and loading statuses for all APIs, indexed by API name. 47 // This helps prevent multiple loading requests being fired at the same time 48 // by multiple google-api-loader elements. 49 var _statuses = {}; 50 var _loaders = {}; 51 52 Polymer({ 53 54 is: 'google-client-loader', 55 56 /** 57 * Fired when the requested API is loaded. Override this name 58 * by setting `successEventName`. 59 * @event google-api-load 60 */ 61 62 /** 63 * Fired if an error occurs while loading the requested API. Override this name 64 * by setting `errorEventName`. 65 * @event google-api-load-error 66 */ 67 68 properties: { 69 /** 70 * Name of the API to load, e.g. 'urlshortener'. 71 * 72 * You can find the full list of APIs on the 73 * <a href="https://developers.google.com/apis-explorer"> Google APIs 74 * Explorer</a>. 75 */ 76 name: String, 77 78 /** 79 * Version of the API to load, e.g. 'v1'. 80 */ 81 version: String, 82 83 /** 84 * App Engine application ID for loading a Google Cloud Endpoints API. 85 */ 86 appId: String, 87 88 /** 89 * Root URL where to load the API from, e.g. 'http://host/apis'. 90 * For App Engine dev server this would be something like: 91 * 'http://localhost:8080/_ah/api'. 92 * Overrides 'appId' if both are specified. 93 */ 94 apiRoot: String, 95 96 /** 97 * Name of the event fired when API library is loaded. 98 */ 99 successEventName: { 100 type: String, 101 value: 'google-api-load' 102 }, 103 104 /** 105 * Name of the event fired when there is an error loading the library. 106 */ 107 errorEventName: { 108 type: String, 109 value: 'google-api-load-error' 110 } 111 }, 112 113 hostAttributes: { 114 hidden: true // remove from rendering tree. 115 }, 116 117 // Used to fix events potentially being fired multiple times by 118 // iron-jsonp-library. 119 _waiting: false, 120 121 /** 122 * Returns the loaded API. 123 */ 124 get api() { 125 if (window.gapi && window.gapi.client && 126 window.gapi.client[this.name]) { 127 return window.gapi.client[this.name]; 128 } else { 129 return undefined; 130 } 131 }, 132 133 /** 134 * Wrapper for `gapi.auth`. 135 */ 136 get auth() { 137 return gapi.auth; 138 }, 139 140 ready: function() { 141 this._loader = document.createElement('google-js-api'); 142 this.listen(this._loader, 'js-api-load', '_loadClient'); 143 }, 144 145 detached: function() { 146 this.unlisten(this._loader, 'js-api-load', '_loadClient'); 147 }, 148 149 _loadClient: function() { 150 gapi.load('client', this._doneLoadingClient.bind(this)); 151 }, 152 153 _handleLoadResponse: function(response) { 154 if (response && response.error) { 155 _statuses[this.name] = 'error'; 156 this._fireError(response); 157 } else { 158 _statuses[this.name] = 'loaded'; 159 this._fireSuccess(); 160 } 161 }, 162 163 _fireSuccess: function() { 164 this.fire(this.successEventName, 165 { 'name': this.name, 'version': this.version }); 166 }, 167 168 _fireError: function(response) { 169 if (response && response.error) { 170 this.fire(this.errorEventName, { 171 'name': this.name, 172 'version': this.version, 173 'error': response.error }); 174 } else { 175 this.fire(this.errorEventName, { 176 'name': this.name, 177 'version': this.version }); 178 } 179 }, 180 181 _doneLoadingClient: function() { 182 _clientLoaded = true; 183 // Fix for API client load event being fired multiple times by 184 // iron-jsonp-library. 185 if (!this._waiting) { 186 this._loadApi(); 187 } 188 }, 189 190 _createSelfRemovingListener: function(eventName) { 191 var handler = function () { 192 _loaders[this.name].removeEventListener(eventName, handler); 193 this._loadApi(); 194 }.bind(this); 195 196 return handler; 197 }, 198 199 _loadApi: function() { 200 if (_clientLoaded && this.name && this.version) { 201 this._waiting = false; 202 // Is this API already loaded? 203 if (_statuses[this.name] == 'loaded') { 204 this._fireSuccess(); 205 // Is a different google-api-loader already loading this API? 206 } else if (_statuses[this.name] == 'loading') { 207 this._waiting = true; 208 _loaders[this.name].addEventListener(this.successEventName, 209 this._createSelfRemovingListener(this.successEventName)); 210 _loaders[this.name].addEventListener(this.errorEventName, 211 this._createSelfRemovingListener(this.errorEventName)); 212 // Did we get an error when we tried to load this API before? 213 } else if (_statuses[this.name] == 'error') { 214 this._fireError(null); 215 // Otherwise, looks like we're loading a new API. 216 } else { 217 var root; 218 if (this.apiRoot) { 219 root = this.apiRoot; 220 } else if (this.appId) { 221 root = 'https://' + this.appId + '.appspot.com/_ah/api'; 222 } 223 _statuses[this.name] = 'loading'; 224 _loaders[this.name] = this; 225 gapi.client.load(this.name, this.version, 226 this._handleLoadResponse.bind(this), root); 227 } 228 } 229 } 230 }); 231 })(); 232</script> 233