npm package: @superherocheesecake/loader
Description: &nbsp; &nbsp;
Author: Superhero Cheesecake
Latest version: 1.1.6

#Loader 🐧🐧🐧 

&nbsp;
&nbsp;

## Tutorial: Introduction & Context

Welcome to the README of the SHCC-Loader module. We hope you enjoy using it, we created this for your happiness. This loader was created to be used with a more configurable setup. So you only include the loaders that you actually need for a project and you can write your own loaders (see "Create loader"). To achieve this a little bit more configuration is needed than other loaders. But don't worry, we'll walk you through it, hand by hand and step by step in this tutorial.  

&nbsp;
&nbsp;

## Tutorial: Getting started

In this tutorial we'll create a loader for images and sounds. The image loader will be configured globally while the sound load will be configured manually to show the difference. 
&nbsp;
First of all we need to install three packages; the global loader module, the image loader and the sound loader.

&nbsp;
&nbsp;

```
  npm install --save @superherocheesecake/loader @superherocheesecake/loaders-image-xhr-loader @superherocheesecake/loaders-howler-loader
```

&nbsp;
&nbsp;

## Tutorial: Setup

So we need to define a global rule for the images as we want all the image files to use the "Image XHR Loader" by default. To set rules you can use a regex match on the source values. Ideally you configure this in a main or index file as the rules will apply to the entire SHCC-Loader Module. 

&nbsp;
&nbsp;

```javascript
  // Define global rules preferable in the main.js or index.js

  // Import Loader package
  import { loader } from '@superherocheesecake/loader';

  // Import Image XHR Loader package
  import ImageXHRLoader from '@superherocheesecake/loaders-image-xhr-loader';

  // Define rules based on source value regex, you can add as many as you want. 
  // In this case we add only the Image XHR Loader for .png, .jpeg, .jpg and .gif files. 
  loader.use([
    {test: /\.(png|jpeg|jpg|gif)$/, loader: ImageXHRLoader},
  ]);
```

&nbsp;
&nbsp;

## Tutorial: Setup advanced

To take a small side step of the tutorial. A more common setup is to add a Data XHR Loader, Image XHR Loader and optionally a Sound Howler Loader. This configuration should be enough for most of the cases. 

&nbsp;
&nbsp;

```javascript
  // Import Loader package
  import { loader } from '@superherocheesecake/loader';

  // Import loader packages
  import DataXHRLoader from '@superherocheesecake/loaders-object-loader';
  import ImageXHRLoader from '@superherocheesecake/loaders-image-xhr-loader';
  import SoundHowlerLoader from '@superherocheesecake/loaders-howler-loader';

  // Set global rule set. 
  loader.use([
      {test: /\.json$/, loader: DataXHRLoader},
      {test: /\.(png|jpeg|jpg|gif)$/, loader: ImageXHRLoader},
      {test: /\.(ogg|mp3)$/, loader: SoundHowlerLoader},
  ]);
```

&nbsp;
&nbsp;

## Tutorial: Loader

Let's continue with the actual tutorial, we've now set the configuration so we can create the loader and add resources. Since we don't define the Sound Howler Loader in the global ruleset we need to include it when we add the sound resources. 

&nbsp;
&nbsp;

```javascript
  import { loader } from '@superherocheesecake/loader';
  import ImageXHRLoader from '@superherocheesecake/loaders-image-xhr-loader';
  import SoundHowlerLoader from '@superherocheesecake/loaders-howler-loader';

  // Define global rules
  loader.use([
    {test: /\.(png|jpeg|jpg|gif)$/, loader: ImageXHRLoader},
  ]);

  // Load image resource, we don't need to pass the loader argument since it's set in global rule set. 
  loader.load({id: 'image', source: 'image.jpeg'}).addEventListener('loaded', function(resource) {});
  
  // Load sound resource, we need to pass the loader argument sincs it's not set in global rule set. 
  loader.load({id: 'sound', source: 'sound.mp3', loader: SoundHowlerLoader}).addEventListener('loaded', function(resource) {});
```

