API Docs for:
Show:

File: development/js/utils/loader.js

import type from './type';
import objects from './object';

/**
 * Async image loading utility
 *
 * @module Utils
 * @class Utils.Loader
 * @static
 */


/* Loading of images
----------------- */
function isImgFile (s) {
    return type.isString(s) && !!/\.(jpg|jpeg|png|svg|gif)$/.test(s);
}

function imgReady (n) {
    if (n.complete) {
        if (n.naturalWidth) {
            return n.naturalWidth + n.naturalHeight > 0;
        }
        return n.width + n.height > 0;
    }
}

function loadImgRecursive (img, done, fail, always, attempts) {
    if (!type.isNode(img) || img.nodeName !== 'IMG') {
        throw 'Unable to load, expected first argument to be <img> but saw: ' + img;
    }

    if (imgReady(img)) {
        done(img);
        return always();
    }

    if (attempts <= 0) {
        fail('Max number of load attempts reached for ' + img.src);
        return always();
    }

    // call recursive until loaded or max attempts is reached
    setTimeout(function() {
        loadImgRecursive(img, done, fail, always, attempts - 1);
    }, 250);
}



/**
Allows to load a single image. One may pass a object of options as argument
    to specify parameters like a success and failure handler or the max number
    of attempts to load the image.

@method loadImage
@for Utils.Loader
@param {object} options Configuration object
@param {string} options.url URL of image to load
@param {function} [options.loaded] Function to call on success
@param {function} [options.failed] Function to call on failure
@param {function} [options.always] Function to call regardless if success or failure
@param {number} [options.cycles = 100] Maximum number of attempts to load

@example
    import loadImage from './utils/loader';
    
    loadImage({
        url: 'path/to/image.jpg',
        loaded: function (img) {
            // success, img is the <img> node
        },
        failed: function (errorMsg) {
            // process error message
        },
        always: function () {
           // executed in any case (success or failure)
        }
    });

**/
const loadImage = function loadImage (options) {
    var _img = isImgFile(options.url) ? document.createElement('img') : null,
        _opts = objects.extend({}, options);

    if (!_img) {
        throw 'Utils.loadImage(:options) expects to find URL in options but found none';
    }

    if (!type.isFunction(_opts.loaded)) {
        _opts.loaded = function () {};
    }

    if (!type.isFunction(_opts.failed)) {
        _opts.failed = function () {};
    }

    if (!type.isFunction(_opts.always)) {
        _opts.always = function () {};
    }

    if (!type.isNumber(_opts.cycles)) {
        _opts.cycles = 100;
    }

    _img.alt = '';
    _img.src = _opts.url;
    loadImgRecursive(
        _img,
        _opts.loaded,
        _opts.failed,
        _opts.always,
        _opts.cycles
    );
}



export default loadImage;