egroupware_official/phpgwapi/js/jsapi/egw_ready.js
Andreas Stöckel d486e50a57 phpgwapi:
* Changed way of how "webserverUrl" gets set - any type of data can now be
	  injected into the egw object by creating an object with the data and an
	  entry "prefsOnly" set to true. This allows to ensure, that "webserverUrl"
	  is the first thing that is being set in the egw object (as needed when
	  including new JS/CSS files at runtime)

jsapi:
	* Fixed including JS/CSS files at runtime in other windows than the root
	  window
	* Added "ready" function/module, which provides an alternative to the
	  $j("ready") function. The ready module provides the functionality to
	  postpone calling the "ready" until certain events happened.
	* using jQuery calendar object instead of jscalendar in the calendar
	  function.
	* added "jquery" module which takes care of including all jQuery modules
	  in all windows
	* added possibility for modules to update constants using the "constant"
	  function.
	* added possibility for modules to access certain other modules using
	  the "module" function

etemplate:
	* Using new egw(window).ready function to build the template first if
	  loading has finished.
2012-03-09 15:32:29 +00:00

218 lines
5.2 KiB
JavaScript

/**
* EGroupware clientside API object
*
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package etemplate
* @subpackage api
* @link http://www.egroupware.org
* @author Andreas Stöckel (as AT stylite.de)
* @version $Id$
*/
"use strict"
/*egw:uses
egw_core;
egw_utils;
egw_debug;
*/
egw.extend('ready', egw.MODULE_WND_LOCAL, function(_app, _wnd) {
var egw = this;
var registeredCallbacks = [];
var registeredProgress = [];
var readyPending = {'readyEvent': true};
var readyPendingCnt = 1;
var readyDoneCnt = 0;
var isReady = false;
function doReadyWaitFor() {
if (!isReady)
{
var uid = egw.uid();
readyPending[uid] = true;
readyPendingCnt++;
readyProgressChange();
return uid;
}
this.debug('warning', 'ready has already been called!');
return null;
}
function doReadyDone(_token) {
if (typeof readyPending[_token] !== 'undefined')
{
delete readyPending[_token];
readyPendingCnt--;
readyDoneCnt++;
readyProgressChange();
testCallReady();
}
}
function readyProgressChange()
{
// Call all registered progress callbacks
for (var i = 0; i < registeredProgress.length; i++)
{
registeredProgress[i].callback.call(
registeredProgress[i].context,
readyDoneCnt,
readyPendingCnt
);
}
egw.debug('log', 'Ready events, processed %s/%s', readyDoneCnt,
readyPendingCnt + readyDoneCnt);
}
function readyEventHandler() {
doReadyDone('readyEvent');
}
function testCallReady()
{
// Check whether no further event is pending
if (readyPendingCnt <= 1 && !isReady)
{
// If exactly one event is pending and that one is not the ready
// event, abort
if (readyPendingCnt === 1 && !readyPending['readyEvent'])
{
return;
}
// Set "isReady" to true, if readyPendingCnt is zero
var isReady = readyPendingCnt === 0;
// Call all registered callbacks
for (var i = registeredCallbacks.length - 1; i >= 0; i--)
{
if (registeredCallbacks[i].before || readyPendingCnt === 0)
{
registeredCallbacks[i].callback.call(
registeredCallbacks[i].context
);
// Delete the callback from the list
registeredCallbacks.splice(i, 1);
}
}
}
}
// Register the event handler for "ready" (code adapted from jQuery)
// Mozilla, Opera and webkit nightlies currently support this event
if (_wnd.document.addEventListener) {
// Use the handy event callback
_wnd.document.addEventListener("DOMContentLoaded", readyEventHandler, false);
// A fallback to window.onload, that will always work
_wnd.addEventListener("load", readyEventHandler, false);
// If IE event model is used
} else if (_wnd.document.attachEvent) {
// ensure firing before onload,
// maybe late but safe also for iframes
_wnd.document.attachEvent("onreadystatechange", readyEventHandler);
// A fallback to window.onload, that will always work
_wnd.attachEvent("onload", readyEventHandler);
}
return {
/**
* The readyWaitFor function can be used to register an event, that has
* to be marked as "done" before the ready function will call its
* registered callbacks. The function returns an id that has to be
* passed to the "readDone" function once
*/
readyWaitFor: function() {
return doReadyWaitFor();
},
/**
* The readyDone function can be used to mark a event token as
* previously requested by "readyWaitFor" as done.
*
* @param _token is the token which has now been processed.
*/
readyDone: function(_token) {
doReadyDone(_token);
},
/**
* The ready function can be used to register a function that will be
* called, when the window is completely loaded. All ready handlers will
* be called exactly once. If the ready handler has already been called,
* the given function will be called defered using setTimeout.
*
* @param _callback is the function which will be called when the page
* is ready. No parameters will be passed.
* @param _context is the context in which the callback function should
* get called.
* @param _beforeDOMContentLoaded specifies, whether the callback should
* get called, before the DOMContentLoaded event has been fired.
*/
ready: function(_callback, _context, _beforeDOMContentLoaded) {
if (!isReady)
{
registeredCallbacks.push({
'callback': _callback,
'context': _context ? _context : null,
'before': _beforeDOMContentLoaded ? true : false
});
}
else
{
setTimeout(function() {
_callback.call(_context)
}, 1);
}
},
/**
* The readyProgress function can be used to register a function that
* will be called whenever a ready event is done or registered.
*
* @param _callback is the function which will be called when the
* progress changes.
* @param _context is the context in which the callback function which
* should get called.
*/
readyProgress: function(_callback, _context) {
if (!isReady)
{
registeredProgress.unshift({
'callback': _callback,
'context': _context ? _context : null
});
}
else
{
this.debug('warning', 'ready has already been called!');
}
},
/**
* Returns whether the ready events have already been called.
*/
isReady: function() {
return isReady;
}
};
});