&nbsp;
&nbsp;

## Tutorial: Queue

OK let's be honest this is pretty awesome right? But not really pratical because on most of the websites we want to load multiple resources at once on the start. But ofcourse we've thought about this as well, introducing the "queue" functionality. Let's see how that looks like in action. 

&nbsp;
&nbsp;

```javascript
  import loader, {QUEUE_STATE} from '@superherocheesecake/loader';
  import ImageXHRLoader from '@superherocheesecake/loaders-image-xhr-loader';
  import SoundHowlerLoader from '@superherocheesecake/loaders-howler-loader';

  // Define global rules
  loader.use([
    {test: /\.(png|jpeg|jpg|gif)$/, loader: ImageXHRLoader},
  ]);

  // Create a new Queue and pass resources
  const queue = loader.queue([
    {id: 'image', source: 'image.jpeg'},
    {id: 'image', source: 'image.jpeg'},
  ]);

  // Listen to queue state
  queue.addEventListener('stateChange', function(state) {
    switch (state) {
      case QUEUE_STATE.LOADING: {
        // Show preloader
        break;
      }
      case QUEUE_STATE.COMPLETED: {
        // Hide preloader
        // Start application
        break;
      }
    }
  });

  // Load queue
  queue.load();
```

&nbsp;
&nbsp;

## API reference: Loader

#### *(method)* load(config)
*Returns Resource instance*

The loader is optional, if you have defined the loader already in the configuration
the loader will use that loader. The loader option will overwrite the global loader config. 

**config (loader.load)**

Name          | Type                    | Required      | Desc
------------- | -------------           | ------------- | -------------
id            | String                  | true          | The id that identifies the asset, should unique throughout the whole app.
source        | String                  | true          | The entry point of the asset, a url to the to be resolved asset.
loader        | Loader  (see loaders)   | false         | Loader that will be used to load the asset. If global config (rules) is set you don't need to specify this. Setting this will overwrite the global config (rules). 
options       | Object                  | false         | Optional object that will pass to the config of the loader.load method. 

**example (loader.load)**

```javascript
  import { loader } from '@superherocheesecake/loader';
  import ImageXHRLoader from '@superherocheesecake/loaders-image-xhr-loader';


  // Load resource
  loader.load({id: 'backgroundImage', source: 'server.com/background-image.ext', loader: ImageXHRLoader});
```

&nbsp;
#### *(method)* get(config)
*Returns Resource instance*

Get resource by id. 

**config (loader.get)**

Name          | Type                    | Required      | Desc
------------- | -------------           | ------------- | -------------
id            | String                  | true          | The id that identifies the asset.

**example (loader.get)**

```javascript
  import { loader } from '@superherocheesecake/loader';
  import ImageXHRLoader from '@superherocheesecake/loaders-image-xhr-loader';
  
  loader.load({id: 'backgroundImage', source: 'server.com/background-image.ext', loader: ImageXHRLoader});

  // Get resource
  loader.get('backgroundImage');
```

&nbsp;
#### *(method)* getResult(config)
*Returns loader's response*

Get resource result by id. 

**config (loader.getResult)**

Name          | Type                    | Required      | Desc
------------- | -------------           | ------------- | -------------
id            | String                  | true          | The id that identifies the asset.

**example (loader.getResult)**

```javascript
  import { loader } from '@superherocheesecake/loader';
  import ImageXHRLoader from '@superherocheesecake/loaders-image-xhr-loader';
  
  // Loader is a singleton
  loader.load({id: 'backgroundImage', source: 'server.com/background-image.ext', loader: ImageXHRLoader});

  // Get resource result
  loader.getResult('backgroundImage');
```

&nbsp;
#### *(method)* queue([])
*Returns Queue instance* 

Will create a queue instance (see Queue). 

**example (loader.queue)**

