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; });