UNPKG

@bespunky/angular-zen

Version:

The Angular tools you always wished were there.

1 lines 16.5 kB
{"version":3,"file":"bespunky-angular-zen-async.mjs","sources":["../../../../libs/angular-zen/async/src/async.module.ts","../../../../libs/angular-zen/async/src/lazy-loader/lazy-loader.service.ts","../../../../libs/angular-zen/async/src/utils/promiseLater.ts","../../../../libs/angular-zen/async/src/bespunky-angular-zen-async.ts"],"sourcesContent":["import { NgModule } from '@angular/core';\n\nimport { CoreModule } from '@bespunky/angular-zen/core';\nimport { UniversalModule } from '@bespunky/angular-zen/universal';\n\n@NgModule({\n declarations: [],\n imports: [ CoreModule, UniversalModule ],\n exports: [ CoreModule ]\n})\nexport class AsyncModule { }\n","import { Observable, of } from 'rxjs';\nimport { Injectable, ElementRef } from '@angular/core';\n\nimport { HeadService } from '@bespunky/angular-zen/core';\nimport { UniversalService } from '@bespunky/angular-zen/universal';\nimport { ScriptLoadOptions } from './script-load-options';\nimport { LoadOptions } from './load-options';\nimport { LazyLoadedFile } from './lazy-loaded-file';\n\ntype ElementCreator = (url: string, onLoad: () => void, onError: (error: any) => void, options: LoadOptions) => ElementRef;\n\n/**\n * Provides methods for lazy loading scripts and styles programatically.\n * The service keeps track of loaded files to skip reloading unless specified otherwise in the options of `loadScript()` or `loadStyle()`.\n */\n@Injectable({\n providedIn: 'root'\n})\nexport class LazyLoaderService\n{\n /**\n * Defines the default options when calling the `LazyLoaderService.loadScript()` method.\n */\n private defaultScriptOptions: ScriptLoadOptions = {\n async: true,\n defer: true,\n alreadyLoaded: (url) => this.isCached(url) || this.isScriptPresent(url),\n force: false\n };\n\n /**\n * Defines the default options when calling the `LazyLoaderService.loadStyle()` method.\n */\n private defaultStyleOptions: LoadOptions = {\n alreadyLoaded: (url) => this.isCached(url) || this.isStylePresent(url),\n force: false\n };\n\n /**\n * Keeps track of loaded lazy files status and references\n */\n private cache: { [url: string]: { lazyFile: LazyLoadedFile, observable: Observable<LazyLoadedFile> } };\n\n constructor(private head: HeadService, private universal: UniversalService)\n {\n this.cache = {};\n }\n\n /**\n * Checks whether the file from the specified url has already been cached.\n * @param url The url for the file to check.\n * @returns A value indicating whether the file from the specified url has already been cached.\n */\n public isCached(url: string): boolean\n {\n return !!this.cache[url];\n }\n\n /**\n * Checks whether a script element is already present in `<head>` for the given url.\n * This doesn't guarantee that the script has been loaded.\n * \n * @param {string} url The url of the loaded script.\n * @returns {boolean} `true` if an element matching the url is present in `<head>`; otherwise `false.\n */\n public isScriptPresent(url: string): boolean\n {\n return this.head.contains('script', { src: url });\n }\n\n /**\n * Checks whether a link element is already present in `<head>` for the given style url.\n * This doesn't guarantee that the style has been loaded.\n * \n * @param {string} url The url of the loaded link.\n * @returns {boolean} `true` if an element matching the url is present in `<head>`; otherwise `false.\n */\n public isStylePresent(url: string): boolean\n {\n return this.head.contains('link', { rel: 'stylesheet', href: url });\n }\n\n /**\n * Loads a script programatically.\n *\n * @param url The full url of the script to load.\n * @param options (Optional) Specifies custom options to override default behaviour.\n * @returns An observable object which allows subscribers to know when the script has been loaded and access its associated `<script>` element.\n * The observable will complete immediately in case the script was already previously loaded.\n * If the script was already loaded outside of the service, the observable will stream `undefined`.\n */\n public loadScript(url: string, options: ScriptLoadOptions = this.defaultScriptOptions): Observable<LazyLoadedFile | null>\n {\n // Set default options if not specified by caller\n options.async = options.async === undefined ? this.defaultScriptOptions.async : options.async;\n options.defer = options.defer === undefined ? this.defaultScriptOptions.defer : options.defer;\n options.alreadyLoaded = options.alreadyLoaded === undefined ? this.defaultScriptOptions.alreadyLoaded : options.alreadyLoaded;\n options.force = options.force === undefined ? this.defaultScriptOptions.force : options.force; \n\n return this.loadFile(url, 'script', options as Required<ScriptLoadOptions>, this.createScriptElement.bind(this));\n }\n\n /**\n * Loads a style programatically.\n *\n * @param url The full url of the style to load.\n * @param options (Optional) Specifies custom options to override default behaviour.\n * @returns An observable object which allows subscribers to know when the style has been loaded and access its associated `<link>` element.\n * The observable will complete immediately in case the style was already previously loaded.\n * If the style was already loaded outside of the service, the observable will stream `undefined`.\n */\n public loadStyle(url: string, options: LoadOptions = this.defaultStyleOptions): Observable<LazyLoadedFile | null>\n {\n // Set default options if not specified by caller\n options.alreadyLoaded = options.alreadyLoaded === undefined ? this.defaultStyleOptions.alreadyLoaded : options.alreadyLoaded;\n options.force = options.force === undefined ? this.defaultStyleOptions.force : options.force;\n\n return this.loadFile(url, 'style', options as Required<LoadOptions>, this.createLinkElement.bind(this));\n }\n\n private loadFile(url: string, type: 'script' | 'style', options: Required<LoadOptions>, createElement: ElementCreator): Observable<LazyLoadedFile | null>\n {\n if (!this.universal.isPlatformBrowser) return of(null);\n\n // If the script should be loaded, load it\n if (!options.alreadyLoaded(url) || options.force)\n {\n // Initialize a base object to store the data later\n const lazyFile: LazyLoadedFile = { url, type, completed: false, element: null };\n // Create an observable that waits until the script has been loaded and executed\n const observable = new Observable<LazyLoadedFile>(observer =>\n {\n // Create the callback that will mark the script as completed and notify the subscriber\n const onLoad = () =>\n {\n lazyFile.completed = true;\n\n observer.next(lazyFile);\n observer.complete();\n };\n\n // Create the actual file tag, start downloading and store the element reference\n lazyFile.element = createElement(url, onLoad, observer.error.bind(observer), options);\n });\n\n // Cache the file and the observable for later use\n this.cache[url] = { lazyFile: lazyFile, observable };\n\n return observable;\n }\n\n // If the file was already loaded and it shouldn't be downloaded again, complete immediately with the previous link data.\n // If the file was already loaded outside of the service, the observable will stream `undefined` as there is nothing cached.\n return of(this.cache[url]?.lazyFile);\n }\n\n /**\n * Creates a `<script>` tag for the given url and adds it to the `<head>` tag to start downloading the script.\n *\n * @param url The url for the script to download.\n * @param onLoad The callback to execute when the script has been downloaded and executed.\n * @param onError The callback to execute when script download or execution has failed.\n * @param options The options to add to the script.\n * @returns A reference to the `<script>` element that was added to the DOM.\n */\n private createScriptElement(url: string, onLoad: () => void, onError: (error: any) => void, options: ScriptLoadOptions): ElementRef<HTMLScriptElement>\n {\n return this.head.addScriptElement('text/javascript', url,\n {\n async: options.async,\n defer: options.defer,\n onload: onLoad,\n onerror: onError\n });\n }\n\n /**\n * Creates a `<link>` tag for the given url and adds it to the `<head>` tag to start downloading the link.\n *\n * @param url The url for the link to download.\n * @param onLoad The callback to execute when the script has been downloaded and executed.\n * @param onError The callback to execute when script download or execution has failed.\n * @returns A reference to the `<link>` element that was added to the DOM.\n */\n private createLinkElement(url: string, onLoad: () => void, onError: (error: any) => void): ElementRef<HTMLLinkElement>\n {\n return this.head.addLinkElement('stylesheet',\n {\n type: 'text/css',\n href: url,\n onload: onLoad,\n onerror: onError\n });\n }\n}\n","type LatePromise<T> = {\n promise: Promise<T>;\n resolve: (value: T | PromiseLike<T>) => void;\n reject : (reason?: any) => void;\n};\n\n/**\n * Creates a promise without which doesn't have the actual async code to resolve, and extracts its `resolve()` and `reject()` methods for later use.\n * Use this when you have to create a promise for an async code that runs in a place different to the one where you create the promise, and it will\n * allow you full control of the promise from other parts of your code.\n *\n * @example\n * import { promiseLater } from '@bespunky/angular-zen/core';\n * // Other imports...\n *\n * export class SomeDirective implements OnInit, OnChanges\n * {\n * private const waitForInit: Promise<SomeType>;\n *\n * constructor()\n * {\n * this.waitForInit = promiseLater();\n * }\n *\n * ngOnInit()\n * {\n * this.waitForInit.resolve();\n * }\n *\n * ngOnChanges(changes: SimpleChanges)\n * {\n * this.waitForInit.promise.then(() => {\n * // ... Some code\n * });\n * }\n * }\n *\n * @export\n * @template T The type of the value promised after resolving the async operation.\n * @returns An object containing the promise, anlong with its `resolve()` and `reject()` methods.\n */\nexport function promiseLater<T>(): LatePromise<T>\n{\n const latePromise: Partial<LatePromise<T>> = { };\n\n const promise = new Promise<T>((resolve, reject) =>\n {\n latePromise.resolve = resolve;\n latePromise.reject = reject;\n });\n\n latePromise.promise = promise;\n\n return latePromise as LatePromise<T>;\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}