```javascript
  import { loader } from '@superherocheesecake/loader';
  import ImageXHRLoader from '@superherocheesecake/loaders-image-xhr-loader';


  // Create queue
  const queue = loader.queue([
    {id: 'backgroundImage', source: 'server.com/background-image.ext', loader: ImageXHRLoader}
    {id: 'backgroundImageTwo', source: 'server.com/background-image-two.ext', loader: ImageXHRLoader}
  ]);
```

&nbsp;
#### *(property)* resources
The collection of resources added to the loader.

&nbsp;
#### *(property)* rules
The collection of rules asigned to the loader.

&nbsp;
&nbsp;

## Queue

#### *(method)* add
*Returns Resource instance*

Add resource to queue.

**config (Queue.add)**

Name          | Type                    | Required      | Desc
------------- | -------------           | ------------- | -------------
id            | String                  | true          | The id that identifies the asset, should unique throughout the whole app.
source        | String                  | true          | The entry point of the asset, a url to the to be resolved asset.
loader        | Loader  (see loaders)   | false         | Loader that will be used to load the asset. If global config (rules) is set you don't need to specify this. Setting this will overwrite the global config (rules). 
options       | Object                  | false         | Optional object that will pass to the config of the loader.load method. 

**example (Queue.add)**

```javascript
  import { loader } from '@superherocheesecake/loader';
  import ImageXHRLoader from '@superherocheesecake/loaders-image-xhr-loader';

  // Create queue
  const queue = loader.queue();
  
  // Add resource to queue pool manually
  queue.add({id: 'backgroundImage', source: 'server.com/background-image.ext', loader: ImageXHRLoader});
```

&nbsp;
#### *(method)* load
*Returns Queue instance*

Loads all the resources added to the queue. 

**example (Queue.load)**

```javascript
  import { loader } from '@superherocheesecake/loader';
  import ImageXHRLoader from '@superherocheesecake/loaders-image-xhr-loader';

  // Create queue
  const queue = loader.queue([
    {id: 'backgroundImage', source: 'server.com/background-image.ext', loader: ImageXHRLoader}
    {id: 'backgroundImageTwo', source: 'server.com/background-image-two.ext', loader: ImageXHRLoader}
  ]);
  
  // Load queue
  queue.load();
```

&nbsp;
#### *(method)* get
*Returns Resource instance*

Find a resource in the queue from id. 

**config (Queue.get)**

Name          | Type                    | Required      | Desc
------------- | -------------           | ------------- | -------------
id            | String                  | true          | The id that identifies the asset.

**example (Queue.get)**

```javascript
  import { loader } from '@superherocheesecake/loader';
  import ImageXHRLoader from '@superherocheesecake/loaders-image-xhr-loader';


  // Create queue
  const queue = loader.queue([
    {id: 'backgroundImage', source: 'server.com/background-image.ext', loader: ImageXHRLoader}
    {id: 'backgroundImageTwo', source: 'server.com/background-image-two.ext', loader: ImageXHRLoader}
  ]);

  // Load queue
  queue.load();

  // Get resource from queue
  queue.get('backgroundImage');
```

&nbsp;
#### *(method)* getResult
*Returns loader's response*

Get resource by id from queue. 

**config (loader.getResult)**

Name          | Type                    | Required      | Desc
------------- | -------------           | ------------- | -------------
id            | String                  | true          | The id that identifies the asset.

**example (loader.getResult) **
```javascript
  import { loader } from '@superherocheesecake/loader';
  import ImageXHRLoader from '@superherocheesecake/loaders-image-xhr-loader';

  // Create queue
  const queue = loader.queue([
    {id: 'backgroundImage', source: 'server.com/background-image.ext', loader: ImageXHRLoader}
    {id: 'backgroundImageTwo', source: 'server.com/background-image-two.ext', loader: ImageXHRLoader}
  ]);

  // Load queue
  queue.load();

  // Get resource result from queue
  queue.getResult('backgroundImage');
```

&nbsp;
#### *(property)* state
The state of the queue, values (compare with Loader.QUEUE_STATE):

Name          | Value 
------------- | -------------
INITIAL       | 'Initial'
LOADING       | 'Loading'
COMPLETED     | 'Completed'

