Skip to content

Instantly share code, notes, and snippets.

@aegyed91
Created December 22, 2016 08:47
Show Gist options
  • Save aegyed91/39e36e054af68aa563150d732101d607 to your computer and use it in GitHub Desktop.
Save aegyed91/39e36e054af68aa563150d732101d607 to your computer and use it in GitHub Desktop.
script-loader
// credits: https://github.com/SebastianM/angular2-google-maps/blob/master/src/core/services/maps-api-loader/lazy-maps-api-loader.ts
import { Injectable } from '@angular/core';
import { isEmpty } from 'lodash';
let _callbacks = 0;
/**
* Configuration for the {@link ScriptLoader}.
*/
export interface ScriptLoaderConfig {
/**
* The Google Maps API Key (see:
* https://developers.google.com/maps/documentation/javascript/get-api-key)
*/
apiKey?: string;
/**
* The Google Maps client ID (for premium plans).
* When you have a Google Maps APIs Premium Plan license, you must authenticate
* your application with either an API key or a client ID.
* The Google Maps API will fail to load if both a client ID and an API key are included.
*/
clientId?: string;
/**
* The Google Maps channel name (for premium plans).
* A channel parameter is an optional parameter that allows you to track usage under your client
* ID by assigning a distinct channel to each of your applications.
*/
channel?: string;
/**
* Google Maps API version.
*/
apiVersion?: string;
/**
* Host and Path used for the `<script>` tag.
*/
hostAndPath?: string;
/**
* Protocol used for the `<script>` tag.
*/
protocol?: string;
/**
* Defines which Google Maps libraries should get loaded.
*/
libraries?: string[];
/**
* The default bias for the map behavior is US.
* If you wish to alter your application to serve different map tiles or bias the
* application, you can overwrite the default behavior (US) by defining a `region`.
* See https://developers.google.com/maps/documentation/javascript/basics#Region
*/
region?: string;
/**
* The Google Maps API uses the browser's preferred language when displaying
* textual information. If you wish to overwrite this behavior and force the API
* to use a given language, you can use this setting.
* See https://developers.google.com/maps/documentation/javascript/basics#Language
*/
language?: string;
}
@Injectable()
export class ScriptLoaderS {
constructor() {
}
load(c: ScriptLoaderConfig): Promise<void> {
const promiseName = 'script_loader_promise_' + _callbacks;
// const callbackName = 'script_loader_cb_' + _callbacks;
if (this[promiseName]) {
return this[promiseName];
}
const script = document.createElement('script');
script.type = 'text/javascript';
script.async = true;
script.defer = true;
script.src = this._getScriptSrc(c/*, callbackName*/);
this[promiseName] = new Promise((resolve, reject) => {
// window[callbackName] = () => {
// delete this[promiseName];
// delete window[callbackName];
// resolve();
// };
script.onload = () => {
delete this[promiseName];
resolve();
};
script.onerror = error => {
reject(error);
};
});
document.body.appendChild(script);
_callbacks = _callbacks + 1;
return this[promiseName];
}
private _getScriptSrc(c/*, callbackName*/) {
const protocol = c.protocol || 'https';
const hostAndPath = c.hostAndPath;
const queryParams = {
v: c.apiVersion || '3',
// callback: callbackName,
key: c.apiKey,
client: c.clientId,
channel: c.channel,
libraries: c.libraries,
region: c.region,
language: c.language
};
const params = Object.keys(queryParams)
.filter(k => !isEmpty(queryParams[k]))
.map(k => {
// join arrays as comma seperated strings
let i = queryParams[k];
if (Array.isArray(i)) {
return {key: k, value: i.join(',')};
}
return {key: k, value: queryParams[k]};
})
.map((entry: {key: string, value: string}) => {
return `${entry.key}=${entry.value}`;
})
.join('&');
return `${protocol}://${hostAndPath}?${params}`;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment