|  | @@ -0,0 +1,316 @@
 | 
	
		
			
				|  |  | +(function(root, factory) {
 | 
	
		
			
				|  |  | +  if (typeof define === 'function' && define.amd) {
 | 
	
		
			
				|  |  | +    define([], factory);
 | 
	
		
			
				|  |  | +  } else if (typeof exports === 'object') {
 | 
	
		
			
				|  |  | +    module.exports = factory();
 | 
	
		
			
				|  |  | +  } else {
 | 
	
		
			
				|  |  | +    root.loadjs = factory();
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +}(this, function() {
 | 
	
		
			
				|  |  | +/**
 | 
	
		
			
				|  |  | + * Global dependencies.
 | 
	
		
			
				|  |  | + * @global {Object} document - DOM
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +var devnull = function() {},
 | 
	
		
			
				|  |  | +    bundleIdCache = {},
 | 
	
		
			
				|  |  | +    bundleResultCache = {},
 | 
	
		
			
				|  |  | +    bundleCallbackQueue = {};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/**
 | 
	
		
			
				|  |  | + * Subscribe to bundle load event.
 | 
	
		
			
				|  |  | + * @param {string[]} bundleIds - Bundle ids
 | 
	
		
			
				|  |  | + * @param {Function} callbackFn - The callback function
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  | +function subscribe(bundleIds, callbackFn) {
 | 
	
		
			
				|  |  | +  // listify
 | 
	
		
			
				|  |  | +  bundleIds = bundleIds.push ? bundleIds : [bundleIds];
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  var depsNotFound = [],
 | 
	
		
			
				|  |  | +      i = bundleIds.length,
 | 
	
		
			
				|  |  | +      numWaiting = i,
 | 
	
		
			
				|  |  | +      fn,
 | 
	
		
			
				|  |  | +      bundleId,
 | 
	
		
			
				|  |  | +      r,
 | 
	
		
			
				|  |  | +      q;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // define callback function
 | 
	
		
			
				|  |  | +  fn = function (bundleId, pathsNotFound) {
 | 
	
		
			
				|  |  | +    if (pathsNotFound.length) depsNotFound.push(bundleId);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    numWaiting--;
 | 
	
		
			
				|  |  | +    if (!numWaiting) callbackFn(depsNotFound);
 | 
	
		
			
				|  |  | +  };
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // register callback
 | 
	
		
			
				|  |  | +  while (i--) {
 | 
	
		
			
				|  |  | +    bundleId = bundleIds[i];
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // execute callback if in result cache
 | 
	
		
			
				|  |  | +    r = bundleResultCache[bundleId];
 | 
	
		
			
				|  |  | +    if (r) {
 | 
	
		
			
				|  |  | +      fn(bundleId, r);
 | 
	
		
			
				|  |  | +      continue;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // add to callback queue
 | 
	
		
			
				|  |  | +    q = bundleCallbackQueue[bundleId] = bundleCallbackQueue[bundleId] || [];
 | 
	
		
			
				|  |  | +    q.push(fn);
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/**
 | 
	
		
			
				|  |  | + * Publish bundle load event.
 | 
	
		
			
				|  |  | + * @param {string} bundleId - Bundle id
 | 
	
		
			
				|  |  | + * @param {string[]} pathsNotFound - List of files not found
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  | +function publish(bundleId, pathsNotFound) {
 | 
	
		
			
				|  |  | +  // exit if id isn't defined
 | 
	
		
			
				|  |  | +  if (!bundleId) return;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  var q = bundleCallbackQueue[bundleId];
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // cache result
 | 
	
		
			
				|  |  | +  bundleResultCache[bundleId] = pathsNotFound;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // exit if queue is empty
 | 
	
		
			
				|  |  | +  if (!q) return;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // empty callback queue
 | 
	
		
			
				|  |  | +  while (q.length) {
 | 
	
		
			
				|  |  | +    q[0](bundleId, pathsNotFound);
 | 
	
		
			
				|  |  | +    q.splice(0, 1);
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/**
 | 
	
		
			
				|  |  | + * Execute callbacks.
 | 
	
		
			
				|  |  | + * @param {Object or Function} args - The callback args
 | 
	
		
			
				|  |  | + * @param {string[]} depsNotFound - List of dependencies not found
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  | +function executeCallbacks(args, depsNotFound) {
 | 
	
		
			
				|  |  | +  // accept function as argument
 | 
	
		
			
				|  |  | +  if (args.call) args = {success: args};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // success and error callbacks
 | 
	
		
			
				|  |  | +  if (depsNotFound.length) (args.error || devnull)(depsNotFound);
 | 
	
		
			
				|  |  | +  else (args.success || devnull)(args);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/**
 | 
	
		
			
				|  |  | + * Load individual file.
 | 
	
		
			
				|  |  | + * @param {string} path - The file path
 | 
	
		
			
				|  |  | + * @param {Function} callbackFn - The callback function
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  | +function loadFile(path, callbackFn, args, numTries) {
 | 
	
		
			
				|  |  | +  var doc = document,
 | 
	
		
			
				|  |  | +      async = args.async,
 | 
	
		
			
				|  |  | +      maxTries = (args.numRetries || 0) + 1,
 | 
	
		
			
				|  |  | +      beforeCallbackFn = args.before || devnull,
 | 
	
		
			
				|  |  | +      pathname = path.replace(/[\?|#].*$/, ''),
 | 
	
		
			
				|  |  | +      pathStripped = path.replace(/^(css|img)!/, ''),
 | 
	
		
			
				|  |  | +      isLegacyIECss,
 | 
	
		
			
				|  |  | +      e;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  numTries = numTries || 0;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  if (/(^css!|\.css$)/.test(pathname)) {
 | 
	
		
			
				|  |  | +    // css
 | 
	
		
			
				|  |  | +    e = doc.createElement('link');
 | 
	
		
			
				|  |  | +    e.rel = 'stylesheet';
 | 
	
		
			
				|  |  | +    e.href = pathStripped;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // tag IE9+
 | 
	
		
			
				|  |  | +    isLegacyIECss = 'hideFocus' in e;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // use preload in IE Edge (to detect load errors)
 | 
	
		
			
				|  |  | +    if (isLegacyIECss && e.relList) {
 | 
	
		
			
				|  |  | +      isLegacyIECss = 0;
 | 
	
		
			
				|  |  | +      e.rel = 'preload';
 | 
	
		
			
				|  |  | +      e.as = 'style';
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  } else if (/(^img!|\.(png|gif|jpg|svg|webp)$)/.test(pathname)) {
 | 
	
		
			
				|  |  | +    // image
 | 
	
		
			
				|  |  | +    e = doc.createElement('img');
 | 
	
		
			
				|  |  | +    e.src = pathStripped;    
 | 
	
		
			
				|  |  | +  } else {
 | 
	
		
			
				|  |  | +    // javascript
 | 
	
		
			
				|  |  | +    e = doc.createElement('script');
 | 
	
		
			
				|  |  | +    e.src = path;
 | 
	
		
			
				|  |  | +    e.async = async === undefined ? true : async;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  e.onload = e.onerror = e.onbeforeload = function (ev) {
 | 
	
		
			
				|  |  | +    var result = ev.type[0];
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // treat empty stylesheets as failures to get around lack of onerror
 | 
	
		
			
				|  |  | +    // support in IE9-11
 | 
	
		
			
				|  |  | +    if (isLegacyIECss) {
 | 
	
		
			
				|  |  | +      try {
 | 
	
		
			
				|  |  | +        if (!e.sheet.cssText.length) result = 'e';
 | 
	
		
			
				|  |  | +      } catch (x) {
 | 
	
		
			
				|  |  | +        // sheets objects created from load errors don't allow access to
 | 
	
		
			
				|  |  | +        // `cssText` (unless error is Code:18 SecurityError)
 | 
	
		
			
				|  |  | +        if (x.code != 18) result = 'e';
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // handle retries in case of load failure
 | 
	
		
			
				|  |  | +    if (result == 'e') {
 | 
	
		
			
				|  |  | +      // increment counter
 | 
	
		
			
				|  |  | +      numTries += 1;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      // exit function and try again
 | 
	
		
			
				|  |  | +      if (numTries < maxTries) {
 | 
	
		
			
				|  |  | +        return loadFile(path, callbackFn, args, numTries);
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    } else if (e.rel == 'preload' && e.as == 'style') {
 | 
	
		
			
				|  |  | +      // activate preloaded stylesheets
 | 
	
		
			
				|  |  | +      return e.rel = 'stylesheet'; // jshint ignore:line
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  | +    // execute callback
 | 
	
		
			
				|  |  | +    callbackFn(path, result, ev.defaultPrevented);
 | 
	
		
			
				|  |  | +  };
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // add to document (unless callback returns `false`)
 | 
	
		
			
				|  |  | +  if (beforeCallbackFn(path, e) !== false) doc.head.appendChild(e);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/**
 | 
	
		
			
				|  |  | + * Load multiple files.
 | 
	
		
			
				|  |  | + * @param {string[]} paths - The file paths
 | 
	
		
			
				|  |  | + * @param {Function} callbackFn - The callback function
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  | +function loadFiles(paths, callbackFn, args) {
 | 
	
		
			
				|  |  | +  // listify paths
 | 
	
		
			
				|  |  | +  paths = paths.push ? paths : [paths];
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  var numWaiting = paths.length,
 | 
	
		
			
				|  |  | +      x = numWaiting,
 | 
	
		
			
				|  |  | +      pathsNotFound = [],
 | 
	
		
			
				|  |  | +      fn,
 | 
	
		
			
				|  |  | +      i;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // define callback function
 | 
	
		
			
				|  |  | +  fn = function(path, result, defaultPrevented) {
 | 
	
		
			
				|  |  | +    // handle error
 | 
	
		
			
				|  |  | +    if (result == 'e') pathsNotFound.push(path);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // handle beforeload event. If defaultPrevented then that means the load
 | 
	
		
			
				|  |  | +    // will be blocked (ex. Ghostery/ABP on Safari)
 | 
	
		
			
				|  |  | +    if (result == 'b') {
 | 
	
		
			
				|  |  | +      if (defaultPrevented) pathsNotFound.push(path);
 | 
	
		
			
				|  |  | +      else return;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    numWaiting--;
 | 
	
		
			
				|  |  | +    if (!numWaiting) callbackFn(pathsNotFound);
 | 
	
		
			
				|  |  | +  };
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // load scripts
 | 
	
		
			
				|  |  | +  for (i=0; i < x; i++) loadFile(paths[i], fn, args);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/**
 | 
	
		
			
				|  |  | + * Initiate script load and register bundle.
 | 
	
		
			
				|  |  | + * @param {(string|string[])} paths - The file paths
 | 
	
		
			
				|  |  | + * @param {(string|Function|Object)} [arg1] - The (1) bundleId or (2) success
 | 
	
		
			
				|  |  | + *   callback or (3) object literal with success/error arguments, numRetries,
 | 
	
		
			
				|  |  | + *   etc.
 | 
	
		
			
				|  |  | + * @param {(Function|Object)} [arg2] - The (1) success callback or (2) object
 | 
	
		
			
				|  |  | + *   literal with success/error arguments, numRetries, etc.
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  | +function loadjs(paths, arg1, arg2) {
 | 
	
		
			
				|  |  | +  var bundleId,
 | 
	
		
			
				|  |  | +      args;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // bundleId (if string)
 | 
	
		
			
				|  |  | +  if (arg1 && arg1.trim) bundleId = arg1;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // args (default is {})
 | 
	
		
			
				|  |  | +  args = (bundleId ? arg2 : arg1) || {};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // throw error if bundle is already defined
 | 
	
		
			
				|  |  | +  if (bundleId) {
 | 
	
		
			
				|  |  | +    if (bundleId in bundleIdCache) {
 | 
	
		
			
				|  |  | +      throw "LoadJS";
 | 
	
		
			
				|  |  | +    } else {
 | 
	
		
			
				|  |  | +      bundleIdCache[bundleId] = true;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  function loadFn(resolve, reject) {
 | 
	
		
			
				|  |  | +    loadFiles(paths, function (pathsNotFound) {
 | 
	
		
			
				|  |  | +      // execute callbacks
 | 
	
		
			
				|  |  | +      executeCallbacks(args, pathsNotFound);
 | 
	
		
			
				|  |  | +      
 | 
	
		
			
				|  |  | +      // resolve Promise
 | 
	
		
			
				|  |  | +      if (resolve) {
 | 
	
		
			
				|  |  | +        executeCallbacks({success: resolve, error: reject}, pathsNotFound);
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      // publish bundle load event
 | 
	
		
			
				|  |  | +      publish(bundleId, pathsNotFound);
 | 
	
		
			
				|  |  | +    }, args);
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  
 | 
	
		
			
				|  |  | +  if (args.returnPromise) return new Promise(loadFn);
 | 
	
		
			
				|  |  | +  else loadFn();
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/**
 | 
	
		
			
				|  |  | + * Execute callbacks when dependencies have been satisfied.
 | 
	
		
			
				|  |  | + * @param {(string|string[])} deps - List of bundle ids
 | 
	
		
			
				|  |  | + * @param {Object} args - success/error arguments
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  | +loadjs.ready = function ready(deps, args) {
 | 
	
		
			
				|  |  | +  // subscribe to bundle load event
 | 
	
		
			
				|  |  | +  subscribe(deps, function (depsNotFound) {
 | 
	
		
			
				|  |  | +    // execute callbacks
 | 
	
		
			
				|  |  | +    executeCallbacks(args, depsNotFound);
 | 
	
		
			
				|  |  | +  });
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  return loadjs;
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/**
 | 
	
		
			
				|  |  | + * Manually satisfy bundle dependencies.
 | 
	
		
			
				|  |  | + * @param {string} bundleId - The bundle id
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  | +loadjs.done = function done(bundleId) {
 | 
	
		
			
				|  |  | +  publish(bundleId, []);
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/**
 | 
	
		
			
				|  |  | + * Reset loadjs dependencies statuses
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  | +loadjs.reset = function reset() {
 | 
	
		
			
				|  |  | +  bundleIdCache = {};
 | 
	
		
			
				|  |  | +  bundleResultCache = {};
 | 
	
		
			
				|  |  | +  bundleCallbackQueue = {};
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/**
 | 
	
		
			
				|  |  | + * Determine if bundle has already been defined
 | 
	
		
			
				|  |  | + * @param String} bundleId - The bundle id
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  | +loadjs.isDefined = function isDefined(bundleId) {
 | 
	
		
			
				|  |  | +  return bundleId in bundleIdCache;
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +// export
 | 
	
		
			
				|  |  | +return loadjs;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +}));
 |