Because ajax loads are asynchronous,
we have to wait for all calls to be sinished to load HTML into DIV
and then we have to wait to do all the callbacks
198197
function inits() {
  log( "init", "step="+step+" ajaxOngoing="+ajaxOngoing );
  if ( getParam( 'nc' ) == 'true' ) {
    noCache = "?nc="+ Math.random();
  }

  if ( ajaxOngoing == 0 ) { 
    if ( step == "load-lang" ) {
      ajaxOngoing++;
      log( 'init', 'Start to load module list...');
      loadLang();
      step = "loadmodulemap";
    } else if ( step == "loadmodulemap" ) {
      ajaxOngoing++;
      log( 'init', 'Start to load module list...');
      loadModuleList();
      step = "loaddecor";
    } else if ( step == "loaddecor" ) {
      ajaxOngoing++;
      log( 'init', 'Start to load decor config...');
      loadDecorList();
      step = "loadstructure";
    } else  if ( step == "loadstructure" ) {
      ajaxOngoing++;
      log( 'init', 'Load Structure File ...');
      loadStructure();
      step = "loadincludes";
    } else if ( step == "loadincludes" ) {
      ajaxOngoing++;
      log( 'init', 'Start to load include JS modules ...');
      checkModules( );
      loadIncludes();
      step = "loadmodules";
    } else if ( step == "loadmodules" ) {
      ajaxOngoing++;
      log( 'init', 'Start to load JS modules ...');
      loadModules();
      if ( layout.theme != null ) {
        loadCSSrelPath( 'css-custom/'+layout.theme+'.css' );
        //jQuery('head').append('<link rel="stylesheet" rel="nofollow" href="css-custom/'+layout.theme+'.css" type="text/css" />');        
      }
      loadCSSrelPath( "css-custom/custom.css" );
      if ( pageInfo["layoutMode"] == 'tablet' ) {
        loadCSSrelPath( "css-custom/custom-t.css" );
        //jQuery('head').append('<link rel="stylesheet" rel="nofollow" href="css-custom/custom-t.css" type="text/css" />');        
      } else if ( pageInfo["layoutMode"] == 'mobile' ) {
        loadCSSrelPath( "css-custom/custom-m.css" );
        //jQuery('head').append('<link rel="st<ylesheet" rel="nofollow" href="css-custom/custom-m.css" type="text/css" />');
      } 
      step = "initmodules";
    } else  if ( step == "initmodules" ) {
      ajaxOngoing++;
      log( 'init', 'Load Structure File ...');
      initModules( layout );
      step = "buildstructure";
    } else  if ( step == "buildstructure" ) {
      ajaxOngoing++;
      log( 'init', 'Start to build HTML ...');
      buildStructure( layout );
      step = "loadres-ht";
    } else  if ( step == "loadres-ht" ) {
      ajaxOngoing++;
      log( 'init', 'Start to load resources HTML ...');
      loadResourcesHT();
      step = "call-hooks";
    } else  if ( step == "call-hooks" ) {
      log( 'init', 'Call module hooks ...');
      callHooks();
      step = "loadres-js";
    } else  if ( step == "loadres-js" ) {
      ajaxOngoing++;
      log( 'init', 'Start to load resources JS ...');
      loadResourcesJS();
      step = "callbacks";
    } else  if ( step == "callbacks" ) {
      log( 'init', 'Start callback methods for resources...');
      resourceCallbacks();
      step = "dialogs";
    } else  if ( step == "dialogs" ) {
      log( 'init', 'Start load dialogs for resources...');
      resourceDialogs();
      step = "afterInit";
    } else  if ( step == "afterInit" ) {
      log( 'init', 'Start load dialogs for resources...');
      startModulesAfterPageLoad( layout );
      clearInterval( initTimerId );
      step = "done";
    }
  }  
}
20485
function contentLoaded(callback) {
    var addEventListener = doc['addEventListener'];
    var done = false, top = true,
        add = addEventListener ? 'addEventListener' : 'attachEvent',
        rem = addEventListener ? 'removeEventListener' : 'detachEvent',
        pre = addEventListener ? '' : 'on',

        init = function(e) {
          if (e.type == 'readystatechange' && doc.readyState != 'complete') {
            return;
          }
          (e.type == 'load' ? win : doc)[rem](pre + e.type, init, false);
          if (!done && (done = true)) { callback.call(win, e.type || e); }
        },

        poll = function() {
          try {
            root.doScroll('left');
          } catch(e) {
            win.setTimeout(poll, 50);
            return;
          }
          init('poll');
        };

    if (doc.readyState == 'complete') {
      callback.call(win, 'lazy');
    } else {
      if (doc.createEventObject && root.doScroll) {
        try { top = !win.frameElement; } catch(e) { }
        if (top) { poll(); }
      }
      doc[add](pre + 'DOMContentLoaded', init, false);
      doc[add](pre + 'readystatechange', init, false);
      win[add](pre + 'load', init, false);
    }
  }