&nbsp;
#### *(property)* progress
Value from 0.0 to 1.0, progress of amount of resources loaded in account of the total queue length. 

&nbsp;
#### *(event)* progress
Dispatches an event when the progress is updated.

&nbsp;
#### *(event)* stateChange
Dispatches an event when the queue state changes.

&nbsp;
#### *(event)* loading
Dispatches an event when the queue starts loading.

&nbsp;
#### *(event)* completed
Dispatches an event when the queue completes loading.

&nbsp;
&nbsp;

## Resource

#### *(method)* load
*Returns Resource instance*

Loads the resource. 

**example (Resource.load)**

```javascript
  import { loader } from '@superherocheesecake/loader';
  import ImageXHRLoader from '@superherocheesecake/loaders-image-xhr-loader';
  
  // Add resource
  const resource = loader.add({id: 'backgroundImage', source: 'server.com/background-image.ext', loader: ImageXHRLoader});

  // Load single resource
  resource.load();
```

&nbsp;
#### *(property)* state
The state of the resource, values (compare with Loader.RESOURCE_STATE):

Name          | Value 
------------- | -------------
INITIAL       | 'Initial'
LOADING       | 'Loading'
LOADED        | 'Loaded'
FAILED        | 'Failed'

&nbsp;
#### *(event)* stateChange
Dispatches an event when the resource state changes.

&nbsp;
#### *(event)* loading
Dispatches an event when the resource starts loading.

&nbsp;
#### *(event)* loaded
Dispatches an event when the resource is loaded.

&nbsp;
#### *(event)* failed
Dispatches an event when the resource has failed to load.

&nbsp;
&nbsp;

## Loaders
- [Data XHR loader](https://code.shcc.nl/projects/frontend-packages/repositories/shcc-utils-loaders-data-xhr-loader)
- [Font loader](https://code.shcc.nl/projects/frontend-packages/repositories/shcc-utils-loaders-font-loader)
- [Image simple loader](https://code.shcc.nl/projects/frontend-packages/repositories/shcc-utils-loaders-image-simple-loader)
- [Image WebWorker loader](https://code.shcc.nl/projects/frontend-packages/repositories/shcc-utils-loaders-image-webworker-loader)
- [Image XHR loader](https://code.shcc.nl/projects/frontend-packages/repositories/shcc-utils-loaders-image-xhr-loader)
- [Sound Howler loader](https://code.shcc.nl/projects/frontend-packages/repositories/shcc-utils-loaders-sound-howler-loader)
- [Video simple loader](https://code.shcc.nl/projects/frontend-packages/repositories/shcc-utils-loaders-video-simple-loader)
- [Video XHR loader](https://code.shcc.nl/projects/frontend-packages/repositories/shcc-utils-loaders-video-xhr-loader)

&nbsp;
&nbsp;

## Create loader

**Loader Class**

Name          | Desc
------------- | -------------
onLoaded      | (setter) The callback that needs to be executed when loaded (invoked from, Resource instance)
onFailed      | (setter) The callback that needs to be executed when failed to load (invoked from, Resource instance)
isSupported   | (method) Returns boolean, if false it will use the fallback loader. 
load          | (method) Function that is invoked when the resource load is invoked.

**example**

```javascript
  
  class LoaderName {

    set onLoaded(callback) {
      this._callbacks.onLoaded = callback;
    }
    set onFailed(callback) {
      this._callbacks.onFailed = callback;
    }

    constructor() {
      this._callbacks = {};
    }

    isSupported() {

      // Check if supported, return true if supported, false if not...
      return true;

    }

    load(source, options {}) {

        // Load code here ...

        // If loaded dispatch this.loaded();
        // If failed dispatch this.failed();

        this.loaded();

    }

    loaded() {
      if (this._callbacks.onLoaded) this._callbacks.onLoaded();
    }
    
    failed() {
      if (this._callbacks.onFailed) this._callbacks.onFailed();
    }

  }
  
```

&nbsp;
&nbsp;

##Build
After updating the code you should run
```npm run build```
to make it es5 compatible.