diff --git a/phpgwapi/inc/class.egw_framework.inc.php b/phpgwapi/inc/class.egw_framework.inc.php
index d927a13420..419ae3d7bb 100644
--- a/phpgwapi/inc/class.egw_framework.inc.php
+++ b/phpgwapi/inc/class.egw_framework.inc.php
@@ -89,6 +89,7 @@ abstract class egw_framework
public static function init_static()
{
self::$js_include_mgr = new egw_include_mgr(array(
+ '/phpgwapi/js/labjs/LAB.src.js',
// allways load jquery (not -ui) and egw_json first
'/phpgwapi/js/jquery/jquery.js',
'/phpgwapi/js/./egw_json.js',
@@ -1302,6 +1303,14 @@ abstract class egw_framework
$start = '\n";
return "\n".$start.implode($end.$start, $to_include).$end;
+
+ // using LABjs to load all javascript would require all other script-tags to run in wait() of queue!
+ /*return "\n".$start.'/phpgwapi/js/labjs/LAB.src.js'.$end."\n".
+ '
+';*/
}
/**
diff --git a/phpgwapi/js/jsapi/egw_files.js b/phpgwapi/js/jsapi/egw_files.js
index fff8d1ba21..0a93f9e5f0 100644
--- a/phpgwapi/js/jsapi/egw_files.js
+++ b/phpgwapi/js/jsapi/egw_files.js
@@ -43,223 +43,41 @@ egw.extend('files', egw.MODULE_WND_LOCAL, function(_app, _wnd) {
return _src.replace(/\?[0-9]+&?/, '?').replace(/\?$/, '');
}
- /**
- * Add file to list of loaded files
- *
- * @param src url of file
- * @param dom optional dom node to trac loading status of javascript files
- */
- function addFile(src, dom)
- {
- if (src)
- {
- files[removeTS(src)] = dom || true;
- }
- }
-
- /**
- * Check if a source file is already loaded or loading
- *
- * @param _src url of file (already run throught removeTS!)
- * @return false: not loaded, true: loaded or "loading"
- */
- function isLoaded(_src)
- {
- switch (typeof files[_src])
- {
- case 'undefined':
- return false;
- case 'boolean':
- return files[_src];
- default:
- return files[_src].readyState == 'complete' || files[_src].readyState == 'loaded';
- }
- return "loading";
- }
-
- /**
- * object with array of callbacks or contexts by source/url
- */
- var callbacks = {};
- var contexts = {};
-
- /**
- * Attach onLoad callback to given js source
- *
- * @param _src url of file (already run throught removeTS!)
- * @param _callback
- * @param _context
- * @return true if callback got attached, false if it was run directly
- */
- function attachCallback(_src, _callback, _context)
- {
- if (typeof _callback === 'undefined') return;
-
- switch (typeof files[_src])
- {
- case 'undefined':
- case 'boolean':
- _callback.call(_context);
- return false;
- }
-
- if (typeof callbacks[_src] === 'undefined')
- {
- callbacks[_src] = [];
- contexts[_src] = [];
- callbacks[_src].push(_callback);
- contexts[_src].push(_context);
-
- var scriptnode = files[_src];
-
- // Setup the 'onload' handler for FF, Opera, Chrome
- scriptnode.onload = function(e) {
- egw.debug('info', 'Retrieved JS file "%s" from server', _src);
- runCallbacks.call(this, _src);
- };
-
- // IE
- if (typeof scriptnode.readyState != 'undefined')
- {
- if (scriptnode.readyState != 'complete' &&
- scriptnode.readyState != 'loaded')
- {
- scriptnode.onreadystatechange = function() {
- var node = _wnd.event.srcElement;
- if (node.readyState == 'complete' || node.readyState == 'loaded')
- {
- egw.debug('info', 'Retrieved JS file "%s" from server', _src);
- runCallbacks.call(this, _src);
- }
- };
- }
- else
- {
- runCallbacks.call(this, _src);
- return false;
- }
- }
- }
- else
- {
- callbacks[_src].push(_callback);
- contexts[_src].push(_context);
- }
- return true;
- }
-
- /**
- * Run all callbacks of a given source
- *
- * @param _src url of file (already run throught removeTS!)
- */
- function runCallbacks(_src)
- {
- if (typeof callbacks[_src] === 'undefined') return;
-
- egw.debug('info', 'Running %d callbacks for JS file "%s"', callbacks[_src].length, _src);
-
- for(var i = 0; i < callbacks[_src].length; i++)
- {
- callbacks[_src][i].call(contexts[_src][i]);
- }
- delete callbacks[_src];
- delete contexts[_src];
- }
-
- /**
- * Gather all already loaded JavaScript and CSS files on document load.
- */
- // Iterate over the script tags
- var scripts = _wnd.document.getElementsByTagName('script');
- for (var i = 0; i < scripts.length; i++)
- {
- addFile(scripts[i].getAttribute('src'), scripts[i]);
- }
-
- // Iterate over the link tags
- var links = _wnd.document.getElementsByTagName('link');
- for (var i = 0; i < links.length; i++)
- {
- addFile(links[i].getAttribute('href'));
- }
-
- /**
- * Include a single javascript file and call given callback once it's done
- *
- * If file is already loaded, _callback gets called imediatly
- *
- * @param _jsFile url of file
- * @param _callback
- * @param _context for callback
- */
- function includeJSFile(_jsFile, _callback, _context)
- {
- var _src = removeTS(_jsFile);
- var alreadyLoaded = isLoaded(_src);
-
- if (alreadyLoaded === false)
- {
- // Create the script node which contains the new file
- var scriptnode = _wnd.document.createElement('script');
- scriptnode.type = "text/javascript";
- scriptnode.src = _jsFile;
- scriptnode._originalSrc = _jsFile;
-
- files[_src] = scriptnode;
-
- // Append the newly create script node to the head
- var head = _wnd.document.getElementsByTagName('head')[0];
- head.appendChild(scriptnode);
-
- // Request the given javascript file
- egw.debug('info', 'Requested JS file "%s" from server', _jsFile);
- }
- else if (alreadyLoaded === true)
- {
- egw.debug('info', 'JS file "%s" already loaded', _jsFile);
- }
- else
- {
- egw.debug('info', 'JS file "%s" currently loading', _jsFile);
- }
-
- // attach (or just run) callback
- attachCallback(_src, _callback, _context);
- }
-
return {
includeJS: function(_jsFiles, _callback, _context, _prefix) {
- // Also allow including a single javascript file
- if (typeof _jsFiles === 'string')
- {
- _jsFiles = [_jsFiles];
- }
if (typeof _prefix === 'undefined')
{
_prefix = '';
}
-
- var loaded = 0;
-
- // Include all given JS files, if all are successfully loaded, call
- // the context function
- for (var i = 0; i < _jsFiles.length; i++)
+ // LABjs uses prefix only if url is not absolute, so removing leading / if necessary and add it to prefix
+ if (_prefix)
{
- includeJSFile.call(this, _prefix+_jsFiles[i], function(_file) {
- loaded++;
- if (loaded == _jsFiles.length && _callback) {
- _callback.call(_context);
- }
- });
+ // Also allow including a single javascript file
+ if (typeof _jsFiles === 'string')
+ {
+ _jsFiles = [_jsFiles];
+ }
+ for(var i=0; i < _jsFiles.length; ++i)
+ {
+ if (_jsFiles[i].charAt(0) == '/') _jsFiles[i] = _jsFiles[i].substr(1);
+ }
+ if (_prefix.charAt(_prefix.length-1) != '/')
+ {
+ _prefix += '/';
+ }
}
+ // setting AlwaysPreserverOrder: true, 'til we have some other means of ensuring dependency resolution
+ $LAB.setOptions({AlwaysPreserveOrder:true,BasePath:_prefix}).script(_jsFiles).wait(function(){
+ _callback.call(_context);
+ });
},
includeCSS: function(_cssFile) {
//Check whether the requested file has already been included
- if (typeof files[_cssFile] === 'undefined')
+ var file = removeTS(_cssFile);
+ if (typeof files[file] === 'undefined')
{
- files[_cssFile] = true;
+ files[file] = true;
// Create the node which is used to include the css fiel
var cssnode = _wnd.document.createElement('link');
diff --git a/phpgwapi/js/labjs/LAB-debug.min.js b/phpgwapi/js/labjs/LAB-debug.min.js
new file mode 100755
index 0000000000..99e7b142fe
--- /dev/null
+++ b/phpgwapi/js/labjs/LAB-debug.min.js
@@ -0,0 +1,5 @@
+/*! LAB.js (LABjs :: Loading And Blocking JavaScript)
+ v2.0.3 (c) Kyle Simpson
+ MIT License
+*/
+(function(j){var N=j.$LAB,A="UseLocalXHR",B="AlwaysPreserveOrder",w="AllowDuplicates",C="CacheBust",l="Debug",D="BasePath",E=/^[^?#]*\//.exec(location.href)[0],F=/^\w+\:\/\/\/?[^\/]+/.exec(E)[0],i=document.head||document.getElementsByTagName("head"),O=(j.opera&&Object.prototype.toString.call(j.opera)=="[object Opera]")||("MozAppearance"in document.documentElement.style),m=function(){},G=m,s=document.createElement("script"),H=typeof s.preload=="boolean",t=H||(s.readyState&&s.readyState=="uninitialized"),I=!t&&s.async===true,P=!t&&!I&&!O;if(j.console&&j.console.log){if(!j.console.error)j.console.error=j.console.log;m=function(a){j.console.log(a)};G=function(a,c){j.console.error(a,c)}}function J(a){return Object.prototype.toString.call(a)=="[object Function]"}function K(a){return Object.prototype.toString.call(a)=="[object Array]"}function Q(a,c){var b=/^\w+\:\/\//;if(/^\/\/\/?/.test(a)){a=location.protocol+a}else if(!b.test(a)&&a.charAt(0)!="/"){a=(c||"")+a}return b.test(a)?a:((a.charAt(0)=="/"?F:E)+a)}function u(a,c){for(var b in a){if(a.hasOwnProperty(b)){c[b]=a[b]}}return c}function R(a){var c=false;for(var b=0;b0){for(var a=0;a=0;){d=q.shift();a=a[d.type].apply(null,d.args)}return a},noConflict:function(){j.$LAB=N;return p},sandbox:function(){return M()}};return p}j.$LAB=M();(function(a,c,b){if(document.readyState==null&&document[a]){document.readyState="loading";document[a](c,b=function(){document.removeEventListener(c,b,false);document.readyState="complete"},false)}})("addEventListener","DOMContentLoaded")})(this);
\ No newline at end of file
diff --git a/phpgwapi/js/labjs/LAB.js b/phpgwapi/js/labjs/LAB.js
new file mode 100755
index 0000000000..e710dfea28
--- /dev/null
+++ b/phpgwapi/js/labjs/LAB.js
@@ -0,0 +1,5 @@
+/*! LAB.js (LABjs :: Loading And Blocking JavaScript)
+ v2.0.3 (c) Kyle Simpson
+ MIT License
+*/
+(function(o){var K=o.$LAB,y="UseLocalXHR",z="AlwaysPreserveOrder",u="AllowDuplicates",A="CacheBust",B="BasePath",C=/^[^?#]*\//.exec(location.href)[0],D=/^\w+\:\/\/\/?[^\/]+/.exec(C)[0],i=document.head||document.getElementsByTagName("head"),L=(o.opera&&Object.prototype.toString.call(o.opera)=="[object Opera]")||("MozAppearance"in document.documentElement.style),q=document.createElement("script"),E=typeof q.preload=="boolean",r=E||(q.readyState&&q.readyState=="uninitialized"),F=!r&&q.async===true,M=!r&&!F&&!L;function G(a){return Object.prototype.toString.call(a)=="[object Function]"}function H(a){return Object.prototype.toString.call(a)=="[object Array]"}function N(a,c){var b=/^\w+\:\/\//;if(/^\/\/\/?/.test(a)){a=location.protocol+a}else if(!b.test(a)&&a.charAt(0)!="/"){a=(c||"")+a}return b.test(a)?a:((a.charAt(0)=="/"?D:C)+a)}function s(a,c){for(var b in a){if(a.hasOwnProperty(b)){c[b]=a[b]}}return c}function O(a){var c=false;for(var b=0;b0){for(var a=0;a=0;){d=n.shift();a=a[d.type].apply(null,d.args)}return a},noConflict:function(){o.$LAB=K;return m},sandbox:function(){return J()}};return m}o.$LAB=J();(function(a,c,b){if(document.readyState==null&&document[a]){document.readyState="loading";document[a](c,b=function(){document.removeEventListener(c,b,false);document.readyState="complete"},false)}})("addEventListener","DOMContentLoaded")})(this);
\ No newline at end of file
diff --git a/phpgwapi/js/labjs/LAB.min.js b/phpgwapi/js/labjs/LAB.min.js
new file mode 100755
index 0000000000..e710dfea28
--- /dev/null
+++ b/phpgwapi/js/labjs/LAB.min.js
@@ -0,0 +1,5 @@
+/*! LAB.js (LABjs :: Loading And Blocking JavaScript)
+ v2.0.3 (c) Kyle Simpson
+ MIT License
+*/
+(function(o){var K=o.$LAB,y="UseLocalXHR",z="AlwaysPreserveOrder",u="AllowDuplicates",A="CacheBust",B="BasePath",C=/^[^?#]*\//.exec(location.href)[0],D=/^\w+\:\/\/\/?[^\/]+/.exec(C)[0],i=document.head||document.getElementsByTagName("head"),L=(o.opera&&Object.prototype.toString.call(o.opera)=="[object Opera]")||("MozAppearance"in document.documentElement.style),q=document.createElement("script"),E=typeof q.preload=="boolean",r=E||(q.readyState&&q.readyState=="uninitialized"),F=!r&&q.async===true,M=!r&&!F&&!L;function G(a){return Object.prototype.toString.call(a)=="[object Function]"}function H(a){return Object.prototype.toString.call(a)=="[object Array]"}function N(a,c){var b=/^\w+\:\/\//;if(/^\/\/\/?/.test(a)){a=location.protocol+a}else if(!b.test(a)&&a.charAt(0)!="/"){a=(c||"")+a}return b.test(a)?a:((a.charAt(0)=="/"?D:C)+a)}function s(a,c){for(var b in a){if(a.hasOwnProperty(b)){c[b]=a[b]}}return c}function O(a){var c=false;for(var b=0;b0){for(var a=0;a=0;){d=n.shift();a=a[d.type].apply(null,d.args)}return a},noConflict:function(){o.$LAB=K;return m},sandbox:function(){return J()}};return m}o.$LAB=J();(function(a,c,b){if(document.readyState==null&&document[a]){document.readyState="loading";document[a](c,b=function(){document.removeEventListener(c,b,false);document.readyState="complete"},false)}})("addEventListener","DOMContentLoaded")})(this);
\ No newline at end of file
diff --git a/phpgwapi/js/labjs/LAB.src.js b/phpgwapi/js/labjs/LAB.src.js
new file mode 100755
index 0000000000..99807cd222
--- /dev/null
+++ b/phpgwapi/js/labjs/LAB.src.js
@@ -0,0 +1,514 @@
+/*! LAB.js (LABjs :: Loading And Blocking JavaScript)
+ v2.0.3 (c) Kyle Simpson
+ MIT License
+*/
+
+(function(global){
+ var _$LAB = global.$LAB,
+
+ // constants for the valid keys of the options object
+ _UseLocalXHR = "UseLocalXHR",
+ _AlwaysPreserveOrder = "AlwaysPreserveOrder",
+ _AllowDuplicates = "AllowDuplicates",
+ _CacheBust = "CacheBust",
+ /*!START_DEBUG*/_Debug = "Debug",/*!END_DEBUG*/
+ _BasePath = "BasePath",
+
+ // stateless variables used across all $LAB instances
+ root_page = /^[^?#]*\//.exec(location.href)[0],
+ root_domain = /^\w+\:\/\/\/?[^\/]+/.exec(root_page)[0],
+ append_to = document.head || document.getElementsByTagName("head"),
+
+ // inferences... ick, but still necessary
+ opera_or_gecko = (global.opera && Object.prototype.toString.call(global.opera) == "[object Opera]") || ("MozAppearance" in document.documentElement.style),
+
+/*!START_DEBUG*/
+ // console.log() and console.error() wrappers
+ log_msg = function(){},
+ log_error = log_msg,
+/*!END_DEBUG*/
+
+ // feature sniffs (yay!)
+ test_script_elem = document.createElement("script"),
+ explicit_preloading = typeof test_script_elem.preload == "boolean", // http://wiki.whatwg.org/wiki/Script_Execution_Control#Proposal_1_.28Nicholas_Zakas.29
+ real_preloading = explicit_preloading || (test_script_elem.readyState && test_script_elem.readyState == "uninitialized"), // will a script preload with `src` set before DOM append?
+ script_ordered_async = !real_preloading && test_script_elem.async === true, // http://wiki.whatwg.org/wiki/Dynamic_Script_Execution_Order
+
+ // XHR preloading (same-domain) and cache-preloading (remote-domain) are the fallbacks (for some browsers)
+ xhr_or_cache_preloading = !real_preloading && !script_ordered_async && !opera_or_gecko
+ ;
+
+/*!START_DEBUG*/
+ // define console wrapper functions if applicable
+ if (global.console && global.console.log) {
+ if (!global.console.error) global.console.error = global.console.log;
+ log_msg = function(msg) { global.console.log(msg); };
+ log_error = function(msg,err) { global.console.error(msg,err); };
+ }
+/*!END_DEBUG*/
+
+ // test for function
+ function is_func(func) { return Object.prototype.toString.call(func) == "[object Function]"; }
+
+ // test for array
+ function is_array(arr) { return Object.prototype.toString.call(arr) == "[object Array]"; }
+
+ // make script URL absolute/canonical
+ function canonical_uri(src,base_path) {
+ var absolute_regex = /^\w+\:\/\//;
+
+ // is `src` is protocol-relative (begins with // or ///), prepend protocol
+ if (/^\/\/\/?/.test(src)) {
+ src = location.protocol + src;
+ }
+ // is `src` page-relative? (not an absolute URL, and not a domain-relative path, beginning with /)
+ else if (!absolute_regex.test(src) && src.charAt(0) != "/") {
+ // prepend `base_path`, if any
+ src = (base_path || "") + src;
+ }
+ // make sure to return `src` as absolute
+ return absolute_regex.test(src) ? src : ((src.charAt(0) == "/" ? root_domain : root_page) + src);
+ }
+
+ // merge `source` into `target`
+ function merge_objs(source,target) {
+ for (var k in source) { if (source.hasOwnProperty(k)) {
+ target[k] = source[k]; // TODO: does this need to be recursive for our purposes?
+ }}
+ return target;
+ }
+
+ // does the chain group have any ready-to-execute scripts?
+ function check_chain_group_scripts_ready(chain_group) {
+ var any_scripts_ready = false;
+ for (var i=0; i 0) {
+ for (var i=0; i=0;) {
+ val = queue.shift();
+ $L = $L[val.type].apply(null,val.args);
+ }
+ return $L;
+ },
+
+ // rollback `[global].$LAB` to what it was before this file was loaded, the return this current instance of $LAB
+ noConflict:function(){
+ global.$LAB = _$LAB;
+ return instanceAPI;
+ },
+
+ // create another clean instance of $LAB
+ sandbox:function(){
+ return create_sandbox();
+ }
+ };
+
+ return instanceAPI;
+ }
+
+ // create the main instance of $LAB
+ global.$LAB = create_sandbox();
+
+
+ /* The following "hack" was suggested by Andrea Giammarchi and adapted from: http://webreflection.blogspot.com/2009/11/195-chars-to-help-lazy-loading.html
+ NOTE: this hack only operates in FF and then only in versions where document.readyState is not present (FF < 3.6?).
+
+ The hack essentially "patches" the **page** that LABjs is loaded onto so that it has a proper conforming document.readyState, so that if a script which does
+ proper and safe dom-ready detection is loaded onto a page, after dom-ready has passed, it will still be able to detect this state, by inspecting the now hacked
+ document.readyState property. The loaded script in question can then immediately trigger any queued code executions that were waiting for the DOM to be ready.
+ For instance, jQuery 1.4+ has been patched to take advantage of document.readyState, which is enabled by this hack. But 1.3.2 and before are **not** safe or
+ fixed by this hack, and should therefore **not** be lazy-loaded by script loader tools such as LABjs.
+ */
+ (function(addEvent,domLoaded,handler){
+ if (document.readyState == null && document[addEvent]){
+ document.readyState = "loading";
+ document[addEvent](domLoaded,handler = function(){
+ document.removeEventListener(domLoaded,handler,false);
+ document.readyState = "complete";
+ },false);
+ }
+ })("addEventListener","DOMContentLoaded");
+
+})(this);
\ No newline at end of file