708258
function (url, callback) {
		var ajax = this.obj.$ajax;
		if (this._update_busy)
			return false;
		else
			this._update_busy = true;

		//this._loader = this._loader || new dtmlXMLLoaderObject(true);

		//this._loader.async=true;
		//this._loader.waitCall=callback;
		//this._loader.loadXML(url);
		ajax.get(url, callback);

	}
353450
async def _async_render(self, *, url: str, script: str = None, scrolldown, sleep: int, wait: float, reload, content: Optional[str], timeout: Union[float, int], keep_page: bool):
        
        try:
            page = await self.browser.newPage()

            # Wait before rendering the page, to prevent timeouts.
            await asyncio.sleep(wait)

            # Load the given page (GET request, obviously.)
            if reload:
                await page.goto(url, options={'timeout': int(timeout * 1000)})
            else:
                await page.goto(f'data:text/html,{self.html}', options={'timeout': int(timeout * 1000)})

            result = None
            if script:
                result = await page.evaluate(script)

            if scrolldown:
                for _ in range(scrolldown):
                    await page._keyboard.down('PageDown')
                    await asyncio.sleep(sleep)
            else:
                await asyncio.sleep(sleep)

            if scrolldown:
                await page._keyboard.up('PageDown')

            # Return the content of the page, JavaScript evaluated.
            content = await page.content()
            if not keep_page:
                await page.close()
                page = None
            return content, result, page
        except TimeoutError:
            await page.close()
            page = None
            return None
1004187
function waitForString(page, ph, str, callback) {
    var elapsed = 0;
    var currentDom = '';
    var timeout = false;

    async.until(
        function () {
            timeout = elapsed > constants.WAIT_TIMEOUT;
            return currentDom.indexOf(str) > -1 || timeout;
        },

        function (callback) {
            setTimeout(function () {
                getData.takeSnapshot(page, ph, function (error, page, ph, dom) {
                    if (error) {
                        callback(error);
                        return;
                    }
                    currentDom = dom;
                    elapsed += constants.POLL_INTERVAL;
                    callback();
                })
            }, constants.POLL_INTERVAL);
        },

        function (error) {
            if (error) {
                callback(error, page, ph);
                return;
            }
            if (timeout) {
                callback('Timeout while waiting for string', page, ph);
                return;
            }
            callback(null, page, ph);
        }
    );
}
1363125
function preloadJavascript(data, onload, onerror) {
         var script = document.createElement("script");
         script.src = data.src;
         script.type = "text/javascript";

         if (typeof api.crossOrigin === "string") {
           script.crossOrigin = api.crossOrigin;
         }

         script.defer = true;

         script.onload = function () {
           // callback
           onload();
         };

         script.onerror = function () {
           // callback
           onerror(data.name);
         };

         document.getElementsByTagName("body")[0].appendChild(script);
       }
172763
function onImagesLoaded(images, callback) {
    var self = this,
        unloaded = images.length;

    if (unloaded === 0) {
      callback();
    }

    images.each(function () {
      // Check if image is loaded
      if (this.complete || this.readyState === 4 || this.readyState === 'complete') {
        singleImageLoaded();
      }
      // Force load the image
      else {
          // fix for IE. See https://css-tricks.com/snippets/jquery/fixing-load-in-ie-for-cached-images/
          var src = $(this).attr('src');
          $(this).attr('src', src + (src.indexOf('?') >= 0 ? '&' : '?') + new Date().getTime());
          $(this).one('load', function () {
            singleImageLoaded();
          });
        }
    });

    function singleImageLoaded() {
      unloaded--;
      if (unloaded === 0) {
        callback();
      }
    }
  }
659089
function (index, callback) {
            $.when(pages[index] && pages[index].load())
                .always(callback);
        }
964445
function() {
        this.items = this.element.find('> li').each(function() {
            var self = $(this);

            // Cache the initial column width
            self.cache('matrix-column-width', self.outerWidth());
        });

        if (this.options.defer) {
            this._deferRender();
        } else {
            this.render();
        }
    }
