sebastian-software/core

View on GitHub
source/class/jasy/Asset.js

Summary

Maintainability
A
0 mins
Test Coverage
/*
==================================================================================================
  Core - JavaScript Foundation
  Copyright 2010-2012 Zynga Inc.
  Copyright 2012-2014 Sebastian Werner
==================================================================================================
*/

"use strict";

(function()
{
    var root = jasy.Env.getValue("jasy.url") + jasy.Env.getValue("jasy.folder.asset") + "/";

    // Internal data storage
    var assets = {};
    var sprites = {};

    /** {Map} Expands internal type names to user readable ones */
    var typeExpansion =
    {
        i: "image",
        a: "audio",
        v: "video",
        f: "font",
        t: "text",
        b: "binary",
        o: "other"
    };


    /**
     * {Array} Resolves the given @id {String} into the stored entry of the asset data base.
     */
    var resolve = function(id)
    {
        if (id.constructor == Object) {
            return id;
        }

        if (jasy.Env.isSet("debug")) {
            core.Assert.isType(id, "String");
        }

        // Support placeholders for environment variables
        if (id.indexOf("{{") !== -1)
        {
            id = id.replace(/{{([a-zA-Z0-9]+)}}/g, function(match, field) {
                return jasy.Env.getValue(field);
            });
        }

        var splits = id.split("/");
        var current = assets;
        for (var i=0, l=splits.length; current && i<l; i++) {
            current = current[splits[i]];
        }

        return current || null;
    };


    /**
     * {String} Returns the URI for the given @entry {Map} (as returned by #resolve) and @id {String}.
     */
    var entryToUri = function(entry, id)
    {
        if (jasy.Env.isSet("debug"))
        {
            core.Assert.isType(id, "String", "Unknown asset ID: " + id);
            core.Assert.isType(entry, "Map", "Invalid entry: " + entry + " for asset ID: " + id);
        }

        // Support placeholders for environment variables
        if (id.indexOf("{{") !== -1)
        {
            id = id.replace(/{{([a-zA-Z0-9]+)}}/g, function(match, field) {
                return jasy.Env.getValue(field);
            });
        }

        // Support for hashed file name
        if (entry.h)
        {
            var extension = id.slice(id.lastIndexOf("."));
            var uri = root + entry.h + extension;
        }

        // Using custom URL (source mode) [1] or just append file ID to URL [2]
        // [1] is typically used during development for references to source files
        // [2] is typically used for basic build while keeping asset structure (non hashed copying)
        else
        {
            var uri = root + (entry.u || id);
        }

        return uri;
    };


    /**
     * Merged two data maps @src {Map} and @dst {Map} recursively by using as much of
     * the original data as possible (no copying). Will never override existing values!
     */
    var mergeData = function(src, dst)
    {
        for (var key in src)
        {
            var srcValue = src[key];
            var dstValue = dst[key];

            // Just use value from source (works for folders and files)
            if (dstValue == null) {
                dst[key] = srcValue;
            }

            // Deep merge
            else if (srcValue.constructor === Object && dstValue.constructor === Object) {
                mergeData(srcValue, dstValue);
            }
        }
    };


    /**
     * Jasy interface to asset API.
     */
    core.Module("jasy.Asset",
    {
        resolve : resolve,
        entryToUri : entryToUri,

        /**
         * {String} Returns the sprite ID for the given data @spriteNumber {Integer} and image
         * @assetId {String}.
         */
        resolveSprite : function(spriteNumber, assetId)
        {
            if (jasy.Env.isSet("debug"))
            {
                core.Assert.isType(spriteNumber, "Number");
                core.Assert.isType(assetId, "String");
            }

            // Sprite data format: index, left, top
            var spriteId = sprites[spriteNumber];

            // Explicit root path
            if (spriteId.charAt(0) == "/") {
                spriteId = spriteId.slice(1);
            }

            // Local path (same folder as requested image)
            else if (spriteId.indexOf("/") == -1)
            {
                var pos = assetId.lastIndexOf("/");
                if (pos != -1) {
                    spriteId = assetId.slice(0, pos+1) + spriteId;
                }
            }

            return spriteId;
        },


        /**
         * Adds the given asset @data {Map}. This is typically generated and called by Jasy.
         */
        addData : function(data)
        {
            // Validate input data
            if (jasy.Env.isSet("debug"))
            {
                core.Assert.isType(data, "Map", "Asset data must be a map.");

                if ("assets" in data) {
                    core.Assert.isType(data.assets, "Map", "Asset data must define a structure of assets under the assets keys.");
                }

                if ("sprites" in data) {
                    core.Assert.isType(data.sprites, "Array", "Sprite data inside assets must be delivered as an Array.");
                }
            }

            // Inject data
            mergeData(data.assets, assets);
            mergeData(data.sprites, sprites);
        },


        /**
         * Resets the internal state of the asset class.
         */
        resetData : function()
        {
            assets = {};
            sprites = {};
        },


        /**
         * {Boolean} Whether the registry has information about the given asset @id {String}.
         */
        has : function(id)
        {
            if (jasy.Env.isSet("debug")) {
                core.Assert.isType(id, "String");
            }

            return !!(resolve(id));
        },


        /**
         * {String} Returns the type of the given asset @id {String}. One of
         * `image`, `audio`, `video`, `font`, `text`, `binary`, `other`.
         */
        getType : function(id)
        {
            if (jasy.Env.isSet("debug")) {
                core.Assert.isType(id, "String", "Invalid asset ID (no string): " + id + "!");
            }

            var entry = resolve(id);
            if (jasy.Env.isSet("debug") && !entry) {
                throw new Error("Could not figure out size of unknown image: " + id);
            }

            return typeExpansion[entry.t] || "other";
        },


        /**
         * {String} Returns the URI for the given asset @id {String}
         */
        toUri : function(id)
        {
            if (jasy.Env.isSet("debug")) {
                core.Assert.isType(id, "String");
            }

            var resolved = resolve(id);
            if (jasy.Env.isSet("debug")) {
                core.Assert.isNotNull(resolved, "Failed to resolve asset ID: " + id);
            }

            return entryToUri(resolved, id);
        }
    });

})();