PHP Classes

File: src/js/Importer.js

Recommend this page to a friend!
  Classes of Nikos M.  >  Importer  >  src/js/Importer.js  >  Download  
File: src/js/Importer.js
Role: Auxiliary data
Content type: text/plain
Description: Auxiliary data
Class: Importer
Load classes, images, CSS and JavaScript
Author: By
Last change: v.1.1.5

* fix js load(class) when fewer arguments are provided
* in browser script assets ensure execution order
* various edits
Date: 1 year ago
Size: 64,010 bytes
 

Contents

Class file image Download
/**
*  Importer
*  a simple loader manager for classes and assets with dependencies for PHP, Python, Javascript
*
*  @version 1.1.5
*  https://github.com/foo123/Importer
**/
!function(root, name, factory){
"use strict";
if (('undefined'!==typeof Components)&&('object'===typeof Components.classes)&&('object'===typeof Components.classesByID)&&Components.utils&&('function'===typeof Components.utils['import'])) /* XPCOM */
    (root.$deps = root.$deps||{}) && (root.EXPORTED_SYMBOLS = [name]) && (root[name] = root.$deps[name] = factory.call(root));
else if (('object'===typeof module)&&module.exports) /* CommonJS */
    (module.$deps = module.$deps||{}) && (module.exports = module.$deps[name] = factory.call(root));
else if (('function'===typeof define)&&define.amd&&('function'===typeof require)&&('function'===typeof require.specified)&&require.specified(name) /*&& !require.defined(name)*/) /* AMD */
    define(name,['module'],function(module){factory.moduleUri = module.uri; return factory.call(root);});
else if (!(name in root)) /* Browser/WebWorker/.. */
    (root[name] = factory.call(root)||1)&&('function'===typeof(define))&&define.amd&&define(function(){return root[name];});
}(  /* current root */          'undefined' !== typeof self ? self : this,
    /* module name */           "Importer",
    /* module factory */        function ModuleFactory__Importer(undef){
"use strict";

var PROTO = 'prototype', HAS = Object[PROTO].hasOwnProperty, ATTR = 'setAttribute', LOWER = 'toLowerCase',
    toString = Object[PROTO].toString, map = Array[PROTO].map, KEYS = Object.keys,
    startsWith = String[PROTO].startsWith
            ? function(s, pre, pos){return s.startsWith(pre, pos||0);}
            : function(s, pre, pos){pos=pos||0; return pre === s.substr(pos, pre.length+pos);},
    NOP = function() {},

    isXPCOM = ('undefined' !== typeof Components) && ('object' === typeof Components.classes) && ('object' === typeof Components.classesByID) && Components.utils && ('function' === typeof Components.utils['import']),
    isNode = !isXPCOM && ('undefined' !== typeof global) && ('[object global]' === toString.call(global)),
    isWebWorker = !isXPCOM && !isNode && ('undefined' !== typeof WorkerGlobalScope) && ('function' === typeof importScripts) && (navigator instanceof WorkerNavigator),
    isBrowser = !isXPCOM && !isNode && !isWebWorker && ('undefined' !== typeof navigator), isClientSide = isBrowser || isWebWorker,
    isAMD = ('function' === typeof define) && define.amd && ('function' === typeof require),
    Cu = isXPCOM ? Components.utils : null,
    Cc = isXPCOM ? Components.classes : null,
    Ci = isXPCOM ? Components.interfaces : null
;

if (isXPCOM)
{
    // do some necessary imports
    Cu['import']('resource://gre/modules/NetUtil.jsm');
    Cu['import']('resource://gre/modules/osfile.jsm');
}

var Scope = isXPCOM ? this : (isNode ? global : (isWebWorker ? this : window)),

    fs = isNode ? require('fs') : null,
    import_module = isXPCOM
    ? function import_module(name, path, scope) {
        Cu['import'](path, scope);
        return scope[name];
    }
    : (isNode
    ? function import_module(name, path, scope) {
        return require(path);
    }
    : (isWebWorker
    ? function import_module(name, path, scope) {
        importScripts(path);
        return scope[name];
    }
    : NOP)),
    XHR = function() {
    return window.XMLHttpRequest
        // code for IE7+, Firefox, Chrome, Opera, Safari
        ? new XMLHttpRequest( )
        // code for IE6, IE5
        : new ActiveXObject('Microsoft.XMLHTTP') // or ActiveXObject("Msxml2.XMLHTTP"); ??
    ;
    },

    DS_RE = /\/|\\/g, PROTOCOL = '://', PROTOCOL_RE = '#PROTOCOL#', ID_RE = /[\-.\/\\:]+/g,
    DS = isXPCOM
    ? (function path_separator() {
        // http://stackoverflow.com/a/7092596/3591273
        var profil_dir = Cc['@mozilla.org/file/directory_service;1'].getService(Ci.nsIProperties).get('ProfD',Ci.nsIFile);
        profil_dir.append('abc'); profil_dir.append('abc');
        return profil_dir.path.substr(profil_dir.path.length-('abc'.length)-1,1);
    })( )
    : (isNode
    ? require('path').sep /* https://nodejs.org/api/path.html#path_path_sep */
    : '/'),

    fileurl_2_nsfile = function(file_uri) {
        // NetUtil.newURI(file_uri).QueryInterface(Ci.nsIFileURL).file
        // http://stackoverflow.com/q/24817347/3591273
        /*var ios = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService),
            url = ios.newURI(file_uri, null, null), // url is a nsIURI
            // file is a nsIFile
            file = url.QueryInterface(Ci.nsIFileURL).file;*/
        return Cc['@mozilla.org/network/io-service;1'].getService(Ci.nsIIOService).newURI(file_uri, null, null).QueryInterface(Ci.nsIFileURL).file;
    },

    read_file = isXPCOM
    ? function read_file(path, enc, defval) {
        var data, file, stream, len;
        // https://developer.mozilla.org/en-US/Add-ons/Code_snippets/File_I_O
        file = fileurl_2_nsfile(path);
        stream = Cc['@mozilla.org/network/file-input-stream;1'].createInstance(Ci.nsIFileInputStream);
        if ('binary' === enc)
        {
            var bstream = Cc['@mozilla.org/binaryinputstream;1'].createInstance(Ci.nsIBinaryInputStream);
            stream.init(file, -1, -1, false);
            len = stream.available( );
            bstream.setInputStream( stream );
            bstream.readByteArray( len, data = new Uint8Array( len ) );
            bstream.close( );
        }
        else
        {
            var cstream = Cc['@mozilla.org/intl/converter-input-stream;1'].createInstance(Ci.nsIConverterInputStream),
                str = {value:''}, read = 0;
            data = null;
            stream.init(file, -1, 0, 0); cstream.init(stream, enc, 0, 0);
            do {
                // read as much as we can and put it in str.value
                read = cstream.readString(0xffffffff, str);
                if ( null === data ) data = '';
                data += str.value;
            } while (0 != read);
            cstream.close(); // this closes stream
            if (null === data) data = null != defval ? defval : '';
        }
        return data;
    }
    : (isNode
    ? function read_file(path, enc, defval) {
        var data = fs.readFileSync(path, 'binary' === enc ? {} : {encoding:enc});
        if (!data) return 'binary' === enc ? (null != defval ? defval : null) : (null != defval ? defval : '');
        return data;
    }
    : function read_file(path, enc, defval) {
        var xhr = XHR();

        // plain text with enc encoding format
        xhr.open('GET', path, false);  // 'false' makes the request synchronous
        if ('binary' === enc)
        {
            // http://stackoverflow.com/questions/9855127/setting-xmlhttprequest-responsetype-forbidden-all-of-a-sudden
            if (isWebWorker) xhr.responseType = 'arraybuffer';
        }
        else
        {
            // http://stackoverflow.com/questions/9855127/setting-xmlhttprequest-responsetype-forbidden-all-of-a-sudden
            if (isWebWorker) xhr.responseType = 'text';
            xhr.setRequestHeader('Content-Type', 'text/plain; charset='+enc+'');
            xhr.overrideMimeType('text/plain; charset='+enc+'');
        }
        xhr.send(null);
        if (200 === xhr.status)
            return 'binary' === enc ? xhr.response : xhr.responseText;
        else
            return 'binary' === enc ? (null != defval ? defval : null) : (null != defval ? defval : '');
    }),
    read_file_async = isXPCOM
    ? function read_file_async(path, enc, cb, defval) {
        // https://developer.mozilla.org/en-US/Add-ons/Code_snippets/File_I_O
        NetUtil.asyncFetch(fileurl_2_nsfile(path), function(stream, status) {
            var data = null;
            if (Components.isSuccessCode(status))
            {
                if ('binary' === enc)
                {
                    var bstream = Cc['@mozilla.org/binaryinputstream;1'].createInstance(Ci.nsIBinaryInputStream),
                        len = stream.available();
                    bstream.setInputStream(stream);
                    bstream.readByteArray(len, data = new Uint8Array(len));
                    bstream.close();
                }
                else
                {
                    data = NetUtil.readInputStreamToString(stream, stream.available(), {charset:enc});
                }
            }
            else
            {
                data = 'binary' === enc ? (null != defval ? defval : null) : (null != defval ? defval : '');
            }
            if (cb) cb(data);
        });
        return '';
    }
    : (isNode
    ? function read_file_async(path, enc, cb, defval) {
        if ('binary' === enc)
        {
            fs.readFile(path, function(err, data) {
                if (cb) cb(!!err ? (null != defval ? defval : null) : data);
            });
        }
        else
        {
            fs.readFile(path, {encoding:enc}, function(err, text) {
                if (cb) cb(!!err ? (null != defval ? defval : '') : text);
            });
        }
        return '';
    }
    : function read_file_async(path, enc, cb, defval) {
        var xhr = XHR();

        // plain text with enc encoding format
        xhr.open('GET', path, true);  // 'true' makes the request asynchronous
        if ('binary' === enc)
        {
            xhr.responseType = 'arraybuffer';
            xhr.onload = function() {
                if (cb) cb(200 === xhr.status ? xhr.response : (null != defval ? defval : null));
            };
        }
        else
        {
            xhr.responseType = 'text';
            xhr.setRequestHeader('Content-Type', 'text/plain; charset='+enc+'');
            xhr.overrideMimeType('text/plain; charset='+enc+'');
            xhr.onload = function() {
                if (cb) cb(200 === xhr.status ? xhr.responseText : (null != defval ? defval : ''));
            };
        }
        xhr.send(null);
        return '';
    }),

    Importer
;

// load javascript(s)/text(s) (a)sync in node, browser, webworker, xpcom/sdk module
function load_deps(importer, scope, cache, ref, complete)
{
    var dl = ref.length, i, t, cached,
        head, load, next, loaded = new Array(dl);
    // xpcom module / nodejs, require / webworker, importScripts
    if (isXPCOM || isNode || isWebWorker)
    {
        for (i=0; i<dl; i++)
        {
            if (HAS.call(ref[i],'loaded'))
            {
                loaded[i] = ref[i].loaded;
                // hook here
                importer.trigger('import-class', [
                    //          this,     id,        classname,   path,        reference
                    importer, ref[i].id, ref[i].name, ref[i].path, loaded[ i ]
                ], ref[i].ctx).trigger('import-class-'+ref[i].id, [
                    //          this,     id,        classname,   path,        reference
                    importer, ref[i].id, ref[i].name, ref[i].path, loaded[ i ]
                ], ref[i].ctx);
            }
            else if (HAS.call(cache,ref[i].ctx+'--'+ref[ i ].cache_id))
            {
                loaded[i] = cache[ref[i].ctx+'--'+ref[ i ].cache_id];
            }
            else if ('class' !== ref[ i ].type)
            {
                loaded[i] = cache[ref[i].ctx+'--'+ref[ i ].cache_id ] = read_file( ref[ i ].path, isXPCOM ? 'UTF-8' : 'utf8');
            }
            else if (ref[ i ].name in scope)
            {
                loaded[i] = scope[ref[ i ].name];
            }
            else
            {
                loaded[i] = import_module(ref[ i ].name, ref[ i ].path, scope) || null;
                // hook here
                importer.trigger('import-class', [
                    //          this,     id,        classname,   path,        reference
                    importer, ref[i].id, ref[i].name, ref[i].path, loaded[ i ]
                ], ref[i].ctx).trigger('import-class-'+ref[i].id, [
                    //          this,     id,        classname,   path,        reference
                    importer, ref[i].id, ref[i].name, ref[i].path, loaded[ i ]
                ], ref[i].ctx);
            }
        }
        return complete.apply(scope, loaded);
    }
    // browser, <script> tags
    else
    {
        head = $$tag('head', 0);
        t = 0; i = 0;
        load = function load(id, ctx, type, path, next) {
            var done, script;
            if ('style' === type || 'script' === type)
            {
                if ((script = $$(id)) && type === script.tagName[LOWER]())
                {
                    next();
                }
                else
                {
                    read_file_async(path, 'utf8', function(data) {
                        cache[ ctx+'--'+id ]  = data;
                        $$asset(type, data)[ATTR]('id', id);
                        next();
                    });
                }
            }
            else if ('class' !== type)
            {
                if ('template' === type && (script = $$(id)) && 'script' === script.tagName[LOWER]())
                {
                    next();
                }
                else
                {
                    read_file_async(path, 'utf8', function(data) {
                        cache[ ctx+'--'+id ]  = data;
                        if ('template' === type && !$$(id))
                            $$asset('tpl', data)[ATTR]('id', id);
                        next();
                    });
                }
            }
            else
            {
                if ((script = $$(id)) && 'script' === script.tagName[LOWER]())
                {
                    next();
                }
                else
                {
                    done = 0;
                    script = $$el('script');
                    script[ATTR]('id', id);
                    script[ATTR]('type', 'text/javascript');
                    script.onload = script.onreadystatechange = function() {
                        if (!done && (!script.readyState || 'loaded' == script.readyState  || 'complete' == script.readyState))
                        {
                            done = 1;
                            script.onload = script.onreadystatechange = null;
                            next();
                        }
                    }
                    // load it
                    //script.src = path;
                    script[ATTR]('src', path);
                    head.appendChild(script);
                }
            }
        };
        next = function next() {
            var cached;
            if (HAS.call(ref[i],'loaded') || (cached=HAS.call(cache,ref[ i ].ctx+'--'+ref[ i ].cache_id)) || (ref[ i ].name in scope))
            {
                loaded[i] = (HAS.call(ref[i],'loaded') ? ref[i].loaded : (cached ? cache[ ref[ i ].ctx+'--'+ref[ i ].cache_id ] : scope[ ref[ i ].name ])) || null;

                // hook here
                importer.trigger('import-class', [
                    //          this,     id,        classname,   path,        reference
                    importer, ref[i].id, ref[i].name, ref[i].path, loaded[ i ]
                ], ref[ i ].ctx).trigger('import-class-'+ref[i].id, [
                    //          this,     id,        classname,   path,        reference
                    importer, ref[i].id, ref[i].name, ref[i].path, loaded[ i ]
                ], ref[ i ].ctx);

                if (++i >= dl)
                {
                    complete.apply(scope, loaded);
                }
                else if (HAS.call(ref[i],'loaded') || (cached=HAS.call(cache,ref[ i ].ctx+'--'+ref[ i ].cache_id)) || (ref[ i ].name in scope))
                {
                    loaded[i] = (HAS.call(ref[i],'loaded') ? ref[i].loaded : (cached ? cache[ ref[ i ].ctx+'--'+ref[ i ].cache_id ] : scope[ ref[ i ].name ])) || null;
                    next();
                }
                else
                {
                    scope[ref[ i ].name] = null;
                    load(ref[ i ].cache_id, ref[ i ].ctx, ref[ i ].type, ref[ i ].path, next);
                }
            }
            else if (++t < 4)
            {
                setTimeout(next, 20);
            }
            else
            {
                t = 0;
                scope[ref[ i ].name] = null;
                // hook here
                importer.trigger('import-class', [
                    //          this,     id,        classname,   path,        reference
                    importer, ref[i].id, ref[i].name, ref[i].path, null
                ], ref[ i ].ctx).trigger('import-class-'+ref[i].id, [
                    //          this,     id,        classname,   path,        reference
                    importer, ref[i].id, ref[i].name, ref[i].path, null
                ], ref[ i ].ctx);
                i++; next();
            }
        };
        while (i < dl && (HAS.call(ref[i],'loaded') || (cached=HAS.call(cache,ref[ i ].ctx+'--'+ref[ i ].cache_id)) || (ref[ i ].name in scope)))
        {
            loaded[i] = (HAS.call(ref[i],'loaded') ? ref[i].loaded : (cached ? cache[ ref[ i ].ctx+'--'+ref[ i ].cache_id ] : scope[ ref[ i ].name ])) || null;
            i++;
        }
        if (i < dl) load(ref[ i ].cache_id, ref[ i ].ctx, ref[ i ].type, ref[ i ].path, next);
        else complete.apply(scope, loaded);
    }
}
// load script assets in browser while ensuring execution order, ie wait using callbacks
function load_scripts(importer, ref, complete, suffix)
{
    var head = $$tag('head', 0), next_deps, load;
    suffix = suffix || '';
    load = function load(ref, next) {
        if (!ref) return next();
        var done, script, ID, i, dl, next_compo;
        if ('scripts-composite' === ref.type)
        {
            ref.asset = array(ref.asset);
            i = 0; dl = ref.asset.length;
            next_compo = function next_compo() {
                if (++i >= dl) next();
                else load_scripts(importer, {id:ref.id, type:'scripts', asset:ref.asset[i], atts:ref.atts, ctx:ref.ctx}, next_compo, '-part-'+i);
            };
            if (dl) load_scripts(importer, {id:ref.id, type:'scripts', asset:ref.asset[i], atts:ref.atts, ctx:ref.ctx}, next_compo, '-part-'+i);
            else next();
        }
        else if ('scripts' === ref.type)
        {
            if (is_array(ref.asset))
            {
                ID = 'importer-inline-script-' + ref.id.replace(ID_RE, '_') + suffix;
                if ((script = $$(ID)) && ('script' === script.tagName[LOWER]()))
                {
                    next();
                }
                else
                {
                    attributes(ref.atts, script = $$el('script'));
                    script[ATTR]('type', 'text/javascript');
                    script[ATTR]('id', ID);
                    script.appendChild(document.createTextNode('/*<![CDATA[*/ '+ref.asset[0]+' /*]]>*/'));
                    head.appendChild(script);
                    importer.trigger('import-asset', [
                        // importer, id,      type,   asset
                        importer, ref.id, ref.type, ref.asset, {}
                    ], ref.ctx).trigger('import-asset-'+ref.id, [
                        // importer, id,      type,   asset
                        importer, ref.id, ref.type, ref.asset, {}
                    ], ref.ctx);
                    next();
                }
            }
            else
            {
                ID = 'importer-script-' + ref.id.replace(ID_RE, '_') + suffix;
                if ((script = $$(ID)) && ('script' === script.tagName[LOWER]()))
                {
                    next();
                }
                else
                {
                    done = 0;
                    attributes(ref.atts, script = $$el('script'));
                    script[ATTR]('type', 'text/javascript');
                    script[ATTR]('id', ID);
                    script.onload = script.onreadystatechange = function() {
                        if (!done && (!script.readyState || 'loaded' == script.readyState  || 'complete' == script.readyState))
                        {
                            done = 1;
                            script.onload = script.onreadystatechange = null;
                            importer.trigger('import-asset', [
                                // importer, id,      type,   asset
                                importer, ref.id, ref.type, ref.asset, {}
                            ], ref.ctx).trigger('import-asset-'+ref.id, [
                                // importer, id,      type,   asset
                                importer, ref.id, ref.type, ref.asset, {}
                            ], ref.ctx);
                            next();
                        }
                    }
                    // load it
                    script[ATTR]('src', importer.path_url(ref.asset));
                    head.appendChild(script);
                }
            }
        }
    };
    if (ref && ref.deps && ref.deps.length)
    {
        var dl = ref.deps.length, i = 0;
        next_deps = function next_deps() {
            if (++i >= dl) load(ref, complete);
            else load_scripts(importer, ref.deps[i], next_deps);
        }
        load_scripts(importer, ref.deps[0], next_deps);
    }
    else
    {
        load(ref, complete);
    }
}

function is_callable(o)
{
    return 'function' === typeof o;
}
function is_string(o)
{
    return o instanceof String || '[object String]' === toString.call(o);
}
function is_array(o)
{
    return o instanceof Array || '[object Array]' === toString.call(o);
}
function is_obj(o)
{
    return o instanceof Object || '[object Object]' === toString.call(o);
}
function empty(o)
{
    if (!o) return true;
    var to_string = toString.call(o);
    return (o instanceof Array || o instanceof String || '[object Array]' === to_string || '[object String]' === to_string) && !o.length;
}
function array(o)
{
    return is_array(o) ? o : [o];
}
function merge(o1, o2)
{
    var k = KEYS(o2), i, l;
    for (i=0,l=k.length; i<l; i++) o1[k[i]] = o2[k[i]];
    return o1;
}
function attributes(atts, node)
{
    if (!atts) return node ? node : '';
    var k = KEYS(atts), i, l;
    if (node)
    {
        for (i=0,l=k.length; i<l; i++) node[ATTR](k[i], true === atts[k[i]] ? k[i] : atts[k[i]]);
        return node;
    }
    else
    {
        var out = [];
        for (i=0,l=k.length; i<l; i++) out.push(k[i]+(true === atts[k[i]] ? '' : '="'+atts[k[i]]+'"'));
        return out.join(' ');
    }
}
function $$(id)
{
    return document.getElementById(id);
}
function $$el(element)
{
    return document.createElement(element);
}
function $$tag(tag, index)
{
    var els = document.getElementsByTagName(tag);
    return arguments.length > 1 ? (index < 0 ? els[els.length+index] : els[index]) : els;
}

// http://davidwalsh.name/add-rules-stylesheets
function $$css(style, css)
{
    var css_type = typeof css, n, index, declaration, selector, rules;

    // css rules object
    if ('object' === css_type)
    {
        index = 0;
        for (n in css)
        {
            if (!HAS.call(css,n)) continue;
            declaration = css[n];
            selector = declaration.selector;
            rules = [].concat(declaration.rules).join('; ');
            if ('insertRule' in style.sheet)
            {
                style.sheet.insertRule(selector + '{' + rules + '}', index);
                declaration.css = style.sheet.cssRules[index];
            }
            else if ('addRule' in style.sheet)
            {
                style.sheet.addRule(selector, rules, index);
                declaration.css = style.sheet.rules[index];
            }
            index++;
        }
    }
    // css literal string
    else if ('string' === css_type)
    {
        if (style.styleSheet) style.styleSheet.cssText = (style.styleSheet.cssText||'') + css;
        else style.appendChild(document.createTextNode(css));
    }
    return css;
}

function $$asset(type, src, unique, atts)
{
    var asset = null, link = null, i, links, wrapper;
    if ('html' === type)
    {
        wrapper = $$el('div');
        wrapper.innerHTML = src;
        while (wrapper.firstChild)
        {
            if ("SCRIPT" === asset.firstChild.nodeName ||
                "STYLE" === asset.firstChild.nodeName ||
                "LINK" === asset.firstChild.nodeName) asset = wrapper.firstChild;
            document.head.appendChild(wrapper.firstChild);
        }
        return asset;
    }
    switch(type)
    {
        // external tpl
        case 'tpl-link':
        // literal tpl
        case 'tpl':
            // Create the <script> tag
            asset = $$el('script');
            if (atts)
            {
                attributes(atts, asset);
            }
            else
            {
                asset[ATTR]('type', 'text/x-template');
            }
            // WebKit hack :(
            asset.appendChild(document.createTextNode(src));
            // Add the <script> element to the page
            document.head.appendChild(asset);
            break;

        // external script
        case 'script-link':
            if (unique)
            {
                // external script, only if not exists
                links = $$tag('script');
                for (i=links.length-1; i>=0; i--)
                {
                    if (links[i].src && src === links[i].src)
                    {
                        // found existing link
                        link = links[ i ];
                        break;
                    }
                }
            }
            if (link)
            {
                // return it, instead
                asset = link;
            }
            else
            {
                // Create the <script> tag
                asset = $$el('script');
                if (atts)
                {
                    attributes(atts, asset);
                }
                else
                {
                    asset[ATTR]('type', 'text/javascript');
                }
                asset[ATTR]('src', src);
                // Add the <script> element to the page
                document.head.appendChild(asset);
            }
            break;

        // literal script
        case 'script':
            // Create the <script> tag
            asset = $$el('script');
            if (atts)
            {
                attributes(atts, asset);
            }
            else
            {
                asset[ATTR]('type', 'text/javascript');
            }
            // WebKit hack :(
            asset.appendChild(document.createTextNode(src));
            // Add the <script> element to the page
            document.head.appendChild(asset);
            break;

        // external stylesheet
        case 'style-link':
            if (unique)
            {
                // external stylesheet, only if not exists
                links = $$tag('link');
                for (i=links.length-1; i>=0; i--)
                {
                    if (src === links[i].href)
                    {
                        // found existing link
                        link = links[ i ];
                        break;
                    }
                }
            }
            if (link)
            {
                // return it, instead
                asset = link;
            }
            else
            {
                // Create the <link> tag
                asset = $$el('link');
                asset[ATTR]('rel', 'stylesheet');
                if (atts)
                {
                    attributes(atts, asset);
                }
                else
                {
                    // Add a media (and/or media query) here if you'd like!
                    asset[ATTR]('type', 'text/css');
                    asset[ATTR]('media', 'all');
                }
                asset[ATTR]('href', src);
                // Add the <style> element to the page
                document.head.appendChild(asset);
            }
            break;

        // literal stylesheet
        case 'style':
        default:
            // Create the <style> tag
            asset = $$el('style');
            if (atts)
            {
                attributes(atts, asset);
            }
            else
            {
                // Add a media (and/or media query) here if you'd like!
                asset[ATTR]('type', 'text/css');
                asset[ATTR]('media', 'all');
            }
            // WebKit hack :(
            asset.appendChild(document.createTextNode(''));
            // Add the <style> element to the page
            document.head.appendChild(asset);
            if (src) $$css(asset, src);
            break;
    }
    return asset;
}

function dispose_asset(asset)
{
    if (asset && asset.parentNode)
        asset.parentNode.removeChild(asset);
}

function remove_protocol(p)
{
    return p.split(PROTOCOL).join(PROTOCOL_RE);
}

function add_protocol(p)
{
    return p.split(PROTOCOL_RE).join(PROTOCOL);
}

function path_join()
{
    var p, args = arguments, full = '.';
    if (!args.length) return full;
    if (isXPCOM)
    {
        full = OS.Path.join.apply(OS.Path, args);
    }
    else if (isNode)
    {
        p = require('path');
        full = p.join.apply( p, args );
    }
    /*else if ( isBrowser && !isWebWorker )
    {
        if ( !path_join.link ) path_join.link = document.createElement('a');
        path_join.link.href = slice.call( args ).join( '/' );
    }*/
    else
    {
        full = join_path.apply(null, args);
    }
    return full;
}
// adapted from https://github.com/JosephMoniz/php-path
function join_path()
{
    var args = arguments, argslen = args.length,
        ds = DS, path, plen,
        isAbsolute, trailingSlash, peices, new_path, up, i, last;

    if (!argslen)  return '.';

    // take care of protocol, if exists
    path = map.call(args, remove_protocol).join(ds);
    plen = path.length;

    if (!plen) return '.';

    isAbsolute    = path.charAt(0);
    trailingSlash = path.charAt(plen - 1);

    peices = path.split(DS_RE).filter(Boolean);

    new_path = [];
    up = 0;
    i = peices.length-1;
    while (i >= 0)
    {
        last = peices[ i ];
        if ('..' === last)
        {
            up++;
        }
        else if ('.' !== last)
        {
            if (up)  up--;
            else new_path.push(peices[i]);
        }
        i--;
    }

    path = new_path.reverse().join(ds);

    if (!path && !isAbsolute)
    {
        path = '.';
    }

    if (path && trailingSlash === ds)
    {
        path += ds;
    }

    return (isAbsolute === ds ? ds : '') + add_protocol(path);
}

function join_path_url()
{
    var _DS = DS, ret;
    DS = '/';
    ret = join_path.apply(null, arguments);
    DS = _DS;
    return ret;
}

Importer = function Importer(base, base_url) {
    var self = this;
    if (!(self instanceof Importer)) return new Importer(base, base_url);
    self.base = '';
    self.base_url = '';
    self.base_path(base, base_url);
    self._classmap = {'__global__':{}};
    self._classes = {'__global__':{}};
    self._assets = {'__global__':{}};
    self._hooks = {'__global__':{}};
    self._cache = {};
};

Importer.VERSION = '1.1.5';
Importer.BASE = './';
Importer.path_join = path_join;
Importer.join_path = join_path;
Importer.join_path_url = join_path_url;
Importer.attributes = attributes;

Importer[PROTO] = {
    constructor: Importer

    ,base: null
    ,base_url: null
    ,_classmap: null
    ,_classes: null
    ,_assets: null
    ,_hooks: null
    ,_cache: null

    ,dispose: function() {
        var self = this;
        self._classmap = null;
        self._classes = null;
        self._assets = null;
        self._hooks = null;
        self._cache = null;
        self.base = null;
        self.base_url = null;
        return self;
    }

    ,on: function(hook, handler, ctx, once) {
        var self = this;
        if (null == ctx) ctx = '__global__';
        if (ctx && !empty(hook) && is_callable(handler))
        {
            if (!HAS.call(self._hooks,ctx)) self._hooks[ctx] = {};
            if (!HAS.call(self._hooks[ctx],hook)) self._hooks[ctx][hook] = [];
            self._hooks[ctx][hook].push([handler, true === once, 0]);
        }
        return self;
    }

    ,one: function(hook, handler, ctx) {
        return this.on(hook, handler, ctx, true);
    }

    ,off: function(hook, handler, ctx) {
        var self = this, hooks, i;
        if (null == ctx) ctx = '__global__';
        if (ctx && HAS.call(self._hooks,ctx) && !empty(hook) && !empty(self._hooks[ctx][hook]))
        {
            if (true === handler)
            {
                delete(self._hooks[ctx][hook]);
            }
            else if (handler)
            {
                hooks = self._hooks[ctx][hook];
                for (i=hooks.length-1; i>=0; i--)
                {
                    if (handler === hooks[i][0])
                        hooks.splice(i, 1);
                }
            }
        }
        return self;
    }

    ,trigger: function(hook, args, ctx) {
        var self = this, hooks, i, h, ret;
        if (null == ctx) ctx = '__global__';
        if (ctx && HAS.call(self._hooks,ctx) && !empty(hook) && !empty(self._hooks[ctx][hook]))
        {
            hooks = self._hooks[ctx][hook];
            args = args || [];
            for (i=0; i<hooks.length; i++)
            {
                h = hooks[i];
                if (h[1] && h[2]) continue;
                h[2] = 1; // called;
                ret = h[0].apply(null, args);
                if (false === ret) break;
            }
            // remove called oneoffs
            for (i=hooks.length-1; i>=0; i--)
            {
                if (hooks[i][1] && hooks[i][2])
                    hooks.splice(i, 1);
            }
        }
        return self;
    }

    ,base_path: function(base, base_url) {
        var self = this;

        if (is_string(base) && base.length) self.base = base;
        else if (false === base) self.base = '';

        if (is_string(base_url) && base_url.length) self.base_url = base_url;
        else if (false === base_url) self.base_url = '';

        return self;
    }

    ,get_path: function(path, base, url) {
        var self = this;

        if (empty(path)) return base||'';

        else if (!empty(base) &&
            (startsWith(path, './') ||
                startsWith(path, '../') ||
                startsWith(path, '.\\') ||
                startsWith(path, '..\\'))
        )
            return true === url ? join_path_url(base, path) : join_path(base, path);

        else return path;
    }

    ,path: function(asset) {
        var self = this;
        return self.get_path(asset||'', isNode ? self.base : self.base_url);
    }

    ,path_url: function(asset) {
        var self = this;
        return self.get_path(asset||'', self.base_url, true);
    }

    ,register: function(what, defs, ctx) {
        var self = this, classes = self._classes, classmap = self._classmap, assets = self._assets,
            i, l, classname, def, id, path, deps, props, type, asset;
        if (null == ctx) ctx = '__global__';
        what = String(what).toLowerCase();
        if (ctx && is_array(defs) && defs.length)
        {
            if (!is_array(defs[0])) defs = [defs]; // make array of arrays

            if ('classes' === what)
            {
                for (i=0,l=defs.length; i<l; i++)
                {
                    def = defs[ i ];
                    /* 0:class, 1:id, 2:path, 3:deps */
                    classname = def[0]; id = def[1]; path = def[2]; deps = def[3] ? def[3] : [];
                    if (!empty(classname) && !empty(id) && !empty(path))
                    {
                        if (!HAS.call(classes,ctx)) classes[ctx] = {};
                        if (!HAS.call(classmap,ctx)) classmap[ctx] = {};
                        path = self.path(path);
                        classes[ctx][id] = [
                            /* 0:class, 1:id, 2:path, 3:deps, 4:loaded */
                            classname,
                            id,
                            path,
                            array(deps),
                            false
                        ];
                        classmap[ctx][classname] = [path, id];
                    }
                }
            }
            else if ('assets' === what)
            {
                for (i=0,l=defs.length; i<l; i++)
                {
                    def = defs[ i ];
                    /* 0:type, 1:id, 2:asset, 3:deps, 4:props */
                    type = def[0]; id = def[1]; asset = def[2]; deps = def[3] ? def[3] : [];
                    props = def[4] ? def[4] : {};
                    if (!empty(type) && !empty(id) && !empty(asset))
                    {
                        type = type[LOWER]( );
                        if ('scripts-composite' === type || 'styles-composite' === type || 'scripts-alt' === type || 'styles-alt' === type)
                        {
                            asset = array(asset);
                        }
                        // maybe literal asset
                        else if (is_string(asset))
                        {
                            asset = self.path_url(asset);
                        }
                        if (!HAS.call(assets,ctx)) assets[ctx] = {};
                        assets[ctx][ id ] = [
                            /* 0:type, 1:id, 2:asset, 3:deps, 4:props, 5:enqueued, 6:loaded */
                            type, id, asset, array(deps), props, false, false
                        ];
                    }
                }
            }
        }
        return self;
    }

    ,import_class: function(id, complete, ctx) {
        var self = this, queue, classes = self._classes,
            cache_id = 'class-'+id, cache = self._cache, exists,
            needs_deps, numdeps, i, dep, deps, to_load, ctx2, ctx3;

        if (null == ctx) ctx = '__global__';
        if (HAS.call(cache,ctx+'--'+cache_id))
        {
            if (is_callable(complete))
                complete.call(self, cache[ctx+'--'+cache_id]);
        }
        else
        {
            exists = false;
            to_load = [ ];
            queue = [ id ];
            while (queue.length)
            {
                id = queue[ 0 ];
                ctx2 = HAS.call(classes,ctx) && HAS.call(classes[ctx],id) ? ctx : '__global__';
                if (HAS.call(classes[ctx2],id) && !classes[ctx2][id][4])
                {
                    exists = true;
                    if (!HAS.call(Scope, classes[ctx2][id][0]))
                    {
                        deps = classes[ctx2][id][3];
                        if (!empty(deps))
                        {
                            needs_deps = false;
                            numdeps = deps.length;
                            for (i=numdeps-1; i>=0; i--)
                            {
                                dep = deps[i];
                                ctx3 = HAS.call(classes,ctx) && HAS.call(classes[ctx],dep) ? ctx : '__global__';
                                if (HAS.call(classes[ctx3],dep) && !classes[ctx3][dep][4])
                                {
                                    needs_deps = true;
                                    queue.unshift(dep);
                                }
                            }
                            if (needs_deps) continue;
                            else queue.shift();
                        }
                        else
                        {
                            queue.shift();
                        }
                        classes[ctx2][id][4] = true; // loaded
                        to_load.push({
                            id: id,
                            type: 'class',
                            cache_id: 'class-' + id,
                            name: classes[ctx2][id][0],
                            path: classes[ctx2][id][2],
                            ctx: ctx
                        });
                    }
                    else
                    {
                        queue.shift();
                        classes[ctx2][id][4] = true; // loaded
                        // trigger events, even if this class is already loaded somewhere else, but not this instance
                        to_load.push({
                            id: id,
                            type: 'class',
                            cache_id: 'class-' + id,
                            name: classes[ctx2][id][0],
                            path: classes[ctx2][id][2],
                            ctx: ctx,
                            loaded: Scope[ classes[ctx2][id][0] ]
                        });
                    }
                }
                else if (HAS.call(classes[ctx2],id))
                {
                    exists = true;
                    queue.shift();
                }
                else
                {
                    queue.shift();
                }
            }
            if (exists && to_load.length)
            {
                load_deps(self, Scope, cache, to_load, function() {
                    var i, l, args = arguments;
                    for (i=0,l=args.length; i<l; i++) cache[ ctx+'--'+to_load[ i ].cache_id ] = args[ i ];
                    if (is_callable(complete)) complete.call(self, cache[ctx+'--'+cache_id]);
                });
            }
            else if (is_callable(complete))
            {
                complete.call(self, null);
            }
        }
        return self;
    }

    ,import_asset: function(id, ctx) {
        var self = this, queue = [id], assets = self._assets, deps, props, atts,
            needs_deps, numdeps, i, dep, out = [], asset_def, type, asset, asset_id,
            is_style, is_script, is_tpl, is_composite, is_alt, is_inlined,
            pi, pl, document_asset, ret, ctx2, ctx3, import_script_assets, browser_scripts = [];
        if (null == ctx) ctx = '__global__';
        while (queue.length)
        {
            id = queue[0];
            ctx2 = HAS.call(assets,ctx) && HAS.call(assets[ctx],id) ? ctx : '__global__';
            if (HAS.call(assets[ctx2],id) && assets[ctx2][id][5] && !assets[ctx2][id][6]) // enqueued but not loaded yet
            {
                asset_def = assets[ctx2][id];
                type = asset_def[0];
                id = asset_def[1];
                asset = asset_def[2];
                deps = asset_def[3];
                props = asset_def[4];
                if (deps && deps.length)
                {
                    needs_deps = false;
                    numdeps = deps.length;
                    for (i=numdeps-1; i>=0; i--)
                    {
                        dep = deps[i];
                        ctx3 = HAS.call(assets,ctx) && HAS.call(assets[ctx],dep) ? ctx : '__global__';
                        if (HAS.call(assets[ctx3],dep) && !assets[ctx3][dep][6])
                        {
                            assets[ctx3][dep][5] = true; // enqueued
                            needs_deps = true;
                            queue.unshift(dep);
                        }
                    }
                    if (needs_deps) continue;
                    else queue.shift();
                }

                asset_def[6] = true; // loaded

                // hook here
                ret = {};
                self.trigger('import-asset', [
                    // importer, id,      type,   asset
                    self, id, type, asset, ret
                ], ctx).trigger('import-asset-'+id, [
                    // importer, id,      type,   asset
                    self, id, type, asset, ret
                ], ctx);

                if (null != ret['return'])
                {
                    out.push(ret['return']);
                }
                else
                {
                    is_style = 'styles' === type || 'styles-composite' === type;
                    is_script = 'scripts' === type || 'scripts-composite' === type;
                    is_tpl = 'templates' === type;
                    is_composite = 'scripts-composite' === type || 'styles-composite' === type;
                    is_alt = 'scripts-alt' === type || 'styles-alt' === type;
                    is_inlined = !is_composite && !is_alt && is_array(asset);
                    asset_id = id.replace(ID_RE, '_');
                    if (is_style)
                    {
                        atts = merge({
                            'type'  : 'text/css',
                            'media' : 'all'
                        }, props);

                        if (isBrowser)
                        {
                            if (is_inlined)
                            {
                                out.push(
                                document_asset = $$('importer-inline-style-'+asset_id) || $$asset('style', asset[0], false, atts)
                                );
                                document_asset[ATTR]('id', 'importer-inline-style-'+asset_id);
                            }
                            else if (is_composite)
                            {
                                for (pi=0,pl=asset.length; pi<pl; pi++)
                                {
                                    if (is_array(asset[pi]))
                                    {
                                        out.push(
                                        document_asset = $$('importer-inline-style-'+asset_id+'-part-'+pi) || $$asset('style', asset[pi][0], false, atts)
                                        );
                                        document_asset[ATTR]('id', 'importer-inline-style-'+asset_id+'-part-'+pi);
                                    }
                                    else
                                    {
                                        out.push(
                                        document_asset = $$('importer-style-'+asset_id+'-part-'+pi) || $$asset('style-link', self.path_url(asset[pi]), true, atts)
                                        );
                                        document_asset[ATTR]('id', 'importer-style-'+asset_id+'-part-'+pi);
                                    }
                                }
                            }
                            else if (is_alt)
                            {
                                out.push(
                                document_asset = $$('importer-style-'+asset_id) || $$asset('html', asset[0])
                                );
                                document_asset[ATTR]('id', 'importer-style-'+asset_id);
                            }
                            else
                            {
                                out.push(
                                document_asset = $$('importer-style-'+asset_id) || $$asset('style-link', self.path_url(asset), true, atts)
                                );
                                document_asset[ATTR]('id', 'importer-style-'+asset_id);
                            }
                        }
                        else
                        {
                            atts = attributes(atts);
                            if (is_inlined)
                            {
                                out.push(
                                '<style id="importer-inline-style-'+asset_id+'" '+atts+'>'+asset[0]+'</style>'
                                );
                            }
                            else if (is_composite)
                            {
                                for (pi=0,pl=asset.length; pi<pl; pi++)
                                {
                                    if (is_array(asset[pi]))
                                    {
                                        out.push(
                                        '<style id="importer-inline-style-'+asset_id+'-part-'+pi+'" '+atts+'>'+asset[pi][0]+'</style>'
                                        );
                                    }
                                    else
                                    {
                                        out.push(
                                        '<link id="importer-style-'+asset_id+'-part-'+pi+'" href="'+self.path_url(asset[pi])+'" rel="stylesheet" '+atts+' />'
                                        );
                                    }
                                }
                            }
                            else if (is_alt)
                            {
                                out.push(
                                asset[0]
                                );
                            }
                            else
                            {
                                out.push(
                                '<link id="importer-style-'+asset_id+'" href="'+self.path_url(asset)+'" rel="stylesheet" '+atts+' />'
                                );
                            }
                        }
                    }
                    else if (is_script)
                    {
                        atts = merge({
                            'type'  : 'text/javascript'
                        }, props);

                        if (isBrowser)
                        {
                            if (is_inlined)
                            {
                                browser_scripts.push(id);
                                /*out.push(
                                document_asset = $$('importer-inline-script-'+asset_id) || $$asset('script', '/*<![CDATA[* / '+asset[0]+' /*]]> /', false, atts)
                                );
                                document_asset[ATTR]('id', 'importer-inline-script-'+asset_id);*/
                            }
                            else if (is_composite)
                            {
                                browser_scripts.push(id);
                                /*for (pi=0,pl=asset.length; pi<pl; pi++)
                                {
                                    if (is_array(asset[pi]))
                                    {
                                        out.push(
                                        document_asset = $$('importer-inline-script-'+asset_id+'-part-'+pi) || $$asset('script', '/*<![CDATA[* / '+asset[pi][0]+' /*]]>* /', false, atts)
                                        );
                                        document_asset[ATTR]('id', 'importer-inline-script-'+asset_id+'-part-'+pi);
                                    }
                                    else
                                    {
                                        out.push(
                                        document_asset = $$('importer-script-'+asset_id+'-part-'+pi) || $$asset('script-link', self.path_url(asset[pi]), true, atts)
                                        );
                                        document_asset[ATTR]('id', 'importer-script-'+asset_id+'-part-'+pi);
                                    }
                                }*/
                            }
                            else if (is_alt)
                            {
                                out.push(
                                document_asset = $$('importer-script-'+asset_id) || $$asset('html', asset[0])
                                );
                                document_asset[ATTR]('id', 'importer-script-'+asset_id);
                            }
                            else
                            {
                                browser_scripts.push(id);
                                /*out.push(
                                document_asset = $$('importer-script-'+asset_id) || $$asset('script-link', self.path_url(asset), true, atts)
                                );
                                document_asset[ATTR]('id', 'importer-script-'+asset_id);*/
                            }
                        }
                        else
                        {
                            atts = attributes(atts);
                            if (is_inlined)
                            {
                                out.push(
                                '<script id="importer-inline-script-'+asset_id+'" '+atts+'>/*<![CDATA[*/ '+asset[0]+' /*]]>*/</script>'
                                );
                            }
                            else if (is_composite)
                            {
                                for (pi=0,pl=asset.length; pi<pl; pi++)
                                {
                                    if (is_array(asset[pi]))
                                    {
                                        out.push(
                                        '<script id="importer-inline-script-'+asset_id+'-part-'+pi+'" '+atts+'>/*<![CDATA[*/ '+asset[pi][0]+' /*]]>*/</script>'
                                        );
                                    }
                                    else
                                    {
                                        out.push(
                                        '<script id="importer-script-'+asset_id+'-part-'+pi+'" src="'+self.path_url(asset[pi])+'" '+atts+'></script>'
                                        );
                                    }
                                }
                            }
                            else if (is_alt)
                            {
                                out.push(
                                asset[0]
                                );
                            }
                            else
                            {
                                out.push(
                                '<script id="importer-script-'+asset_id+'" src="'+self.path_url(asset)+'" '+atts+'></script>'
                                );
                            }
                        }
                    }
                    else if (is_tpl)
                    {
                        atts = merge({
                            'type'  : 'text/x-template'
                        }, props);

                        if (isBrowser)
                        {
                            out.push(document_asset = is_inlined
                                ? $$('importer-inline-tpl-'+asset_id) || $$asset('tpl', asset[0], false, atts)
                                : $$('importer-inline-tpl-'+asset_id) || $$asset('tpl', self.get(asset), false, atts));
                            document_asset[ATTR]('id', is_inlined ? 'importer-inline-tpl-'+asset_id : 'importer-inline-tpl-'+asset_id);
                        }
                        else
                        {
                            atts = attributes(atts);
                            out.push(is_inlined
                                ? ('<script id="importer-inline-tpl-'+asset_id+'" '+atts+'>'+asset[0]+'</script>')
                                : ('<script id="importer-inline-tpl-'+asset_id+'" '+atts+'>'+self.get(asset)+'</script>')
                            );
                        }
                    }
                    else
                    {
                        out.push(is_inlined ? asset[0] : self.get(asset)) ;
                    }
                }
            }
            else
            {
                queue.shift();
            }
        }
        if (isBrowser && browser_scripts.length)
        {
            import_script_assets = function import_script_assets(id) {
                var dependencies = [], ctx2 = HAS.call(assets,ctx) && HAS.call(assets[ctx],id) ? ctx : '__global__';
                if (HAS.call(assets[ctx2],id) && assets[ctx2][id][5] && -1 < browser_scripts.indexOf(id)) // to be specially loaded
                {
                    var asset_def = assets[ctx2][id],
                        type = asset_def[0],
                        id = asset_def[1],
                        asset = asset_def[2],
                        deps = asset_def[3],
                        props = asset_def[4],
                        numdeps, dep, i, ctx3
                    ;
                    if (deps && deps.length)
                    {
                        numdeps = deps.length;
                        for (i=numdeps-1; i>=0; i--)
                        {
                            dep = deps[i];
                            ctx3 = HAS.call(assets,ctx) && HAS.call(assets[ctx],dep) ? ctx : '__global__';
                            if (HAS.call(assets[ctx3],dep) && -1 < browser_scripts.indexOf(dep))
                            {
                                assets[ctx3][dep][5] = true; // enqueued
                                dependencies.push(import_script_assets(dep));
                            }
                        }
                    }
                    asset_def[6] = true; // loaded
                    return {id:id, type:type, asset:asset, deps:dependencies, atts:props, ctx:ctx};
                }
                return null;
            };
            // any browser scripts to be loaded while ensuring execution order, ie use callbacks
            load_scripts(self, import_script_assets(browser_scripts[browser_scripts.length-1]), function(){});
        }
        return out;
    }

    ,assets: function(type, ctx) {
        var self = this, out, assets = self._assets, next,
            id, asset_def, i, l, to_load = [ ], type_composite, type_alt;
        if (!arguments.length) {type = 'scripts'; ctx='__global__';}
        if (null == ctx) ctx = '__global__';
        if (!ctx || !HAS.call(assets,ctx)) return '';
        type = type[LOWER]();
        type_composite = type + '-composite';
        type_alt = type + '-alt';
        for (id in assets[ctx])
        {
            if (!HAS.call(assets[ctx],id)) continue;
            asset_def = assets[ctx][id];
            if ((type === asset_def[0] || type_composite === asset_def[0] || type_alt === asset_def[0]) && asset_def[5] && !asset_def[6])
            {
                to_load.push(asset_def[1]);
            }
        }
        if (isBrowser)
        {
            for (i=0,l=to_load.length; i<l; i++)
                self.import_asset(to_load[i], ctx);
            out = '';
        }
        else //if ( isXPCOM || isNode || isWebWorker )
        {
            out = [ ];
            for (i=0,l=to_load.length; i<l; i++)
                out = out.concat(self.import_asset(to_load[i], ctx));
            out = out.join("\n");
        }
        return out;
    }

    ,enqueue: function(type, id, asset_def, ctx) {
        var self = this, assets = self._assets, ctx2, asset = null, deps = null, props = null;
        if (is_array(asset_def))
        {
            asset = asset_def[0] || null;
            deps = asset_def[1] || null;
            props = asset_def[2] || null;
        }
        else
        {
            ctx = asset_def;
        }
        if (null == ctx) ctx = '__global__';
        if (ctx && !empty(type) && !empty(id))
        {
            ctx2 = HAS.call(assets,ctx) && HAS.call(assets[ctx],id) ? ctx : '__global__';
            if (HAS.call(assets,ctx2) && HAS.call(assets[ctx2],id))
            {
                assets[ctx2][id][5] = true; // enqueued
                // hook here
                self.trigger('enqueue-asset', [
                    // importer, id,      type,   asset
                    self, id, type, assets[ctx2][id][2]
                ], ctx).trigger('enqueue-asset-'+id, [
                    // importer, id,      type,   asset
                    self, id, type, assets[ctx2][id][2]
                ], ctx);
            }
            else if (!empty(asset))
            {
                self.register('assets', [type, id, asset, deps, props], ctx);
                assets[ctx][id][5] = true; // enqueued
                // hook here
                self.trigger('enqueue-asset', [
                    // importer, id,      type,   asset
                    self, id, type, assets[ctx][id][2]
                ], ctx).trigger('enqueue-asset-'+id, [
                    // importer, id,      type,   asset
                    self, id, type, assets[ctx][id][2]
                ], ctx);
            }
        }
        return self;
    }

    ,get: function(path, opts, complete) {
        var self = this, encoding, file, default_value;
        opts = opts || {};
        default_value = HAS.call(opts,'default') ? opts['default'] : '';
        encoding = opts.encoding || (isXPCOM ? 'UTF-8' : 'utf8');
        if (!empty(opts.binary)) encoding = 'binary';
        complete = complete || opts.complete || (is_callable(opts) && opts);
        if (isBrowser)
        {
            file = self.path(path);
            return read_file_async(file, encoding, function(data) {
                if (is_callable(complete)) complete(data);
            }, default_value);
        }
        else
        {
            file = self.path(path);
            return is_callable(complete)
            ? read_file_async(file, encoding, complete, default_value)
            : read_file(file, encoding, default_value);
        }
    }

    ,load: function(classname, class_def, complete, ctx) {
        var self = this, argslen = arguments.length, l, c, i, loader, ctx2, path = null, deps = null;
        if (is_array(classname))
        {
            if (is_callable(class_def))
            {
                ctx = complete;
                complete = class_def;
            }
            else
            {
                ctx = class_def;
            }
            if (null == ctx) ctx = '__global__';
            l = classname.length; c = new Array(l); i = 0;
            loader = function loader(loaded) {
                if (arguments.length)
                {
                    c[ i ] = loaded || null;
                    i++;
                }
                if (i < l) self.import_class(classname[i],  loader, ctx);
                else if (is_callable(complete))
                {
                    complete.apply(self, c);
                }
            };
            loader();
        }
        else
        {
            if (is_callable(class_def))
            {
                ctx = complete;
                complete = class_def;
                class_def = null;
            }
            else if (is_array(class_def))
            {
                path = class_def[0] || null;
                deps = class_def[1] || null;
            }
            else if (2 === arguments.length)
            {
                ctx = class_def;
            }
            if (null == ctx) ctx = '__global__';
            if ((!HAS.call(self._classes,ctx) || !HAS.call(self._classes[ctx],classname)) && !HAS.call(self._classes['__global__'],classname) && !empty(path))
                self.register('classes', [classname, classname, self.path(path), deps], ctx);
            ctx2 = HAS.call(self._classes,ctx) && HAS.call(self._classes[ctx],classname) ? ctx : '__global__';
            if (HAS.call(self._classes[ctx2],classname) && !self._classes[ctx2][classname][4])
                self.import_class(classname, complete, ctx2);
            else if (is_callable(complete))
                complete.call(self, self._cache[ctx2+'--class-'+classname]||null);
        }
        return self;
    }
}

Importer.BASE = isXPCOM
    ? './'
    : (isNode
    ? __dirname
    : (isWebWorker
    ? this.location.href.split('/').slice(0,-1).join('/')
    : ($$tag('script', -1).src||'./').split('/').slice(0,-1).join('/') // absolute uri
));

// export it
return Importer;
});
For more information send a message to info at phpclasses dot org.