1230885
function(src) {
    var _deferred = $q.defer();

    // Instance
    var _loadable = {

      src: src,

      // Loading completion flag
      isComplete: false,

      promise: _deferred.promise,

      // TODO switch to $document
      $element: document.createElement('script')
    };

    // Build DOM element
    _loadable.$element.src = src;
    _loadable.$element.type = 'text/javascript';
    _loadable.$element.async = false;

    _head.insertBefore(_loadable.$element, _head.firstChild);

    // Mark loading in progress
    _loadingList.push(_loadable);

    // Completion
    _loadable.$element.onload = _loadable.$element.onreadystatechange = function() {

      if(!_loadable.isComplete && (!this.readyState || this.readyState === "loaded" || this.readyState === "complete")) {
        _loadable.isComplete = true;
        _loadable.$element.onload = _loadable.$element.onreadystatechange = null;
        
        if(_head && _loadable.$element.parentNode) {
          _head.removeChild(_loadable.$element);
        }

        // Mark complete
        var i = _loadingList.indexOf(_loadable);
        if(i !== -1) {
          _loadingList.splice(i, 1);
        }
        _completedList.push(_loadable);

        _deferred.resolve(_loadable);
      }
    };

    return _loadable;
  }
1319473
protected function autoloadJS()
	{
		if (!is_string($this->callback))
		{
			return;
		}

		try
		{
			$this->js = FunctionProvider::get($this->callback);
		}
		catch (InvalidArgumentException $e)
		{
			// Do nothing
		}
	}
837627
function documentReady(callback) {
  document.readyState === "interactive" || document.readyState === "complete" ? callback() : document.addEventListener("DOMContentLoaded", callback);
}
362050
function ready(callback) {
  let onLoaded = (event) => {
    if (document.addEventListener) {
      document.removeEventListener('DOMContentLoaded', onLoaded, false);
      window.removeEventListener('load', onLoaded, false);
    }
    else if (document.attachEvent) {
      document.detachEvent('onreadystatechange', onLoaded);
      window.detachEvent('onload', onLoaded);
    }

    setTimeout(callback, 1);
  };

  if (document.readyState === 'complete') return setTimeout(callback, 1);

  if (document.addEventListener) {
    document.addEventListener('DOMContentLoaded', onLoaded, false);
    window.addEventListener('load', onLoaded, false);
  }
  else if (document.attachEvent) {
    document.attachEvent('onreadystatechange', onLoaded);
    window.attachEvent('onload', onLoaded);
  }
}
1255132
function startModulesAfterPageLoad( lo ) {
  // header hooks
  if ( ( lo != null ) && ( lo.header != null ) && ( lo.header.modules != null ) ) {
    for ( var i = 0; i < lo.header.modules.length; i++ ) {
      startModuleAfterPageLoad( lo.header.modules[i] );
    }
  }
  // footer hooks
  if ( ( lo != null ) && ( lo.footer != null ) && ( lo.footer.modules != null ) ) {
    for ( var i = 0; i < lo.footer.modules.length; i++ ) {
      startModuleAfterPageLoad( lo.footer.modules[i] );
    }
  }
  ajaxOngoing--;
}
1362937
function EventLoop() {
    var renderCallbacks = [],
        intervalId,
        startInternal = function () {
            intervalId = requestAnimationFrame(startInternal);
            for (var i = 0, n = renderCallbacks.length; i < n; ++i) {
                renderCallbacks[i]();
            }
        };

    this.onRender = function (callback) {
        if (typeof callback === 'function') {
            renderCallbacks.push(callback);
        }
    };
    this.start = function () {
        startInternal();
    };
    this.stop = function () {
        if (intervalId) {
            cancelAnimationFrame(intervalId);
            intervalId = null;
        }
    };
}
363976
function loadJs(url, ignoreDuplicate, cb) {
        if (ignoreDuplicate && loadedRes[url]) {
            cb && cb();
            return;
        }
        if (ignoreDuplicate && loadingRes[url]) {
            loadingRes[url].push(cb);
            return;
        }
        loadingRes[url] = loadingRes[url] || [];
        var script = d.createElement('script');
        var loaded = false;
        var wrap = function () {
            if (loaded) {
                return;
            }
            loaded = true;
            loadedRes[url] = true;
            if (ignoreDuplicate) {
                for (var i = 0; i < loadingRes[url].length; i++) {
                    loadingRes[url][i] && loadingRes[url][i]();
                }
                loadingRes[url] = null;
            }
            cb && cb();
        };
        script.setAttribute('src', url);
        script.setAttribute('type', 'text/javascript');
        script.onload = script.onerror = wrap;
        script.onreadystatechange = wrap;
        head.appendChild(script);
    }
665045
function ajaxCallback(page, ph, oldUrl, options, callback) {
    // callback for page change
    switch(options) {
        case 1:
            // expect ajax
            pageDomHasChanged(page, ph, function (error, page, ph) {
                callback(error, page, ph);
            });
            break;
        case 2:
            // expect navigation
            pageHasChanged(page, oldUrl, function (error) {
                callback(error, page, ph);
            });
            break;
        default:
            // callback immediately
            callback(null, page, ph);
            break;
    }
}