import {S, Maybe, Either} from "../external/sanctuary/Sanctuary"; import {isNil} from "../utils/Utils"; const DOMURL = window.URL || (window as any).webkitURL || window; const sameOrigin = (url:string):boolean => (new URL(url).origin === window.location.origin); export const LOADER_TYPE_IMAGE = "image"; export enum LoaderImageType { URL = "url", } export interface LoaderImageRequest { url: string; __loaderType:string; } export interface LoaderImageResponse { img?: HTMLImageElement; errorEvt?:Event; __loaderType:string; } //Nothing means it's loading, Left/Right means error/success export type LoaderImageStatus = Maybe | Either; export type LoaderImageCallback = (resp:Either) => void; //this class is expected to be polled (or callback) //use loadImage for Promise style export class LoaderImage { private _status: Either; public __loaderType = LOADER_TYPE_IMAGE; constructor(_req:Partial, callbackAfterLoad?:LoaderImageCallback) { const req = { ..._req, __loaderType: LOADER_TYPE_IMAGE } const img = new Image(); img.addEventListener("load", evt => { this._status = S.Right({ img: img, __loaderType: LOADER_TYPE_IMAGE }); if(callbackAfterLoad !== undefined) { callbackAfterLoad(this._status); } }); img.addEventListener("error", evt => { console.error(evt); this._status = S.Left({ errorEvt: evt }) }); if(!sameOrigin(req.url)) { img.crossOrigin = "anonymous"; } img.src = req.url; } public get status():LoaderImageStatus { return isNil(this._status) ? S.Nothing : this._status } } export const loadImagePromise = (_req:Partial):Promise> => new Promise>(resolve => new LoaderImage(_req, resolve)); export const loadImageFactory = (req:Partial, callback?:LoaderImageCallback):LoaderImage => new LoaderImage(req, callback) export const isLoaderImage = (arg:any): arg is LoaderImage => arg.__loaderType === LOADER_TYPE_IMAGE;