Skip to content
Snippets Groups Projects
Select Git revision
  • 60829f30587a3dba6bd8f0fadfcf7052657217db
  • master default protected
  • 1.31
  • 4.38.7
  • 4.38.6
  • 4.38.5
  • 4.38.4
  • 4.38.3
  • 4.38.2
  • 4.38.1
  • 4.38.0
  • 4.37.2
  • 4.37.1
  • 4.37.0
  • 4.36.0
  • 4.35.0
  • 4.34.1
  • 4.34.0
  • 4.33.1
  • 4.33.0
  • 4.32.2
  • 4.32.1
  • 4.32.0
23 results

resourcemanager.mjs

Blame
  • resourcemanager.mjs 4.62 KiB
    /**
     * Copyright schukai GmbH and contributors 2023. All Rights Reserved.
     * Node module: @schukai/monster
     * This file is licensed under the AGPLv3 License.
     * License text available at https://www.gnu.org/licenses/agpl-3.0.en.html
     */
    
    import { extend } from "../data/extend.mjs";
    import { Base } from "../types/base.mjs";
    import { getGlobalObject } from "../types/global.mjs";
    import { equipWithInternal } from "../types/internal.mjs";
    import { isArray } from "../types/is.mjs";
    import { ATTRIBUTE_HREF, ATTRIBUTE_SRC } from "./constants.mjs";
    import { Resource } from "./resource.mjs";
    import { Data } from "./resource/data.mjs";
    import { Stylesheet } from "./resource/link/stylesheet.mjs";
    import { Script } from "./resource/script.mjs";
    
    export { ResourceManager };
    
    /**
     * The ResourceManager is a singleton that manages all resources.
     *
     * @license AGPLv3
     * @since 1.25.0
     * @copyright schukai GmbH
     * @memberOf Monster.DOM
     * @summary A Resource class
     */
    class ResourceManager extends Base {
    	/**
    	 *
    	 * @param {Object} options
    	 * throw {Error} unsupported document type
    	 */
    	constructor(options) {
    		super(options);
    		equipWithInternal.call(this);
    
    		if (!(this.getOption("document") instanceof Document)) {
    			throw new Error("unsupported document type");
    		}
    	}
    
    	/**
    	 * @deprecated since 3.15.0 use getInternal instead
    	 * @property {string} baseurl
    	 */
    	getOption(key) {
    		return this.getInternal(key);
    	}
    
    	/**
    	 * @property {string} baseurl
    	 */
    	getBaseURL() {
    		this.getOption("document")?.baseURL;
    	}
    
    	/**
    	 * @property {string} baseurl
    	 * @deprecated since 3.15.0 use internalDefaults instead
    	 */
    	get defaults() {
    		return this.internalDefaults;
    	}
    
    	/**
    	 *
    	 * @property {HTMLDocument} document=document Document
    	 * @property {Object} resources
    	 * @property {Array} resources.scripts=[] array with {@link Monster.DOM.Resource.Script} objects
    	 * @property {Array} resources.stylesheets=[] array with {@link Monster.DOM.Resource.Link.Stylesheet} objects
    	 * @property {Array} resources.data=[] array with {@link Monster.DOM.Resource.Data} objects
    	 */
    	get internalDefaults() {
    		return Object.assign(
    			{},
    			{
    				document: getGlobalObject("document"),
    				resources: {
    					scripts: [],
    					stylesheets: [],
    					data: [],
    				},
    			},
    		);
    	}
    
    	/**
    	 * Append Tags to DOM
    	 *
    	 * @return {Monster.DOM.ResourceManager}
    	 * @throws {Error} unsupported resource definition
    	 */
    	connect() {
    		runResourceMethod.call(this, "connect");
    		return this;
    	}
    
    	/**
    	 * Check if available
    	 *
    	 * @return {Promise}
    	 * @throws {Error} unsupported resource definition
    	 */
    	available() {
    		return Promise.all(runResourceMethod.call(this, "available"));
    	}
    
    	/**
    	 * Add a script
    	 *
    	 * @param {string|URL} url
    	 * @param [Object|undefined} options
    	 * @return {Monster.DOM.ResourceManager}
    	 * @see Monster.DOM.Resource.Script
    	 */
    	addScript(url, options) {
    		return addResource.call(this, "scripts", url, options);
    	}
    
    	/**
    	 * Add Stylesheet
    	 *
    	 * @param {string|URL} url
    	 * @param [Object|undefined} options
    	 * @return {Monster.DOM.ResourceManager}
    	 * @see Monster.DOM.Resource.Link.Stylesheet
    	 */
    	addStylesheet(url, options) {
    		return addResource.call(this, "stylesheets", url, options);
    	}
    
    	/**
    	 * Add Data Tag
    	 *
    	 * @param {string|URL} url
    	 * @param [Object|undefined} options
    	 * @return {Monster.DOM.ResourceManager}
    	 * @see Monster.DOM.Resource.Data
    	 */
    	addData(url, options) {
    		return addResource.call(this, "data", url, options);
    	}
    }
    
    /**
     * @private
     * @param {string} method
     * @return {Array}
     */
    function runResourceMethod(method) {
    	const result = [];
    
    	for (const type of ["scripts", "stylesheets", "data"]) {
    		const resources = this.getOption(`resources.${type}`);
    		if (!isArray(resources)) {
    			continue;
    		}
    
    		for (const resource of resources) {
    			if (!(resource instanceof Resource)) {
    				throw new Error("unsupported resource definition");
    			}
    
    			result.push(resource[method]());
    		}
    	}
    
    	return result;
    }
    
    /**
     *
     * @param {string} type
     * @param {string|URL} url
     * @param [Object|undefined} options
     * @return {Monster.DOM.ResourceManager}
     * @private
     */
    function addResource(type, url, options) {
    	if (url instanceof URL) {
    		url = url.toString();
    	}
    
    	options = options || {};
    
    	let resource;
    	switch (type) {
    		case "scripts":
    			resource = new Script(extend({}, options, { [ATTRIBUTE_SRC]: url }));
    			break;
    		case "stylesheets":
    			resource = new Stylesheet(extend({}, options, { [ATTRIBUTE_HREF]: url }));
    			break;
    		case "data":
    			resource = new Data(extend({}, options, { [ATTRIBUTE_SRC]: url }));
    			break;
    		default:
    			throw new Error(`unsupported type ${type}`);
    	}
    
    	this.getOption("resources")?.[type].push(resource);
    	return this;
    }