lemanschik / web-modules

A Web Module Loader can also be used in WInterCG Standard Supporting Runtimes
The Unlicense
0 stars 1 forks source link

first loader version #1

Open lemanschik opened 1 year ago

lemanschik commented 1 year ago
const getUrl = (url) => fetch(url);
const qS = (selector) => document?.querySelector(selector) ;
// Shim the above if the below runs in a unsupported environment it is ES2015 intentional.
var module = (function(){
  const Cls = function(){
    this._modules = {};
  };

  Cls.prototype.define = function(key, obj){
    /* */ console.info(`module: Define '${key}'`);
    this._modules[key] = obj;
    return this;
  };

  Cls.prototype.require = function(key){
    return this._modules[key];
  }

  const ins = new Cls();

  return ins;
})();

module.define('load', (function(){

  const Cls = function(){
    this._thens = [];
    this._cache = [];
    this._resolved = false;
    this._rejected = false;
    this._ready    = true;
    this._urls = [];
    this._resolved_args = undefined;
    this._rejected_args = undefined;
    this._load_num = 0;
    this._loaded_num = 0;
  };

  Cls.prototype.then = function(f1, f2){

    if(this._resolved){
      if(this._load_num > this._loaded_num) return this;

      if(typeof f1 === 'function') f1.apply(undefined, this._resolved_args);
      return this;
    }

    if(this._rejected){
      if(this._load_num > this._loaded_num) return this;

      if(typeof f2 === 'function') f2.apply(undefined, this._rejected_args);
      return this;
    }

    this._thens.push({num: this._load_num, f1: f1, f2: f2 });
    return this;
  };

  Cls.prototype.done = function(f){
    return this.then(f, undefined);
  };

  Cls.prototype.fail = function(f){
    return this.then(undefined, f);
  };

  Cls.prototype.resolve = function(){
    this._resolved_args = arguments;
    this._resolved = true;

    while(this._thens.length > 0){
      if(this._thens[0].num > this._loaded_num) return this.ready();

      let fs = this._thens.splice(0, 1)[0];
      if(typeof fs.f1 === 'function') fs.f1.apply(undefined, this._resolved_args);
    }

    return this.ready();
  };

  Cls.prototype.reject  =function(){
    this._rejected_args = arguments;
    this._rejected = true;

    while(this._thens.length > 0){
      if(this._thens[0].num > this._loaded_num) return this;

      let fs = this._thens.splice(0, 1)[0];
      if(typeof fs.f2 === 'function') fs.f2.apply(undefined, this._rejected_args);
    }

    return this;
  };

  Cls.prototype.ready = function(){
    if(this._urls.length > 0){
      let url = this._urls.splice(0, 1)[0];
      this._ready = true;
      return this.load(url);
    }

    this._ready = true;
    return this;
  };

  Cls.prototype.load = function(url){
    this._load_num++;

    if(! this._ready){
      this._urls.push(url);
      return this;
    }

    this._loaded_num++;
    this._resolved = false;
    this._rejected = false;
    this._ready = false;

    const me = this;
    /* */ console.info(`load: ${url}`);
    if(/^.+\.css\s*$/i.test(url)){
      if(qS(`link[href="${url}"`).length <= 0){
        qS('<link rel="stylesheet" type="text/css"/>')
        .attr('href', url)
        .appendTo(qS('head'));

        this.resolve();
      }
    }else{
      getUrl(url).then(function(){
        me.resolve.apply(me, arguments);
      }).catch(function(){
        me.reject.apply(me, arguments);
      });
    }

    return this;
  };

  const Func = function(url){
    let ins = new Cls();
    return ins.load(url);
  };

  return Func;

})());