From 592b7fb97dc6820bc1b411b9b72dada4b605dc14 Mon Sep 17 00:00:00 2001 From: Ralf Becker Date: Sat, 5 Jun 2021 20:39:39 +0200 Subject: [PATCH] replace LAB.js with native es5 loading --- api/config.php | 6 +- api/images.php | 2 +- api/js/egw_action/egw_action_common.js | 2 +- api/js/egw_json.js | 1375 ++++++++--------- api/js/framework/fw_base.js | 4 +- api/js/framework/fw_browser.js | 13 +- api/js/framework/fw_classes.js | 210 ++- api/js/framework/fw_desktop.js | 12 +- api/js/framework/fw_ui.js | 94 +- .../jquery-tap-and-hold/jquery.tapandhold.js | 1 + api/js/jquery/jquery-ui-timepicker-addon.js | 2 + api/js/jquery/jquery.noconflict.js | 1 + api/js/jsapi/app_base.js | 3 +- api/js/jsapi/egw.js | 51 +- api/js/jsapi/egw_app.js | 327 ++-- api/js/jsapi/egw_calendar.js | 1 + api/js/jsapi/egw_config.js | 1 + api/js/jsapi/egw_css.js | 1 + api/js/jsapi/egw_data.js | 2 + api/js/jsapi/egw_debug.js | 1 + api/js/jsapi/egw_files.js | 9 +- api/js/jsapi/egw_images.js | 1 + api/js/jsapi/egw_jquery.js | 1 + api/js/jsapi/egw_json.js | 12 +- api/js/jsapi/egw_jsonq.js | 1 + api/js/jsapi/egw_lang.js | 1 + api/js/jsapi/egw_links.js | 1 + api/js/jsapi/egw_message.js | 2 + api/js/jsapi/egw_notification.js | 1 + api/js/jsapi/egw_open.js | 1 + api/js/jsapi/egw_preferences.js | 1 + api/js/jsapi/egw_ready.js | 1 + api/js/jsapi/egw_store.js | 1 + api/js/jsapi/egw_tail.js | 6 +- api/js/jsapi/egw_tooltip.js | 1 + api/js/jsapi/egw_user.js | 1 + api/js/jsapi/egw_utils.js | 1 + api/js/jsapi/jsapi.js | 120 +- api/js/labjs/LAB-debug.min.js | 5 - api/js/labjs/LAB.js | 5 - api/js/labjs/LAB.min.js | 5 - api/js/labjs/LAB.src.js | 514 ------ api/js/login.js | 2 + api/lang.php | 5 +- api/src/Framework.php | 46 +- api/src/Framework/Ajax.php | 4 +- api/src/Framework/Bundle.php | 3 +- api/src/Framework/IncludeMgr.php | 136 +- api/src/Header/ContentSecurityPolicy.php | 18 + api/user.php | 7 +- notifications/inc/hook_after_navbar.inc.php | 2 +- notifications/js/notificationajaxpopup.js | 10 +- pixelegg/js/fw_pixelegg.js | 8 +- pixelegg/login.tpl | 2 +- 54 files changed, 1258 insertions(+), 1785 deletions(-) delete mode 100755 api/js/labjs/LAB-debug.min.js delete mode 100755 api/js/labjs/LAB.js delete mode 100755 api/js/labjs/LAB.min.js delete mode 100755 api/js/labjs/LAB.src.js diff --git a/api/config.php b/api/config.php index 1af9594458..8aaa43abd9 100644 --- a/api/config.php +++ b/api/config.php @@ -43,8 +43,10 @@ if (isset($_SERVER['HTTP_IF_NONE_MATCH']) && $_SERVER['HTTP_IF_NONE_MATCH'] == $ exit; } -$content = 'egw.set_configs('.$config.", egw && egw.window !== window);\n"; -$content .= 'egw.set_link_registry('.$link_registry.", undefined, egw && egw.window !== window);\n"; +$content = "import './js/jsapi/egw_config.js';\n"; +$content .= "import './js/jsapi/egw_links.js';\n\n"; +$content .= 'window.egw.set_configs('.$config.", window.egw && window.egw.window !== window);\n"; +$content .= 'window.egw.set_link_registry('.$link_registry.", undefined, window.egw && window.egw.window !== window);\n"; // we run our own gzip compression, to set a correct Content-Length of the encoded content if (in_array('gzip', explode(',',$_SERVER['HTTP_ACCEPT_ENCODING'])) && function_exists('gzencode')) diff --git a/api/images.php b/api/images.php index 0d82d5aecd..2d58dad7e9 100644 --- a/api/images.php +++ b/api/images.php @@ -48,7 +48,7 @@ if (isset($_SERVER['HTTP_IF_NONE_MATCH']) && $_SERVER['HTTP_IF_NONE_MATCH'] == $ exit; } -if (empty($_GET['debug'])) $content = 'egw.set_images('.$content.", egw && egw.window !== window);\n"; +if (empty($_GET['debug'])) $content = "import './js/jsapi/egw_images.js';\n\nwindow.egw.set_images(".$content.", window.egw && window.egw.window !== window);\n"; // we run our own gzip compression, to set a correct Content-Length of the encoded content if (in_array('gzip', explode(',',$_SERVER['HTTP_ACCEPT_ENCODING'])) && function_exists('gzencode')) diff --git a/api/js/egw_action/egw_action_common.js b/api/js/egw_action/egw_action_common.js index e5e46eaa11..47191357a8 100644 --- a/api/js/egw_action/egw_action_common.js +++ b/api/js/egw_action/egw_action_common.js @@ -451,7 +451,7 @@ egwFnct.prototype.exec = function() */ var _egw_mobileBrowser = null; -function egwIsMobile() { +window.egwIsMobile = function() { if (_egw_mobileBrowser == null) { diff --git a/api/js/egw_json.js b/api/js/egw_json.js index 38c58d6e6a..b284096cd6 100644 --- a/api/js/egw_json.js +++ b/api/js/egw_json.js @@ -15,789 +15,698 @@ */ /* The egw_json_request is the javaScript side implementation of class.egw_json.inc.php.*/ +(function() { + "use strict"; -function _egw_json_escape_string(input) -{ - var len = input.length; - var res = ""; + function _egw_json_escape_string(input) { + var len = input.length; + var res = ""; - for (var i = 0; i < len; i++) - { - switch (input.charAt(i)) - { - case '"': - res += '\\"'; - break; + for (var i = 0; i < len; i++) { + switch (input.charAt(i)) { + case '"': + res += '\\"'; + break; - case '\n': - res += '\\n'; - break; + case '\n': + res += '\\n'; + break; - case '\r': - res += '\\r'; - break; + case '\r': + res += '\\r'; + break; - case '\\': - res += '\\\\'; - break; + case '\\': + res += '\\\\'; + break; - case '\/': - res += '\\/'; - break; + case '\/': + res += '\\/'; + break; - case '\b': - res += '\\b'; - break; + case '\b': + res += '\\b'; + break; - case '\f': - res += '\\f'; - break; + case '\f': + res += '\\f'; + break; - case '\t': - res += '\\t'; - break; + case '\t': + res += '\\t'; + break; + + default: + res += input.charAt(i); + } + } + + return res; + } + + function _egw_json_encode_simple(input) { + switch (input.constructor) { + case String: + return '"' + _egw_json_escape_string(input) + '"'; + + case Number: + return input.toString(); + + case Boolean: + return input ? 'true' : 'false'; default: - res += input.charAt(i); + return null; } } - return res; -} - -function _egw_json_encode_simple(input) -{ - switch (input.constructor) - { - case String: - return '"' + _egw_json_escape_string(input) + '"'; - - case Number: - return input.toString(); - - case Boolean: - return input ? 'true' : 'false'; - - default: - return null; + window.egw_json_encode = function (input) { + egw.debug("warn", "Function %s is deprecated, use egw.jsonEncode() instead", arguments.callee.name); + return egw.jsonEncode(input); } -} - -function egw_json_encode(input) -{ - egw.debug("warn", "Function %s is deprecated, use egw.jsonEncode() instead", arguments.callee.name); - return egw.jsonEncode(input); -} -/** - * Some variables needed to store which JS and CSS files have already be included - */ -var egw_json_files = {}; + /** + * Some variables needed to store which JS and CSS files have already be included + */ + var egw_json_files = {}; -/** - * Initialize the egw_json_files object with all files which are already bound in - */ -jQuery(document).ready(function() { - jQuery("script, link").each(function() { - var file = false; - if (jQuery(this).attr("src")) { - file = jQuery(this).attr("src"); - } else if (jQuery(this).attr("href")) { - file = jQuery(this).attr("href"); - } - if (file) { - egw_json_files[file] = true; - } + /** + * Initialize the egw_json_files object with all files which are already bound in + */ + jQuery(document).ready(function () { + jQuery("script, link").each(function () { + var file = false; + if (jQuery(this).attr("src")) { + file = jQuery(this).attr("src"); + } else if (jQuery(this).attr("href")) { + file = jQuery(this).attr("href"); + } + if (file) { + egw_json_files[file] = true; + } + }); }); -}); -/** - * Variable which stores all currently registered plugins - */ -var _egw_json_plugins = []; + /** + * Variable which stores all currently registered plugins + */ + var _egw_json_plugins = []; -/** - * Register a plugin for the egw_json handler - */ -function egw_json_register_plugin(_callback, _context) -{ - egw.debug("warn", "Function %s is deprecated", arguments.callee.name); - //Default the context parameter to "window" - if (typeof _context == 'undefined') { - _context = window; - } - - //Add a plugin object to the plugins array - _egw_json_plugins[_egw_json_plugins.length] = { - 'callback': _callback, - 'context': _context - }; -} - -/** - * Function used internally to pass a response to all registered plugins - */ -function _egw_json_plugin_handle(_type, _response, _context) { - for (var i = 0; i < _egw_json_plugins.length; i++) - { - try { - var plugin = _egw_json_plugins[i]; - - var context = plugin.context; - if (!plugin.context && typeof _context != "undefined") - { - context = _context; - } - - if (plugin.callback.call(context, _type, _response)) { - return true; - } - } catch (e) { - if (typeof console != 'undefined') - { - console.log(e); - } + /** + * Register a plugin for the egw_json handler + */ + window.egw_json_register_plugin = function (_callback, _context) { + egw.debug("warn", "Function %s is deprecated", arguments.callee.name); + //Default the context parameter to "window" + if (typeof _context == 'undefined') { + _context = window; } + + //Add a plugin object to the plugins array + _egw_json_plugins[_egw_json_plugins.length] = { + 'callback': _callback, + 'context': _context + }; } - return false; -} + /** + * Function used internally to pass a response to all registered plugins + */ + function _egw_json_plugin_handle(_type, _response, _context) { + for (var i = 0; i < _egw_json_plugins.length; i++) { + try { + var plugin = _egw_json_plugins[i]; -/** The constructor of the egw_json_request class. - * - * @param string _menuaction the menuaction function which should be called and - * which handles the actual request. If the menuaction is a full featured - * url, this one will be used instead. - * @param array _parameters which should be passed to the menuaction function. - * @param object _context is the context which will be used for the callbacks (not callback of sendRequest!) - */ -function egw_json_request(_menuaction, _parameters, _context) -{ - egw.debug("warn", "Function %s is deprecated", arguments.callee.name); - this.context = window.document; - if (typeof _context != 'undefined') - this.context = _context; + var context = plugin.context; + if (!plugin.context && typeof _context != "undefined") { + context = _context; + } - if (typeof _parameters != 'undefined') - { - this.parameters = _parameters; - } - else - { - this.parameters = new Array; - } - - // Check whether the supplied menuaction parameter is a full featured url - // or just a menuaction - if (_menuaction.match(/json.php\?menuaction=[a-z_0-9]*\.[a-z_0-9]*\.[a-z_0-9]*/i)) - { - // Menuaction is a full featured url - this.url = _menuaction; - } - else - { - // We only got a menu action, assemble the url manually. - this.url = this._assembleAjaxUrl(_menuaction); - } - - this.request = null; - this.sender = null; - this.callback = null; - this.alertHandler = this.alertFunc; - this.onLoadFinish = null; - this.loadedJSFiles = {}; - this.handleResponseDone = false; - this.app = null; - if (window.egw_alertHandler) - { - this.alertHandler = window.egw_alertHandler; - } -} - -/** - * Sets the "application" object which is passed to egw_appWindowOpen when a redirect is done - */ -egw_json_request.prototype.setAppObject = function(_app) -{ - this.app = _app; -} - -egw_json_request.prototype._assembleAjaxUrl = function(_menuaction) -{ - // Retrieve the webserver url - var webserver_url = window.egw_webserverUrl || egw_topWindow().egw_webserverUrl; - - // Check whether the webserver_url is really set - // Don't check for !webserver_url as it might be empty. - // Thank you to Ingo Ratsdorf for reporting this. - if (typeof webserver_url == "undefined") - { - throw "Internal JS error, top window not found, webserver url could not be retrieved."; - } - - // Add the ajax relevant parts - return webserver_url + '/json.php?menuaction=' + _menuaction; -} - -/** - * Sends the AJAX JSON request. - * - * @param boolean _async specifies whether the request should be handeled asynchronously (true, the sendRequest function immediately returns to the caller) or asynchronously (false, the sendRequest function waits until the request is received) - * @param _callback is an additional callback function which should be called upon a "data" response is received - * @param _sender context (this) of _callback (different from _context param of constructor used for standard callbacks!) -*/ -egw_json_request.prototype.sendRequest = function(_async, _callback, _sender) -{ - egw.debug("warn", "egw_json_request is deprecated\n\ -Use egw.json(menuaction, parameters [,callback, context, async, sender]).sendRequest() instead."); - //Store the sender and callback parameter inside this class - this.sender = _sender; - if (typeof _callback != "undefined") - this.callback = _callback; - - //Copy the async parameter which defaults to "true" - var is_async = true; - if (typeof _async != "undefined") - is_async = _async; - - //Assemble the actual request object containing the json data string - var request_obj = { - "json_data": egw.jsonEncode( - { - "request": { - "parameters": this.parameters - } - }) - }; - - //Send the request via the jquery AJAX interface to the server - this.request = jQuery.ajax({url: this.url, - async: is_async, - context: this, - data: request_obj, - dataType: 'json', - type: 'POST', - success: this.handleResponse, - error: function(_xmlhttp,_err) { - window.console.error('Ajax request to ' + this.url + ' failed: ' + _err); - } - }); -} - -egw_json_request.prototype.abort = function() -{ - this.request.abort(); -} - -egw_json_request.prototype.alertFunc = function(_message, _details) -{ - alert(_message); - if(_details) _egw_json_debug_log(_message, _details); -} - -function _egw_json_debug_log(_msg, _e) -{ - if (typeof console != "undefined" && typeof console.log != "undefined") - { - console.log(_msg, _e); - } -} - -/* Displays an json error message */ -egw_json_request.prototype.jsonError = function(_msg, _e) -{ - var msg = 'EGW JSON Error: '+_msg; - - //Log and show the error message - _egw_json_debug_log(msg, _e); - this.alertHandler(msg); -} - -/* Internal function which handles the response from the server */ -egw_json_request.prototype.handleResponse = function(data, textStatus, XMLHttpRequest) -{ - this.handleResponseDone = false; - if (data && data.response) - { - var hasResponse = false; - // Try to load files using API - if(egw && egw().includeJS) - { - var js_files = []; - var css_files = []; - for (var i = data.response.length - 1; i > 0; --i) - { - var res = data.response[i]; - if(res.type == 'js' && typeof res.data == 'string') - { - js_files.unshift(res.data); - this.loadedJSFiles[res.data] = false; - data.response.splice(i,1); + if (plugin.callback.call(context, _type, _response)) { + return true; + } + } catch (e) { + if (typeof console != 'undefined') { + console.log(e); } } - if(js_files.length > 0) - { - egw().includeJS(js_files, function() { - for(var i = 0; i < js_files.length; i++) - { - this.loadedJSFiles[js_files[i]] = true; - } - this.checkLoadFinish(); - },this); - } } - for (var i = 0; i < data.response.length; i++) - { - try - { - var res = data.response[i]; - switch (data.response[i].type) + return false; + } + + /** The constructor of the egw_json_request class. + * + * @param string _menuaction the menuaction function which should be called and + * which handles the actual request. If the menuaction is a full featured + * url, this one will be used instead. + * @param array _parameters which should be passed to the menuaction function. + * @param object _context is the context which will be used for the callbacks (not callback of sendRequest!) + */ + window.egw_json_request = function (_menuaction, _parameters, _context) { + egw.debug("warn", "Function %s is deprecated", arguments.callee.name); + this.context = window.document; + if (typeof _context != 'undefined') + this.context = _context; + + if (typeof _parameters != 'undefined') { + this.parameters = _parameters; + } else { + this.parameters = new Array; + } + + // Check whether the supplied menuaction parameter is a full featured url + // or just a menuaction + if (_menuaction.match(/json.php\?menuaction=[a-z_0-9]*\.[a-z_0-9]*\.[a-z_0-9]*/i)) { + // Menuaction is a full featured url + this.url = _menuaction; + } else { + // We only got a menu action, assemble the url manually. + this.url = this._assembleAjaxUrl(_menuaction); + } + + this.request = null; + this.sender = null; + this.callback = null; + this.alertHandler = this.alertFunc; + this.onLoadFinish = null; + this.loadedJSFiles = {}; + this.handleResponseDone = false; + this.app = null; + if (window.egw_alertHandler) { + this.alertHandler = window.egw_alertHandler; + } + } + + /** + * Sets the "application" object which is passed to egw_appWindowOpen when a redirect is done + */ + window.egw_json_request.prototype.setAppObject = function (_app) { + this.app = _app; + } + + window.egw_json_request.prototype._assembleAjaxUrl = function (_menuaction) { + // Retrieve the webserver url + var webserver_url = window.egw_webserverUrl || egw_topWindow().egw_webserverUrl; + + // Check whether the webserver_url is really set + // Don't check for !webserver_url as it might be empty. + // Thank you to Ingo Ratsdorf for reporting this. + if (typeof webserver_url == "undefined") { + throw "Internal JS error, top window not found, webserver url could not be retrieved."; + } + + // Add the ajax relevant parts + return webserver_url + '/json.php?menuaction=' + _menuaction; + } + + /** + * Sends the AJAX JSON request. + * + * @param boolean _async specifies whether the request should be handeled asynchronously (true, the sendRequest function immediately returns to the caller) or asynchronously (false, the sendRequest function waits until the request is received) + * @param _callback is an additional callback function which should be called upon a "data" response is received + * @param _sender context (this) of _callback (different from _context param of constructor used for standard callbacks!) + */ + window.egw_json_request.prototype.sendRequest = function (_async, _callback, _sender) { + egw.debug("warn", "egw_json_request is deprecated\n\ +Use egw.json(menuaction, parameters [,callback, context, async, sender]).sendRequest() instead."); + //Store the sender and callback parameter inside this class + this.sender = _sender; + if (typeof _callback != "undefined") + this.callback = _callback; + + //Copy the async parameter which defaults to "true" + var is_async = true; + if (typeof _async != "undefined") + is_async = _async; + + //Assemble the actual request object containing the json data string + var request_obj = { + "json_data": egw.jsonEncode( { - case 'alert': - //Check whether all needed parameters have been passed and call the alertHandler function - if ((typeof res.data.message != 'undefined') && - (typeof res.data.details != 'undefined')) - { - this.alertHandler( - res.data.message, - res.data.details) - hasResponse = true; - } else - throw 'Invalid parameters'; - break; - case 'assign': - //Check whether all needed parameters have been passed and call the alertHandler function - if ((typeof res.data.id != 'undefined') && - (typeof res.data.key != 'undefined') && - (typeof res.data.value != 'undefined')) - { - var obj = document.getElementById(res.data.id); - if (obj) - { - obj[res.data.key] = res.data.value; + "request": { + "parameters": this.parameters + } + }) + }; - if (res.data.key == "innerHTML") - { - egw_insertJS(res.data.value); + //Send the request via the jquery AJAX interface to the server + this.request = jQuery.ajax({ + url: this.url, + async: is_async, + context: this, + data: request_obj, + dataType: 'json', + type: 'POST', + success: this.handleResponse, + error: function (_xmlhttp, _err) { + window.console.error('Ajax request to ' + this.url + ' failed: ' + _err); + } + }); + } + + window.egw_json_request.prototype.abort = function () { + this.request.abort(); + } + + window.egw_json_request.prototype.alertFunc = function (_message, _details) { + alert(_message); + if (_details) _egw_json_debug_log(_message, _details); + } + + function _egw_json_debug_log(_msg, _e) { + if (typeof console != "undefined" && typeof console.log != "undefined") { + console.log(_msg, _e); + } + } + + /* Displays an json error message */ + window.egw_json_request.prototype.jsonError = function (_msg, _e) { + var msg = 'EGW JSON Error: ' + _msg; + + //Log and show the error message + _egw_json_debug_log(msg, _e); + this.alertHandler(msg); + } + + /* Internal function which handles the response from the server */ + window.egw_json_request.prototype.handleResponse = function (data, textStatus, XMLHttpRequest) { + this.handleResponseDone = false; + if (data && data.response) { + var hasResponse = false; + // Try to load files using API + if (egw && egw().includeJS) { + var js_files = []; + var css_files = []; + for (var i = data.response.length - 1; i > 0; --i) { + var res = data.response[i]; + if (res.type == 'js' && typeof res.data == 'string') { + js_files.unshift(res.data); + this.loadedJSFiles[res.data] = false; + data.response.splice(i, 1); + } + } + if (js_files.length > 0) { + egw().includeJS(js_files, function () { + for (var i = 0; i < js_files.length; i++) { + this.loadedJSFiles[js_files[i]] = true; + } + this.checkLoadFinish(); + }, this); + } + } + for (var i = 0; i < data.response.length; i++) { + try { + var res = data.response[i]; + + switch (data.response[i].type) { + case 'alert': + //Check whether all needed parameters have been passed and call the alertHandler function + if ((typeof res.data.message != 'undefined') && + (typeof res.data.details != 'undefined')) { + this.alertHandler( + res.data.message, + res.data.details) + hasResponse = true; + } else + throw 'Invalid parameters'; + break; + case 'assign': + //Check whether all needed parameters have been passed and call the alertHandler function + if ((typeof res.data.id != 'undefined') && + (typeof res.data.key != 'undefined') && + (typeof res.data.value != 'undefined')) { + var obj = document.getElementById(res.data.id); + if (obj) { + obj[res.data.key] = res.data.value; + + if (res.data.key == "innerHTML") { + egw_insertJS(res.data.value); + } + + hasResponse = true; + } + } else + throw 'Invalid parameters'; + break; + case 'data': + //Callback the caller in order to allow him to handle the data + if (this.callback) { + this.callback.call(this.sender, res.data); + hasResponse = true; + } + break; + case 'script': + if (typeof res.data == 'string') { + try { + var func = new Function(res.data); + func.call(window); + } catch (e) { + e.code = res.data; + _egw_json_debug_log(e); + } + hasResponse = true; + } else + throw 'Invalid parameters'; + break; + case 'apply': + if (typeof res.data.func == 'string' && typeof window[res.data.func] == 'function') { + try { + window[res.data.func].apply(window, res.data.parms); + } catch (e) { + _egw_json_debug_log(e, {'Function': res.data.func, 'Parameters': res.data.parms}); + } + hasResponse = true; + } else if (typeof res.data.func == "string" && + res.data.func.substr(0, 4) == "app." && app) { + + var parts = res.data.func.split("."); + // check if we need a not yet instanciated app.js object --> instanciate it now + if (parts.length == 3 && typeof app[parts[1]] == 'undefined' && + typeof app.classes[parts[1]] == 'function') { + app[parts[1]] = new app.classes[parts[1]](); + } + if (parts.length == 3 && typeof app[parts[1]] == "object" && + typeof app[parts[1]][parts[2]] == "function") { + try { + this.context = app[parts[1]][parts[2]].apply(app[parts[1]], res.data.parms); + } catch (e) { + _egw_json_debug_log(e, { + 'Function': res.data.func, + 'Parameters': res.data.parms + }); + } + } + hasResponse = true; + + } else + throw 'Invalid parameters'; + break; + case 'jquery': + if (typeof res.data.select == 'string' && + typeof res.data.func == 'string') { + try { + var jQueryObject = jQuery(res.data.select, this.context); + jQueryObject[res.data.func].apply(jQueryObject, res.data.parms); + } catch (e) { + _egw_json_debug_log(e, {'Function': res.data.func, 'Parameters': res.data.parms}); + } + hasResponse = true; + } else + throw 'Invalid parameters'; + break; + case 'redirect': + //console.log(res.data.url); + if (typeof res.data.url == 'string' && + typeof res.data.global == 'boolean' && + typeof res.data.app == 'string') { + //Special handling for framework reload + res.data.global |= (res.data.url.indexOf("?cd=10") > 0); + + if (res.data.global) { + egw_topWindow().location.href = res.data.url; + } else { + egw_appWindowOpen(res.data.app, res.data.url); } hasResponse = true; - } - } else - throw 'Invalid parameters'; - break; - case 'data': - //Callback the caller in order to allow him to handle the data - if (this.callback) - { - this.callback.call(this.sender, res.data); - hasResponse = true; - } - break; - case 'script': - if (typeof res.data == 'string') - { - try - { - var func = new Function(res.data); - func.call(window); - } - catch (e) - { - e.code = res.data; - _egw_json_debug_log(e); - } - hasResponse = true; - } else - throw 'Invalid parameters'; - break; - case 'apply': - if (typeof res.data.func == 'string' && typeof window[res.data.func] == 'function') - { - try - { - window[res.data.func].apply(window, res.data.parms); - } - catch (e) - { - _egw_json_debug_log(e, {'Function': res.data.func, 'Parameters': res.data.parms}); - } - hasResponse = true; - } else if (typeof res.data.func == "string" && - res.data.func.substr(0,4) == "app." && app) - { + } else + throw 'Invalid parameters'; + break; + case 'css': + if (typeof res.data == 'string') { + //Check whether the requested file had already be included + if (!egw_json_files[res.data]) { + egw_json_files[res.data] = true; - var parts = res.data.func.split("."); - // check if we need a not yet instanciated app.js object --> instanciate it now - if (parts.length == 3 && typeof app[parts[1]] == 'undefined' && - typeof app.classes[parts[1]] == 'function') - { - app[parts[1]] = new app.classes[parts[1]](); - } - if(parts.length == 3 && typeof app[parts[1]] == "object" && - typeof app[parts[1]][parts[2]] == "function") - { - try - { - this.context = app[parts[1]][parts[2]].apply(app[parts[1]], res.data.parms); + //Get the head node and append a new link node with the stylesheet url to it + var headID = document.getElementsByTagName('head')[0]; + var cssnode = document.createElement('link'); + cssnode.type = "text/css"; + cssnode.rel = "stylesheet"; + cssnode.href = res.data; + headID.appendChild(cssnode); } - catch (e) - { - _egw_json_debug_log(e, {'Function': res.data.func, 'Parameters': res.data.parms}); - } - } - hasResponse = true; + hasResponse = true; + } else + throw 'Invalid parameters'; + break; + case 'js': + if (typeof res.data == 'string') { + //Check whether the requested file had already be included + if (!egw_json_files[res.data]) { + egw_json_files[res.data] = true; - } else - throw 'Invalid parameters'; - break; - case 'jquery': - if (typeof res.data.select == 'string' && - typeof res.data.func == 'string') - { - try - { - var jQueryObject = jQuery(res.data.select, this.context); - jQueryObject[res.data.func].apply(jQueryObject, res.data.parms); - } - catch (e) - { - _egw_json_debug_log(e, {'Function': res.data.func, 'Parameters': res.data.parms}); - } - hasResponse = true; - } else - throw 'Invalid parameters'; - break; - case 'redirect': - //console.log(res.data.url); - if (typeof res.data.url == 'string' && - typeof res.data.global == 'boolean' && - typeof res.data.app == 'string') - { - //Special handling for framework reload - res.data.global |= (res.data.url.indexOf("?cd=10") > 0); + //Get the head node and append a new script node with the js file to it + var headID = document.getElementsByTagName('head')[0]; + var scriptnode = document.createElement('script'); + scriptnode.type = "text/javascript"; + scriptnode.src = res.data; + scriptnode._originalSrc = res.data; + headID.appendChild(scriptnode); - if (res.data.global) - { - egw_topWindow().location.href = res.data.url; - } - else - { - egw_appWindowOpen(res.data.app, res.data.url); - } + //Increment the includedJSFiles count + this.loadedJSFiles[res.data] = false; - hasResponse = true; - } else - throw 'Invalid parameters'; - break; - case 'css': - if (typeof res.data == 'string') - { - //Check whether the requested file had already be included - if (!egw_json_files[res.data]) - { - egw_json_files[res.data] = true; - - //Get the head node and append a new link node with the stylesheet url to it - var headID = document.getElementsByTagName('head')[0]; - var cssnode = document.createElement('link'); - cssnode.type = "text/css"; - cssnode.rel = "stylesheet"; - cssnode.href = res.data; - headID.appendChild(cssnode); - } - hasResponse = true; - } else - throw 'Invalid parameters'; - break; - case 'js': - if (typeof res.data == 'string') - { - //Check whether the requested file had already be included - if (!egw_json_files[res.data]) - { - egw_json_files[res.data] = true; - - //Get the head node and append a new script node with the js file to it - var headID = document.getElementsByTagName('head')[0]; - var scriptnode = document.createElement('script'); - scriptnode.type = "text/javascript"; - scriptnode.src = res.data; - scriptnode._originalSrc = res.data; - headID.appendChild(scriptnode); - - //Increment the includedJSFiles count - this.loadedJSFiles[res.data] = false; - - if (typeof console != 'undefined' && typeof console.log != 'undefined') - console.log("Requested JS file '%s' from server", res.data); - - var self = this; - - //FF, Opera, Chrome - scriptnode.onload = function(e) { - var file = e.target._originalSrc; if (typeof console != 'undefined' && typeof console.log != 'undefined') - console.log("Retrieved JS file '%s' from server", file); + console.log("Requested JS file '%s' from server", res.data); - self.loadedJSFiles[file] = true; - self.checkLoadFinish(); - }; + var self = this; - //IE - if (typeof scriptnode.readyState != 'undefined') - { - if (scriptnode.readyState != 'complete' && - scriptnode.readyState != 'loaded') - { - scriptnode.onreadystatechange = function() { - var node = window.event.srcElement; - if (node.readyState == 'complete' || node.readyState == 'loaded') { - var file = node._originalSrc; - if (typeof console != 'undefined' && typeof console.log != 'undefined') - console.log("Retrieved JS file '%s' from server", [file]); + //FF, Opera, Chrome + scriptnode.onload = function (e) { + var file = e.target._originalSrc; + if (typeof console != 'undefined' && typeof console.log != 'undefined') + console.log("Retrieved JS file '%s' from server", file); - self.loadedJSFiles[file] = true; - self.checkLoadFinish(); - } - }; - } - else - { - this.loadedJSFiles[res.data] = true; + self.loadedJSFiles[file] = true; + self.checkLoadFinish(); + }; + + //IE + if (typeof scriptnode.readyState != 'undefined') { + if (scriptnode.readyState != 'complete' && + scriptnode.readyState != 'loaded') { + scriptnode.onreadystatechange = function () { + var node = window.event.srcElement; + if (node.readyState == 'complete' || node.readyState == 'loaded') { + var file = node._originalSrc; + if (typeof console != 'undefined' && typeof console.log != 'undefined') + console.log("Retrieved JS file '%s' from server", [file]); + + self.loadedJSFiles[file] = true; + self.checkLoadFinish(); + } + }; + } else { + this.loadedJSFiles[res.data] = true; + } } } - } - hasResponse = true; - } else - throw 'Invalid parameters'; - break; - case 'error': - if (typeof res.data == 'string') - { - this.jsonError(res.data); - hasResponse = true; - } else - throw 'Invalid parameters'; - break; - } + hasResponse = true; + } else + throw 'Invalid parameters'; + break; + case 'error': + if (typeof res.data == 'string') { + this.jsonError(res.data); + hasResponse = true; + } else + throw 'Invalid parameters'; + break; + } - //Try to handle the json response with all registered plugins - hasResponse |= _egw_json_plugin_handle(data.response[i].type, res, this.context); - } catch(e) { - this.jsonError('Internal JSON handler error', e); - } - } - - /* If no explicit response has been specified, call the callback (if one was set) */ - if (!hasResponse && this.callback && data.response[i]) - { - this.callback.call(this.sender, data.response[i].data); - } - - this.handleResponseDone = true; - - this.checkLoadFinish(); - } -} - -/** - * The "onLoadFinish" handler gets called after all JS-files have been loaded - * successfully - */ -egw_json_request.prototype.checkLoadFinish = function() -{ - var complete = true; - for (var key in this.loadedJSFiles) { - complete = complete && this.loadedJSFiles[key]; - } - - if (complete && this.onLoadFinish && this.handleResponseDone) - { - this.onLoadFinish.call(this.sender); - } -} - -function egw_json_getFormValues(_form, _filterClass) -{ - egw.debug("warn", "Function %s is deprecated", arguments.callee.name); - var elem = null; - if (typeof _form == 'object') - { - elem = _form; - } - else - { - elem = document.getElementsByName(_form)[0]; - } - - var serialized = new Object; - if (typeof elem != "undefined" && elem && elem.childNodes) - { - if (typeof _filterClass == 'undefined') - _filterClass = null; - - _egw_json_getFormValues(serialized, elem.childNodes, _filterClass) - } - - return serialized; -} - -/** - * Deprecated legacy xajax wrapper functions for the new egw_json interface - */ -_xajax_doXMLHTTP = function(_async, _menuaction, _arguments) -{ - egw.debug("warn", "Function %s is deprecated", arguments.callee.name); - /* Assemble the parameter array */ - var paramarray = new Array(); - for (var i = 1; i < _arguments.length; i++) - { - paramarray[paramarray.length] = _arguments[i]; - } - - /* Create a new request, passing the menuaction and the parameter array */ - var request = new egw_json_request(_menuaction, paramarray); - - /* Send the request */ - request.sendRequest(_async); - - return request; -} - -xajax_doXMLHTTP = function(_menuaction) -{ - return _xajax_doXMLHTTP(true, _menuaction, arguments); -} - -xajax_doXMLHTTPsync = function(_menuaction) -{ - return _xajax_doXMLHTTP(false, _menuaction, arguments); -}; - -window.xajax = { - "getFormValues": function(_form) - { - return egw_json_getFormValues(_form); - } -}; - -/* - The following code is adapted from the xajax project which is licensed under - the following license - @copyright Copyright (c) 2005-2007 by Jared White & J. Max Wilson - @copyright Copyright (c) 2008-2009 by Joseph Woolley, Steffen Konerow, Jared White & J. Max Wilson - @license http://www.xajaxproject.org/bsd_license.txt BSD License -*/ - -/** - * used internally by the legacy "egw_json_response.getFormValues" to recursively - * run over all form elements - * @param serialized is the object which will contain the form data - * @param children is the children node of the form we're runing over - * @param string _filterClass if given only return - */ -function _egw_json_getFormValues(serialized, children, _filterClass) -{ - egw.debug("warn", "Function %s is deprecated", arguments.callee.name); - //alert('_egw_json_getFormValues(,,'+_filterClass+')'); - for (var i = 0; i < children.length; ++i) { - var child = children[i]; - - if (typeof child.childNodes != "undefined") - _egw_json_getFormValues(serialized, child.childNodes, _filterClass); - - if ((!_filterClass || jQuery(child).hasClass(_filterClass)) && typeof child.name != "undefined") - { - //alert('_egw_json_getFormValues(,,'+_filterClass+') calling _egw_json_getFormValue for name='+child.name+', class='+child.class+', value='+child.value); - _egw_json_getFormValue(serialized, child); - } - } -} - -function _egw_json_getObjectLength(_obj) -{ - var res = 0; - for (key in _obj) - { - if (_obj.hasOwnProperty(key)) - res++; - } - return res; -} - -/** - * used internally to serialize - */ -function _egw_json_getFormValue(serialized, child) -{ - //Return if the child doesn't have a name, is disabled, or is a radio-/checkbox and not checked - if ((typeof child.name == "undefined") || (child.disabled && child.disabled == true) || - (child.type && (child.type == 'radio' || child.type == 'checkbox' || child.type == 'button' || child.type == 'submit') && (!child.checked))) - { - return; - } - - var name = child.name; - var values = null; - - if ('select-multiple' == child.type) - { - values = new Array; - for (var j = 0; j < child.length; ++j) - { - var option = child.options[j]; - if (option.selected == true) - values.push(option.value); - } - } - else - { - values = child.value; - } - - //Special treatment if the name of the child contains a [] - then all theese - //values are added to an array. - var keyBegin = name.indexOf('['); - if (0 <= keyBegin) { - var n = name; - var k = n.substr(0, n.indexOf('[')); - var a = n.substr(n.indexOf('[')); - if (typeof serialized[k] == 'undefined') - serialized[k] = new Object; - - var p = serialized; // pointer reset - while (a.length != 0) { - var sa = a.substr(0, a.indexOf(']')+1); - - var lk = k; //save last key - var lp = p; //save last pointer - - a = a.substr(a.indexOf(']')+1); - p = p[k]; - k = sa.substr(1, sa.length-2); - if (k == '') { - if ('select-multiple' == child.type) { - k = lk; //restore last key - p = lp; - } else { - k = _egw_json_getObjectLength(p); + //Try to handle the json response with all registered plugins + hasResponse |= _egw_json_plugin_handle(data.response[i].type, res, this.context); + } catch (e) { + this.jsonError('Internal JSON handler error', e); } } - if (typeof p[k] == 'undefined') - { - p[k] = new Object; + + /* If no explicit response has been specified, call the callback (if one was set) */ + if (!hasResponse && this.callback && data.response[i]) { + this.callback.call(this.sender, data.response[i].data); } - } - p[k] = values; - } else { - //Add the value to the result object with the given name - if (typeof values != "undefined") - { - serialized[name] = values; + + this.handleResponseDone = true; + + this.checkLoadFinish(); } } -} + + /** + * The "onLoadFinish" handler gets called after all JS-files have been loaded + * successfully + */ + window.egw_json_request.prototype.checkLoadFinish = function () { + var complete = true; + for (var key in this.loadedJSFiles) { + complete = complete && this.loadedJSFiles[key]; + } + + if (complete && this.onLoadFinish && this.handleResponseDone) { + this.onLoadFinish.call(this.sender); + } + } + + window.egw_json_getFormValues = function (_form, _filterClass) { + egw.debug("warn", "Function %s is deprecated", arguments.callee.name); + var elem = null; + if (typeof _form == 'object') { + elem = _form; + } else { + elem = document.getElementsByName(_form)[0]; + } + + var serialized = new Object; + if (typeof elem != "undefined" && elem && elem.childNodes) { + if (typeof _filterClass == 'undefined') + _filterClass = null; + + _egw_json_getFormValues(serialized, elem.childNodes, _filterClass) + } + + return serialized; + } + + /** + * Deprecated legacy xajax wrapper functions for the new egw_json interface + */ + let _xajax_doXMLHTTP = function (_async, _menuaction, _arguments) { + egw.debug("warn", "Function %s is deprecated", arguments.callee.name); + /* Assemble the parameter array */ + var paramarray = new Array(); + for (var i = 1; i < _arguments.length; i++) { + paramarray[paramarray.length] = _arguments[i]; + } + + /* Create a new request, passing the menuaction and the parameter array */ + var request = new egw_json_request(_menuaction, paramarray); + + /* Send the request */ + request.sendRequest(_async); + + return request; + } + + window.xajax_doXMLHTTP = function (_menuaction) { + return _xajax_doXMLHTTP(true, _menuaction, arguments); + } + + window.xajax_doXMLHTTPsync = function (_menuaction) { + return _xajax_doXMLHTTP(false, _menuaction, arguments); + }; + + window.xajax = { + "getFormValues": function (_form) { + return egw_json_getFormValues(_form); + } + }; + + /* + The following code is adapted from the xajax project which is licensed under + the following license + @copyright Copyright (c) 2005-2007 by Jared White & J. Max Wilson + @copyright Copyright (c) 2008-2009 by Joseph Woolley, Steffen Konerow, Jared White & J. Max Wilson + @license http://www.xajaxproject.org/bsd_license.txt BSD License + */ + + /** + * used internally by the legacy "egw_json_response.getFormValues" to recursively + * run over all form elements + * @param serialized is the object which will contain the form data + * @param children is the children node of the form we're runing over + * @param string _filterClass if given only return + */ + function _egw_json_getFormValues(serialized, children, _filterClass) { + egw.debug("warn", "Function %s is deprecated", arguments.callee.name); + //alert('_egw_json_getFormValues(,,'+_filterClass+')'); + for (var i = 0; i < children.length; ++i) { + var child = children[i]; + + if (typeof child.childNodes != "undefined") + _egw_json_getFormValues(serialized, child.childNodes, _filterClass); + + if ((!_filterClass || jQuery(child).hasClass(_filterClass)) && typeof child.name != "undefined") { + //alert('_egw_json_getFormValues(,,'+_filterClass+') calling _egw_json_getFormValue for name='+child.name+', class='+child.class+', value='+child.value); + _egw_json_getFormValue(serialized, child); + } + } + } + + function _egw_json_getObjectLength(_obj) { + var res = 0; + for (key in _obj) { + if (_obj.hasOwnProperty(key)) + res++; + } + return res; + } + + /** + * used internally to serialize + */ + function _egw_json_getFormValue(serialized, child) { + //Return if the child doesn't have a name, is disabled, or is a radio-/checkbox and not checked + if ((typeof child.name == "undefined") || (child.disabled && child.disabled == true) || + (child.type && (child.type == 'radio' || child.type == 'checkbox' || child.type == 'button' || child.type == 'submit') && (!child.checked))) { + return; + } + + var name = child.name; + var values = null; + + if ('select-multiple' == child.type) { + values = new Array; + for (var j = 0; j < child.length; ++j) { + var option = child.options[j]; + if (option.selected == true) + values.push(option.value); + } + } else { + values = child.value; + } + + //Special treatment if the name of the child contains a [] - then all theese + //values are added to an array. + var keyBegin = name.indexOf('['); + if (0 <= keyBegin) { + var n = name; + var k = n.substr(0, n.indexOf('[')); + var a = n.substr(n.indexOf('[')); + if (typeof serialized[k] == 'undefined') + serialized[k] = new Object; + + var p = serialized; // pointer reset + while (a.length != 0) { + var sa = a.substr(0, a.indexOf(']') + 1); + + var lk = k; //save last key + var lp = p; //save last pointer + + a = a.substr(a.indexOf(']') + 1); + p = p[k]; + k = sa.substr(1, sa.length - 2); + if (k == '') { + if ('select-multiple' == child.type) { + k = lk; //restore last key + p = lp; + } else { + k = _egw_json_getObjectLength(p); + } + } + if (typeof p[k] == 'undefined') { + p[k] = new Object; + } + } + p[k] = values; + } else { + //Add the value to the result object with the given name + if (typeof values != "undefined") { + serialized[name] = values; + } + } + } +}).call(window); \ No newline at end of file diff --git a/api/js/framework/fw_base.js b/api/js/framework/fw_base.js index b38e0c2760..b0d329c0ea 100644 --- a/api/js/framework/fw_base.js +++ b/api/js/framework/fw_base.js @@ -11,8 +11,10 @@ vendor.bower-asset.jquery.dist.jquery; egw_inheritance.js; */ +import '../../../vendor/bower-asset/jquery/dist/jquery.js'; +import '../jsapi/egw_inheritance.js'; -var fw_base = (function(){ "use strict"; return Class.extend( +window.fw_base = (function(){ "use strict"; return Class.extend( { /** * Framework base class constructor sets up basic initialization diff --git a/api/js/framework/fw_browser.js b/api/js/framework/fw_browser.js index adbd53c02d..b24514c8e2 100644 --- a/api/js/framework/fw_browser.js +++ b/api/js/framework/fw_browser.js @@ -12,14 +12,19 @@ egw_inheritance.js; */ +import '../../../vendor/bower-asset/jquery/dist/jquery.js'; +import '../egw_action/egw_action_common.js'; +import '../jsapi/egw_inheritance.js'; +import '../etemplate/etemplate2.js'; // otherwise et2_load json-response-handler is not (yet) available + /** * Constants definition */ -EGW_BROWSER_TYPE_NONE = 0; -EGW_BROWSER_TYPE_IFRAME = 1; -EGW_BROWSER_TYPE_DIV = 2; +window.EGW_BROWSER_TYPE_NONE = 0; +window.EGW_BROWSER_TYPE_IFRAME = 1; +window.EGW_BROWSER_TYPE_DIV = 2; -var fw_browser = (function(){ "use strict"; return Class.extend( +window.fw_browser = (function(){ "use strict"; return Class.extend( { /** * @param {string} _app diff --git a/api/js/framework/fw_classes.js b/api/js/framework/fw_classes.js index 84293d5319..cd747a5bb0 100644 --- a/api/js/framework/fw_classes.js +++ b/api/js/framework/fw_classes.js @@ -10,141 +10,135 @@ /*---------------------------- Class egw_fw_class_application ----------------------------*/ -/** - * application class constructor - * - * @param {type} _parentFw - * @param {type} _appName - * @param {type} _displayName - * @param {type} _icon - * @param {type} _indexUrl - * @param {type} _sideboxWidth - * @param {type} _baseUrl - * @param {type} _internalName - * @returns {egw_fw_class_application} - */ -function egw_fw_class_application(_parentFw, _appName, _displayName, _icon, - _indexUrl, _sideboxWidth, _baseUrl, _internalName) +(function() { - //Copy the application properties - this.appName = _appName; - this.internalName = _internalName; - this.displayName = _displayName; - this.icon = _icon; - this.indexUrl = _indexUrl; - this.sidebox_md5 = ''; - this.hasPrerequisites; - this.baseUrl = _baseUrl; + "use strict"; - this.website_title = ''; - this.app_header = ''; + /** + * application class constructor + * + * @param {type} _parentFw + * @param {type} _appName + * @param {type} _displayName + * @param {type} _icon + * @param {type} _indexUrl + * @param {type} _sideboxWidth + * @param {type} _baseUrl + * @param {type} _internalName + * @returns {egw_fw_class_application} + */ + window.egw_fw_class_application = function(_parentFw, _appName, _displayName, _icon, + _indexUrl, _sideboxWidth, _baseUrl, _internalName) { + //Copy the application properties + this.appName = _appName; + this.internalName = _internalName; + this.displayName = _displayName; + this.icon = _icon; + this.indexUrl = _indexUrl; + this.sidebox_md5 = ''; + this.hasPrerequisites; + this.baseUrl = _baseUrl; - this.sideboxWidth = _sideboxWidth; + this.website_title = ''; + this.app_header = ''; - //Setup a link to the parent framework class - this.parentFw = _parentFw; + this.sideboxWidth = _sideboxWidth; - //Preset some variables - this.hasSideboxMenuContent = false; - this.sidemenuEntry = null; - this.tab = null; - this.browser = null; -} + //Setup a link to the parent framework class + this.parentFw = _parentFw; -/** - * destroy application object and its relative parts - */ -egw_fw_class_application.prototype.destroy = function() -{ - delete this.tab; - if (this.sidemenuEntry) this.sidemenuEntry.remove(); - delete this.sidemenuEntry; - delete this.browser; - delete (framework.applications[this.appName]); -}; - -/** - * Returns an menuaction inside the jdots_framework for this application. - * without a "this" context (by directly calling egw_fw_class_application.prototype.getAjaxUrl) - * or passing null to a "call" call "home" will be used as application name and - * the the base url will be omitted (default behaviour for all applications which) - * lie inside the default egw instance. - * - * @param {string} _fun is the function which shall be called on the server. - * @param {string} _ajax_exec_url contains menuaction for _fun === 'ajax_exec' - */ -egw_fw_class_application.prototype.getMenuaction = function(_fun, _ajax_exec_url) -{ - var baseUrl = ''; - var appName = 'home'; - - if (this) - { - baseUrl = this.getBaseUrl(); - appName = this.internalName; + //Preset some variables + this.hasSideboxMenuContent = false; + this.sidemenuEntry = null; + this.tab = null; + this.browser = null; } - // Check whether the baseurl is actually set. If not, then this application - // resides inside the same egw instance as the jdots framework. We'll simply - // return a menu action and not a full featured url here. - if (baseUrl != '') - { - baseUrl = baseUrl + 'json.php?menuaction='; - } + /** + * destroy application object and its relative parts + */ + window.egw_fw_class_application.prototype.destroy = function () { + delete this.tab; + if (this.sidemenuEntry) this.sidemenuEntry.remove(); + delete this.sidemenuEntry; + delete this.browser; + delete (framework.applications[this.appName]); + }; - var menuaction = _ajax_exec_url ? _ajax_exec_url.match(/menuaction=([^&]+)/) : null; + /** + * Returns an menuaction inside the jdots_framework for this application. + * without a "this" context (by directly calling window.egw_fw_class_application.prototype.getAjaxUrl) + * or passing null to a "call" call "home" will be used as application name and + * the the base url will be omitted (default behaviour for all applications which) + * lie inside the default egw instance. + * + * @param {string} _fun is the function which shall be called on the server. + * @param {string} _ajax_exec_url contains menuaction for _fun === 'ajax_exec' + */ + window.egw_fw_class_application.prototype.getMenuaction = function (_fun, _ajax_exec_url) { + var baseUrl = ''; + var appName = 'home'; - // use template handler to call current framework, eg. pixelegg - return baseUrl + appName + '.jdots_framework.' + _fun + '.template'+ - (menuaction ? '.'+menuaction[1] : ''); -}; + if (this) { + baseUrl = this.getBaseUrl(); + appName = this.internalName; + } -/** - * Returns the base url for this application. If the application resides inside - * the default egw instance, '' will be returned unless the _force parameter is - * set to true. - * - * @param {boolean} _force Optional parameter. If set, getBaseUrl will return the - * webserverUrl instead of '' if the application resides inside the main - * egw instance. - */ -egw_fw_class_application.prototype.getBaseUrl = function(_force) + // Check whether the baseurl is actually set. If not, then this application + // resides inside the same egw instance as the jdots framework. We'll simply + // return a menu action and not a full featured url here. + if (baseUrl != '') { + baseUrl = baseUrl + 'json.php?menuaction='; + } + + var menuaction = _ajax_exec_url ? _ajax_exec_url.match(/menuaction=([^&]+)/) : null; + + // use template handler to call current framework, eg. pixelegg + return baseUrl + appName + '.jdots_framework.' + _fun + '.template' + + (menuaction ? '.' + menuaction[1] : ''); + }; + + /** + * Returns the base url for this application. If the application resides inside + * the default egw instance, '' will be returned unless the _force parameter is + * set to true. + * + * @param {boolean} _force Optional parameter. If set, getBaseUrl will return the + * webserverUrl instead of '' if the application resides inside the main + * egw instance. + */ + window.egw_fw_class_application.prototype.getBaseUrl = function (_force) { + if (this.baseUrl) { + return this.baseUrl; + } else if ((typeof _force != 'undefined') && _force) { + return egw_topWindow().egw_webserverUrl; + } else { + return ''; + } + }; +}).call(window); + +window.egw_fw_getMenuaction = function(_fun) { - if (this.baseUrl) - { - return this.baseUrl; - } - else if ((typeof _force != 'undefined') && _force) - { - return egw_topWindow().egw_webserverUrl; - } - else - { - return ''; - } -}; - -function egw_fw_getMenuaction(_fun) -{ - return egw_fw_class_application.prototype.getMenuaction.call(null, _fun); + return window.egw_fw_class_application.prototype.getMenuaction.call(null, _fun); } /*---------------------------- Class egw_fw_class_callback ----------------------------*/ -function egw_fw_class_callback(_context, _proc) +window.egw_fw_class_callback = function(_context, _proc) { this.context = _context; this.proc = _proc; } -egw_fw_class_callback.prototype.call = function() +window.egw_fw_class_callback.prototype.call = function() { return this.proc.apply(this.context, arguments); }; -array_remove = function(array, index) +window.array_remove = function(array, index) { array.splice(index, 1); }; diff --git a/api/js/framework/fw_desktop.js b/api/js/framework/fw_desktop.js index 61cab2046d..27aa98d799 100644 --- a/api/js/framework/fw_desktop.js +++ b/api/js/framework/fw_desktop.js @@ -16,6 +16,12 @@ framework.fw_classes; egw_inheritance.js; */ +import '../../../vendor/bower-asset/jquery/dist/jquery.js'; +import './fw_base.js'; +import './fw_browser.js'; +import './fw_ui.js'; +import './fw_classes.js'; +import '../jsapi/egw_inheritance.js'; /** * @@ -29,8 +35,8 @@ * * @type @exp;fw_ui_sidemenu_entry@call;extend */ - var desktop_ui_sidemenu_entry = fw_ui_sidemenu_entry.extend({ - + window.desktop_ui_sidemenu_entry = fw_ui_sidemenu_entry.extend( + { /** * Override fw_ui_sidemenu_entry class constructor * @@ -91,7 +97,7 @@ * * @type @exp;fw_ui_sidemenu@call;extend */ - var desktop_ui_sidemenu = fw_ui_sidemenu.extend( + window.desktop_ui_sidemenu = fw_ui_sidemenu.extend( { init: function(_baseDiv, _sortCallback) { diff --git a/api/js/framework/fw_ui.js b/api/js/framework/fw_ui.js index 27f84b48be..241f4a0018 100644 --- a/api/js/framework/fw_ui.js +++ b/api/js/framework/fw_ui.js @@ -12,6 +12,10 @@ /api/js/jquery/mousewheel/mousewheel.js; egw_inheritance.js; */ +import '../../../vendor/bower-asset/jquery/dist/jquery.js'; +import '../../../vendor/bower-asset/jquery-ui/jquery-ui.js'; +import '../jquery/mousewheel/mousewheel.js'; +import '../jsapi/egw_inheritance.js'; /** * ui siemenu entry class @@ -19,7 +23,7 @@ * * @type @exp;Class@call;extend */ -var fw_ui_sidemenu_entry = (function(){ "use strict"; return Class.extend( +window.fw_ui_sidemenu_entry = (function(){ "use strict"; return Class.extend( { /** * Framework ui sidemenu entry class constructor @@ -194,7 +198,7 @@ var fw_ui_sidemenu_entry = (function(){ "use strict"; return Class.extend( * * @type @exp;Class@call;extend */ -var fw_ui_sidemenu = (function(){ "use strict"; return Class.extend( +window.fw_ui_sidemenu = (function(){ "use strict"; return Class.extend( { /** * The constructor of the egw_fw_ui_sidemenu. @@ -310,7 +314,7 @@ var fw_ui_sidemenu = (function(){ "use strict"; return Class.extend( * @param {int} _pos is the position where the tab will be inserted * @param {string} application status (e.g. status="5") */ -function egw_fw_ui_tab(_parent, _contHeaderDiv, _contDiv, _icon, _callback, +window.egw_fw_ui_tab = function(_parent, _contHeaderDiv, _contDiv, _icon, _callback, _closeCallback, _tag, _pos, _status) { this.parent = _parent; @@ -452,7 +456,7 @@ function egw_fw_ui_tab(_parent, _contHeaderDiv, _contDiv, _icon, _callback, * @param {int} _value if set to 0 the notification gets reset if nothing set * it will increase the notification value by one */ -egw_fw_ui_tab.prototype.setNotification = function(_value) +window.egw_fw_ui_tab.prototype.setNotification = function(_value) { this.notification = typeof _value != 'undefined' ? _value : this.notification+1; jQuery(this.notificationDiv).text(this.notification).toggle(this.notification > 0); @@ -463,7 +467,7 @@ egw_fw_ui_tab.prototype.setNotification = function(_value) * * @param {string} _title HTML/Text which should be displayed. */ -egw_fw_ui_tab.prototype.setTitle = function(_title) +window.egw_fw_ui_tab.prototype.setTitle = function(_title) { this.title = _title; jQuery(this.headerH1).empty(); @@ -475,7 +479,7 @@ egw_fw_ui_tab.prototype.setTitle = function(_title) * * @param {string} _hint Text which should be displayed. */ -egw_fw_ui_tab.prototype.setHint = function(_hint) +window.egw_fw_ui_tab.prototype.setHint = function(_hint) { this.hint = _hint; egw().tooltipBind(jQuery(this.headerDiv), _hint); @@ -486,7 +490,7 @@ egw_fw_ui_tab.prototype.setHint = function(_hint) * * @param {string} _content HTML/Text which should be displayed. */ -egw_fw_ui_tab.prototype.setContent = function(_content) +window.egw_fw_ui_tab.prototype.setContent = function(_content) { jQuery(this.contentDiv).empty(); jQuery(this.contentDiv).append(_content); @@ -496,7 +500,7 @@ egw_fw_ui_tab.prototype.setContent = function(_content) * Shows the content of the tab. Only one tab should be displayed at once. By using egw_fw_ui_tabs.showTab * you can assure this. */ -egw_fw_ui_tab.prototype.show = function() +window.egw_fw_ui_tab.prototype.show = function() { jQuery(this.headerDiv).addClass("egw_fw_ui_tab_header_active"); var content = jQuery(this.contentDiv); @@ -519,7 +523,7 @@ egw_fw_ui_tab.prototype.show = function() /** * Hides the content of this tab. */ -egw_fw_ui_tab.prototype.hide = function() +window.egw_fw_ui_tab.prototype.hide = function() { jQuery(this.headerDiv).removeClass("egw_fw_ui_tab_header_active"); var content = jQuery(this.contentDiv); @@ -538,7 +542,7 @@ egw_fw_ui_tab.prototype.hide = function() /** * hide tab header only */ -egw_fw_ui_tab.prototype.hideTabHeader = function() +window.egw_fw_ui_tab.prototype.hideTabHeader = function() { jQuery(this.headerDiv).hide(); }; @@ -546,7 +550,7 @@ egw_fw_ui_tab.prototype.hideTabHeader = function() /** * Removes this tab and all its content. */ -egw_fw_ui_tab.prototype.remove = function() +window.egw_fw_ui_tab.prototype.remove = function() { this.hide(); jQuery(this.contentDiv).remove(); @@ -558,7 +562,7 @@ egw_fw_ui_tab.prototype.remove = function() * * @param {boolean} _closeable if true, the close button is shown, if false, the close button is hidden. default is true. */ -egw_fw_ui_tab.prototype.setCloseable = function(_closeable) +window.egw_fw_ui_tab.prototype.setCloseable = function(_closeable) { this.closeable = _closeable; if (_closeable) @@ -579,7 +583,7 @@ egw_fw_ui_tab.prototype.setCloseable = function(_closeable) * * @param {object} _contDiv specifies "div" element the tab ui element should be displayed in. */ -function egw_fw_ui_tabs(_contDiv) +window.egw_fw_ui_tabs = function(_contDiv) { this.contDiv = _contDiv; @@ -609,7 +613,7 @@ function egw_fw_ui_tabs(_contDiv) * @param {string} _text is the text which will be seen in the appHeader. * @param {string} _msg_class css class for message */ -egw_fw_ui_tabs.prototype.setAppHeader = function(_text, _msg_class) +window.egw_fw_ui_tabs.prototype.setAppHeader = function(_text, _msg_class) { this.appHeader.text(_text); this.appHeader.prop('class', "egw_fw_ui_app_header"); @@ -623,7 +627,7 @@ egw_fw_ui_tabs.prototype.setAppHeader = function(_text, _msg_class) * to switch back to the last tab when a tab is closed. Double entries in the tab history * may appear whenever a tab is deleted. */ -egw_fw_ui_tabs.prototype.cleanHistory = function() +window.egw_fw_ui_tabs.prototype.cleanHistory = function() { for (var i = this.tabHistory.length - 1; i >= 0; i--) { @@ -643,7 +647,7 @@ egw_fw_ui_tabs.prototype.cleanHistory = function() * @param {int} _pos specifies the position in the tab list. If _pos is -1, the tab will be added to the end of the tab list * @param {string} application status */ -egw_fw_ui_tabs.prototype.addTab = function(_icon, _callback, _closeCallback, _tag, _pos, _status) +window.egw_fw_ui_tabs.prototype.addTab = function(_icon, _callback, _closeCallback, _tag, _pos, _status) { var pos = -1; if (typeof _pos != 'undefined') @@ -684,7 +688,7 @@ egw_fw_ui_tabs.prototype.addTab = function(_icon, _callback, _closeCallback, _ta * * @param {object} _tab is the object which should be closed. */ -egw_fw_ui_tabs.prototype.removeTab = function(_tab) +window.egw_fw_ui_tabs.prototype.removeTab = function(_tab) { //Delete the deleted tab from the history for (var i = this.tabHistory.length - 1; i >= 0; i--) @@ -734,7 +738,7 @@ egw_fw_ui_tabs.prototype.removeTab = function(_tab) * * @param {object} _tab is the object which should be opened. */ -egw_fw_ui_tabs.prototype.showTab = function(_tab) +window.egw_fw_ui_tabs.prototype.showTab = function(_tab) { if (this.activeTab != _tab && (_tab.status != '5' || _tab.tag.isFrameworkTab)) { @@ -765,7 +769,7 @@ egw_fw_ui_tabs.prototype.showTab = function(_tab) * * @param {boolean} _closeable */ -egw_fw_ui_tabs.prototype.setCloseable = function(_closeable) +window.egw_fw_ui_tabs.prototype.setCloseable = function(_closeable) { for (var i = 0; i < this.tabs.length; i++) { @@ -777,7 +781,7 @@ egw_fw_ui_tabs.prototype.setCloseable = function(_closeable) * Clears all data, removes all tabs, independently from the question, whether they may be closed or * not. */ -egw_fw_ui_tabs.prototype.clean = function() +window.egw_fw_ui_tabs.prototype.clean = function() { //Remove all tabs, clean the tabs array for (var i = 0; i < this.tabs.length; i++) @@ -798,7 +802,7 @@ egw_fw_ui_tabs.prototype.clean = function() * * @return {boolean} returns true if the open tab is not the last visible tab otherwise false */ -egw_fw_ui_tabs.prototype._isNotTheLastTab = function() +window.egw_fw_ui_tabs.prototype._isNotTheLastTab = function() { var n = 0; for (var i in this.tabs) @@ -815,7 +819,7 @@ egw_fw_ui_tabs.prototype._isNotTheLastTab = function() * @param {string} _appname * @returns {object|boolean} returns tab object, returns false if no tab found */ -egw_fw_ui_tabs.prototype.getTab = function(_appname) +window.egw_fw_ui_tabs.prototype.getTab = function(_appname) { for (var i = 0; i < this.tabs.length; i++) { @@ -840,7 +844,7 @@ egw_fw_ui_tabs.prototype.getTab = function(_appname) * @param {object} _tag */ -function egw_fw_ui_category(_contDiv, _name, _title, _content, _callback, _animationCallback, _tag) +window.egw_fw_ui_category = function(_contDiv, _name, _title, _content, _callback, _animationCallback, _tag) { //Copy the parameters this.contDiv = _contDiv; @@ -906,7 +910,7 @@ function egw_fw_ui_category(_contDiv, _name, _title, _content, _callback, _anima jQuery(this.headerDiv).append(this.contentDiv); } -egw_fw_ui_category.prototype.open = function(_instantly) +window.egw_fw_ui_category.prototype.open = function(_instantly) { this.callback.call(this, true); jQuery(this.headerDiv).addClass('egw_fw_ui_category_active') @@ -926,7 +930,7 @@ egw_fw_ui_category.prototype.open = function(_instantly) jQuery("li:first-child", this.headerDiv).eq(0).focus(); }; -egw_fw_ui_category.prototype.close = function(_instantly) +window.egw_fw_ui_category.prototype.close = function(_instantly) { this.callback.call(this, false); jQuery(this.headerDiv).removeClass('egw_fw_ui_category_active') @@ -945,7 +949,7 @@ egw_fw_ui_category.prototype.close = function(_instantly) } }; -egw_fw_ui_category.prototype.remove = function() +window.egw_fw_ui_category.prototype.remove = function() { //Delete the content and header div jQuery(this.contDiv).remove(); @@ -958,7 +962,7 @@ egw_fw_ui_category.prototype.remove = function() * @param {object} _contDiv */ -function egw_fw_ui_scrollarea(_contDiv) +window.egw_fw_ui_scrollarea = function(_contDiv) { this.startScrollSpeed = 50.0; //in px/sec this.endScrollSpeed = 250.0; //in px/sec @@ -1059,7 +1063,7 @@ function egw_fw_ui_scrollarea(_contDiv) this.update(); } -egw_fw_ui_scrollarea.prototype.setScrollPos = function(_pos) +window.egw_fw_ui_scrollarea.prototype.setScrollPos = function(_pos) { var scrollArea = egw.preference('scroll_area', 'common') == 1 ? true : false; if (this.buttonsVisible) @@ -1116,12 +1120,12 @@ egw_fw_ui_scrollarea.prototype.setScrollPos = function(_pos) } }; -egw_fw_ui_scrollarea.prototype.scrollDelta = function(_delta) +window.egw_fw_ui_scrollarea.prototype.scrollDelta = function(_delta) { this.setScrollPos(this.scrollPos + _delta); }; -egw_fw_ui_scrollarea.prototype.toggleButtons = function(_visible) +window.egw_fw_ui_scrollarea.prototype.toggleButtons = function(_visible) { if (_visible) { @@ -1141,7 +1145,7 @@ egw_fw_ui_scrollarea.prototype.toggleButtons = function(_visible) this.buttonsVisible = _visible; }; -egw_fw_ui_scrollarea.prototype.update = function() +window.egw_fw_ui_scrollarea.prototype.update = function() { //Get the height of the content and the outer box this.contHeight = jQuery(this.scrollDiv).outerHeight(); @@ -1151,7 +1155,7 @@ egw_fw_ui_scrollarea.prototype.update = function() this.setScrollPos(this.scrollPos); }; -egw_fw_ui_scrollarea.prototype.getScrollDelta = function(_timeGap) +window.egw_fw_ui_scrollarea.prototype.getScrollDelta = function(_timeGap) { //Calculate the current scroll speed var curScrollSpeed = this.startScrollSpeed + this.scrollSpeedAccel * this.scrollTime; @@ -1167,7 +1171,7 @@ egw_fw_ui_scrollarea.prototype.getScrollDelta = function(_timeGap) return curScrollSpeed * _timeGap; }; -egw_fw_ui_scrollarea.prototype.mouseOverCallback = function(_context) +window.egw_fw_ui_scrollarea.prototype.mouseOverCallback = function(_context) { //Do the scrolling _context.scrollDelta(_context.getScrollDelta(_context.timerInterval) * @@ -1181,7 +1185,7 @@ egw_fw_ui_scrollarea.prototype.mouseOverCallback = function(_context) } }; -egw_fw_ui_scrollarea.prototype.mouseOverToggle = function(_over, _dir) +window.egw_fw_ui_scrollarea.prototype.mouseOverToggle = function(_over, _dir) { this.mouseOver = _over; this.dir = _dir; @@ -1202,10 +1206,10 @@ egw_fw_ui_scrollarea.prototype.mouseOverToggle = function(_over, _dir) * egw_fw_ui_splitter class */ -var EGW_SPLITTER_HORIZONTAL = 0; -var EGW_SPLITTER_VERTICAL = 1; +window.EGW_SPLITTER_HORIZONTAL = 0; +window.EGW_SPLITTER_VERTICAL = 1; -function egw_fw_ui_splitter(_contDiv, _orientation, _resizeCallback, _constraints, _tag) +window.egw_fw_ui_splitter = function(_contDiv, _orientation, _resizeCallback, _constraints, _tag) { //Copy the parameters this.tag = _tag; @@ -1293,7 +1297,7 @@ function egw_fw_ui_splitter(_contDiv, _orientation, _resizeCallback, _constraint jQuery(this.contDiv).append(this.splitterDiv); } -egw_fw_ui_splitter.prototype.clipDelta = function(_delta) +window.egw_fw_ui_splitter.prototype.clipDelta = function(_delta) { var result = _delta; @@ -1319,7 +1323,7 @@ egw_fw_ui_splitter.prototype.clipDelta = function(_delta) return result; }; -egw_fw_ui_splitter.prototype.dragStartHandler = function(event, ui) +window.egw_fw_ui_splitter.prototype.dragStartHandler = function(event, ui) { switch (this.orientation) { @@ -1332,7 +1336,7 @@ egw_fw_ui_splitter.prototype.dragStartHandler = function(event, ui) } }; -egw_fw_ui_splitter.prototype.dragHandler = function(event, ui) +window.egw_fw_ui_splitter.prototype.dragHandler = function(event, ui) { /* var delta = 0; switch (this.orientation) @@ -1351,7 +1355,7 @@ egw_fw_ui_splitter.prototype.dragHandler = function(event, ui) }; -egw_fw_ui_splitter.prototype.dragStopHandler = function(event, ui) +window.egw_fw_ui_splitter.prototype.dragStopHandler = function(event, ui) { var delta = 0; switch (this.orientation) @@ -1377,7 +1381,7 @@ egw_fw_ui_splitter.prototype.dragStopHandler = function(event, ui) * Disable/Enable drabbale splitter * @param {type} _state */ -egw_fw_ui_splitter.prototype.set_disable = function (_state) +window.egw_fw_ui_splitter.prototype.set_disable = function (_state) { jQuery(this.splitterDiv).draggable(_state?'disable':'enable'); }; @@ -1390,7 +1394,7 @@ egw_fw_ui_splitter.prototype.set_disable = function (_state) * @param {object} _callbackContext context of the toggleCallback * @returns {egw_fw_ui_toggleSidebar} */ -function egw_fw_ui_toggleSidebar (_contentDiv, _toggleCallback, _callbackContext) +window.egw_fw_ui_toggleSidebar = function(_contentDiv, _toggleCallback, _callbackContext) { var self = this; this.toggleCallback = _toggleCallback; @@ -1416,7 +1420,7 @@ function egw_fw_ui_toggleSidebar (_contentDiv, _toggleCallback, _callbackContext * Toggle menu on/off * @param {object} _callbackContext context of the toggleCallback */ -egw_fw_ui_toggleSidebar.prototype.onToggle = function(_callbackContext) +window.egw_fw_ui_toggleSidebar.prototype.onToggle = function(_callbackContext) { if (typeof this.toggleAudio != 'undefined') this.toggleAudio[0].play(); if (this.contDiv.hasClass('egw_fw_sidebar_toggleOn')) @@ -1444,7 +1448,7 @@ egw_fw_ui_toggleSidebar.prototype.onToggle = function(_callbackContext) * @param {type} _toggleCallback callback function to handle toggle preference and resize * @param {type} _context context of callback function */ -egw_fw_ui_toggleSidebar.prototype.set_toggle = function (_state, _toggleCallback, _context) +window.egw_fw_ui_toggleSidebar.prototype.set_toggle = function (_state, _toggleCallback, _context) { this.contDiv.toggleClass('egw_fw_sidebar_toggleOn',_state === 'on'?true:false); _context.splitterUi.set_disable(_state === 'on'?true:false); diff --git a/api/js/jquery/jquery-tap-and-hold/jquery.tapandhold.js b/api/js/jquery/jquery-tap-and-hold/jquery.tapandhold.js index b70041d557..a360d1e2ba 100644 --- a/api/js/jquery/jquery-tap-and-hold/jquery.tapandhold.js +++ b/api/js/jquery/jquery-tap-and-hold/jquery.tapandhold.js @@ -17,6 +17,7 @@ * @description Adds a handler for a custom event 'taphold' that handles a * tap and hold on touch interfaces. */ +import '../../../../vendor/bower-asset/jquery/dist/jquery.js'; (function($) { var TAP_AND_HOLD_TRIGGER_TIMER = 600; var MAX_DISTANCE_ALLOWED_IN_TAP_AND_HOLD_EVENT = 40; diff --git a/api/js/jquery/jquery-ui-timepicker-addon.js b/api/js/jquery/jquery-ui-timepicker-addon.js index 1f67c320bc..80fc1ce325 100644 --- a/api/js/jquery/jquery-ui-timepicker-addon.js +++ b/api/js/jquery/jquery-ui-timepicker-addon.js @@ -1,6 +1,8 @@ /*! jQuery Timepicker Addon - v1.6.1 - 2015-11-14 * http://trentrichardson.com/examples/timepicker * Copyright (c) 2015 Trent Richardson; Licensed MIT */ +import '../../../vendor/bower-asset/jquery/dist/jquery.js'; +import '../../../vendor/bower-asset/jquery-ui/jquery-ui.js'; (function (factory) { if (typeof define === 'function' && define.amd) { define(['jquery', 'jquery-ui'], factory); diff --git a/api/js/jquery/jquery.noconflict.js b/api/js/jquery/jquery.noconflict.js index 1f0047921b..97db806a33 100644 --- a/api/js/jquery/jquery.noconflict.js +++ b/api/js/jquery/jquery.noconflict.js @@ -12,5 +12,6 @@ /*egw:uses /vendor/bower-asset/jquery/dist/jquery.js; */ +import '../../../vendor/bower-asset/jquery/dist/jquery.js'; jQuery.noConflict(); \ No newline at end of file diff --git a/api/js/jsapi/app_base.js b/api/js/jsapi/app_base.js index 2c491104b7..628084582b 100644 --- a/api/js/jsapi/app_base.js +++ b/api/js/jsapi/app_base.js @@ -15,6 +15,7 @@ egw_inheritance; /api/js/es6-promise.min.js; */ +import './egw_inheritance.js'; /** * Object to collect instanciated appliction objects @@ -28,7 +29,7 @@ * * @type object */ -app = {classes: {}}; +window.app = {classes: {}}; /** * Common base class for application javascript diff --git a/api/js/jsapi/egw.js b/api/js/jsapi/egw.js index e998b8417e..2d6f00c7de 100644 --- a/api/js/jsapi/egw.js +++ b/api/js/jsapi/egw.js @@ -4,10 +4,9 @@ * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License * @package etemplate * @subpackage api - * @link http://www.egroupware.org + * @link https://www.egroupware.org * @author Andreas Stöckel (as AT stylite.de) * @author Ralf Becker - * @version $Id$ */ /*egw:uses @@ -165,8 +164,40 @@ window.focus(); } - window.egw_LAB = $LAB.setOptions({AlwaysPreserveOrder:true,BasePath:window.egw_webserverUrl+'/'}); - window.egw_LAB.script(include).wait(function() + /** + * Import JavaScript legacy code: global scope, non-strict and executed in order + * + * @param String|Array _src + * @param String|undefined _baseurl + * @return {Promise[]>} + */ + async function legacy_js_import(_src, _baseurl) + { + if (!Array.isArray(_src)) _src = [].concat(_src); + return Promise.all(_src.map(src => { + return new Promise(function(_resolve, _reject) + { + const script = document.createElement('script'); + script.src = (_baseurl ? _baseurl+'/' : '')+src; + script.async = _src.length === 1; + script.onload = _resolve; + script.onerror = _reject; + document.head.appendChild(script); + }) + // catch and display, but not stop execution + .catch((err) => { alert(src+":\n\n"+err.message)}); + })); + } + + // split includes in legacy js and modules + const legacy_regexp = /dhtmlx/; + // make our promise global, as legacy code calls egw_LAB.wait which we assign to egw_ready.then + window.egw_LAB = window.egw_ready = Promise.all( + [legacy_js_import(include.filter((src) => src.match(legacy_regexp) !== null), window.egw_webserverUrl)] + .concat(include.filter((src) => src.match(legacy_regexp) === null) + .map(rel_src => import(window.egw_webserverUrl+'/'+rel_src) + .catch((err) => { alert(rel_src+":\n\n"+err.message)}) + ))).then(() => { // We need to override the globalEval to mitigate potential execution of // script tag. This issue is relevant to jQuery 1.12.4, we need to check @@ -252,7 +283,7 @@ catch(e) { // ignore SecurityError exception if opener is different security context / cross-origin } - // instanciate app object + // instantiate app object var appname = window.egw_appName; if (app && typeof app[appname] != 'object' && typeof app.classes[appname] == 'function') { @@ -444,7 +475,9 @@ // ignore SecurityError exception if top is different security context / cross-origin } }); - }); + }, (e) => alert(e.message+"\n\n"+e.stack)); + // + window.egw_LAB.wait = window.egw_ready.then; /** * @@ -459,7 +492,7 @@ })(); // get TypeScript modules working with our loader -function require(_file) +window.require = function(_file) { switch(_file) { @@ -468,7 +501,7 @@ function require(_file) } return window.exports; } -var exports = {}; +window.exports = {}; /** * Call a function specified by it's name (possibly dot separated, eg. "app.myapp.myfunc") @@ -478,7 +511,7 @@ var exports = {}; * @returns {Mixed|Promise} * @deprecated use egw.callFunc(_func, ...) or egw.applyFunc(_func, args) */ -function et2_call(_func) +window.et2_call = function(_func) { return egw.applyFunc(_func, [].slice.call(arguments, 1), window); } diff --git a/api/js/jsapi/egw_app.js b/api/js/jsapi/egw_app.js index bbef092817..b8d5b55130 100644 --- a/api/js/jsapi/egw_app.js +++ b/api/js/jsapi/egw_app.js @@ -1,4 +1,3 @@ -"use strict"; /** * EGroupware clientside Application javascript base object * @@ -10,16 +9,13 @@ * @author Hadi Nategh * @author Nathan Gray */ -Object.defineProperty(exports, "__esModule", { value: true }); -exports.EgwApp = void 0; -require("jquery"); -require("jqueryui"); -require("../jsapi/egw_global"); -var etemplate2_1 = require("../etemplate/etemplate2"); -var et2_extension_nextmatch_1 = require("../etemplate/et2_extension_nextmatch"); -var et2_widget_dialog_1 = require("../etemplate/et2_widget_dialog"); -var et2_core_widget_1 = require("../etemplate/et2_core_widget"); -var et2_widget_favorites_1 = require("../etemplate/et2_widget_favorites"); +import 'jquery'; +import 'jqueryui'; +import { etemplate2 } from "../etemplate/etemplate2"; +import { et2_nextmatch } from "../etemplate/et2_extension_nextmatch"; +import { et2_dialog } from "../etemplate/et2_widget_dialog"; +import { et2_createWidget } from "../etemplate/et2_core_widget"; +import { et2_favorites } from "../etemplate/et2_widget_favorites"; /** * Common base class for application javascript * Each app should extend as needed. @@ -50,12 +46,12 @@ var et2_widget_favorites_1 = require("../etemplate/et2_widget_favorites"); * } * }); */ -var EgwApp = /** @class */ (function () { +export class EgwApp { /** * Initialization and setup goes here, but the etemplate2 object * is not yet ready. */ - function EgwApp(appname) { + constructor(appname) { /** * PGP begin and end tags */ @@ -97,18 +93,18 @@ var EgwApp = /** @class */ (function () { * Clean up any created objects & references * @param {object} _app local app object */ - EgwApp.prototype.destroy = function (_app) { + destroy(_app) { delete this.et2; if (this.sidebox) this.sidebox.off(); delete this.sidebox; if (!_app) delete app[this.appname]; - var index = -1; + let index = -1; if ((index = EgwApp._instances.indexOf(this)) >= 0) { EgwApp._instances.splice(index, 1); } - }; + } /** * This function is called when the etemplate2 object is loaded * and ready. If you must store a reference to the et2 object, @@ -118,7 +114,7 @@ var EgwApp = /** @class */ (function () { * @param {etemplate2} et2 * @param {string} name template name */ - EgwApp.prototype.et2_ready = function (et2, name) { + et2_ready(et2, name) { if (this.et2 !== null) { egw.debug('log', "Changed et2 object"); } @@ -129,7 +125,7 @@ var EgwApp = /** @class */ (function () { } // Highlights the favorite based on initial list state this.highlight_favorite(); - }; + } /** * Observer method receives update notifications from all applications * @@ -149,8 +145,8 @@ var EgwApp = /** @class */ (function () { * or null, if not triggered on server-side, which adds that info * @return {false|*} false to stop regular refresh, thought all observers are run */ - EgwApp.prototype.observer = function (_msg, _app, _id, _type, _msg_type, _links) { - }; + observer(_msg, _app, _id, _type, _msg_type, _links) { + } /** * Handle a push notification about entry changes from the websocket * @@ -169,7 +165,7 @@ var EgwApp = /** @class */ (function () { * @param {object|null} pushData.acl Extra data for determining relevance. eg: owner or responsible to decide if update is necessary * @param {number} pushData.account_id User that caused the notification */ - EgwApp.prototype.push = function (pushData) { + push(pushData) { var _a; // don't care about other apps data, reimplement if your app does care eg. calendar if (pushData.app !== this.appname) @@ -191,7 +187,7 @@ var EgwApp = /** @class */ (function () { return; } // Nextmatch does the hard part of updating. Try to find one. - var nm = (_a = this.et2) === null || _a === void 0 ? void 0 : _a.getDOMWidgetById('nm'); + let nm = (_a = this.et2) === null || _a === void 0 ? void 0 : _a.getDOMWidgetById('nm'); if (!nm) { return; } @@ -202,7 +198,7 @@ var EgwApp = /** @class */ (function () { } // Pass actual refresh on to just nextmatch nm.refresh(pushData.id, pushData.type); - }; + } /** * Check grants to see if we can quickly tell if this entry is not for us * @@ -214,31 +210,27 @@ var EgwApp = /** @class */ (function () { * * @return boolean Entry has ACL access */ - EgwApp.prototype._push_grant_check = function (pushData, grant_fields, appname) { - var grants = egw.grants(appname || this.appname); + _push_grant_check(pushData, grant_fields, appname) { + let grants = egw.grants(appname || this.appname); // No grants known if (!grants) return true; - var _loop_1 = function (i) { - var grant_field = pushData.acl[grant_fields[i]]; + // check user has a grant from owner or something + for (let i = 0; i < grant_fields.length; i++) { + let grant_field = pushData.acl[grant_fields[i]]; if (["number", "string"].indexOf(typeof grant_field) >= 0 && grants[grant_field] !== 'undefined') { - return { value: true }; + // ACL access + return true; } else if (!Object.keys(grants).filter(function (grant_account) { return grant_field.indexOf(grant_account) >= 0 || grant_field.indexOf(parseInt(grant_account)).length; })) { - return { value: false }; + return false; } - }; - // check user has a grant from owner or something - for (var i = 0; i < grant_fields.length; i++) { - var state_1 = _loop_1(i); - if (typeof state_1 === "object") - return state_1.value; } return false; - }; + } /** * Check pushData.acl values against a list of fields to see if we care about this entry based on current nextmatch * filter values. This is not a definitive yes or no (the server will tell us when we ask), we just want to cheaply @@ -248,59 +240,52 @@ var EgwApp = /** @class */ (function () { * @param filter_fields List of filter field names eg: [owner, cat_id] * @return boolean True if the nextmatch filters might include the entry, false if not */ - EgwApp.prototype._push_field_filter = function (pushData, nm, filter_fields) { - var filters = {}; - for (var i = 0; i < filter_fields.length; i++) { + _push_field_filter(pushData, nm, filter_fields) { + let filters = {}; + for (let i = 0; i < filter_fields.length; i++) { filters[filter_fields[i]] = { col: filter_fields[i], filter_values: [] }; } // Get current filter values - var value = nm.getValue(); + let value = nm.getValue(); if (!value || !value.col_filter) return false; - for (var _i = 0, _a = Object.values(filters); _i < _a.length; _i++) { - var field_filter = _a[_i]; - var val = value.col_filter[field_filter.col]; + for (let field_filter of Object.values(filters)) { + let val = value.col_filter[field_filter.col]; if (val && (typeof val == "string" && val.trim().length > 0 || typeof val == "object" && !jQuery.isEmptyObject(val))) { field_filter.filter_values.push(val); } } - var _loop_2 = function (field_filter) { + // check filters against pushData.acl data + for (let field_filter of Object.values(filters)) { // no filter set if (field_filter.filter_values.length == 0) - return "continue"; + continue; // acl value is a scalar (not array) --> check contained in filter if (pushData.acl && typeof pushData.acl[field_filter.col] !== 'object') { if (field_filter.filter_values.indexOf(pushData.acl[field_filter.col]) < 0) { - return { value: false }; + return false; } - return "continue"; + continue; } // acl value is an array (eg. tr_assigned) --> check intersection with filter - if (!field_filter.filter_values.filter(function (account) { return pushData.acl[field_filter.col].indexOf(account) >= 0; }).length) { - return { value: false }; + if (!field_filter.filter_values.filter(account => pushData.acl[field_filter.col].indexOf(account) >= 0).length) { + return false; } - }; - // check filters against pushData.acl data - for (var _b = 0, _c = Object.values(filters); _b < _c.length; _b++) { - var field_filter = _c[_b]; - var state_2 = _loop_2(field_filter); - if (typeof state_2 === "object") - return state_2.value; } return true; - }; + } /** * Get (possible) app-specific uid * * @param {object} pushData see push method for individual attributes */ - EgwApp.prototype.uid = function (pushData) { + uid(pushData) { return pushData.app + '::' + pushData.id; - }; + } /** * Open an entry. * @@ -310,12 +295,12 @@ var EgwApp = /** @class */ (function () { * @param _action * @param _senders */ - EgwApp.prototype.open = function (_action, _senders) { + open(_action, _senders) { var id_app = _senders[0].id.split('::'); egw.open(id_app[1], this.appname); - }; - EgwApp.prototype._do_action = function (action_id, selected) { - }; + } + _do_action(action_id, selected) { + } /** * A generic method to action to server asynchronously * @@ -327,7 +312,7 @@ var EgwApp = /** @class */ (function () { * @param {egwAction} _action * @param {egwActionObject[]} _elems */ - EgwApp.prototype.action = function (_action, _elems) { + action(_action, _elems) { // let user confirm select-all var select_all = _action.getManager().getActionById("select_all"); var confirm_msg = (_elems.length > 1 || select_all && select_all.checked) && @@ -336,11 +321,11 @@ var EgwApp = /** @class */ (function () { if (typeof confirm_msg != 'undefined') { var that = this; var action_id = _action.id; - et2_widget_dialog_1.et2_dialog.show_dialog(function (button_id, value) { - if (button_id != et2_widget_dialog_1.et2_dialog.NO_BUTTON) { + et2_dialog.show_dialog(function (button_id, value) { + if (button_id != et2_dialog.NO_BUTTON) { that._do_action(action_id, _elems); } - }, confirm_msg, egw.lang('Confirmation required'), null, et2_widget_dialog_1.et2_dialog.BUTTONS_YES_NO, et2_widget_dialog_1.et2_dialog.QUESTION_MESSAGE); + }, confirm_msg, egw.lang('Confirmation required'), null, et2_dialog.BUTTONS_YES_NO, et2_dialog.QUESTION_MESSAGE); } else if (typeof this._do_action == 'function') { this._do_action(_action.id, _elems); @@ -361,7 +346,7 @@ var EgwApp = /** @class */ (function () { nm.getInstanceManager().submit(); } } - }; + } /** * Set the application's state to the given state. * @@ -376,7 +361,7 @@ var EgwApp = /** @class */ (function () { * @param {string} template template name to check, instead of trying all templates of current app * @return {boolean} false - Returns false to stop event propagation */ - EgwApp.prototype.setState = function (state, template) { + setState(state, template) { var _a; // State should be an object, not a string, but we'll parse if (typeof state == "string") { @@ -397,7 +382,7 @@ var EgwApp = /** @class */ (function () { } // Try and find a nextmatch widget, and set its filters var nextmatched = false; - var et2 = template ? etemplate2_1.etemplate2.getByTemplate(template) : etemplate2_1.etemplate2.getByApplication(this.appname); + var et2 = template ? etemplate2.getByTemplate(template) : etemplate2.getByApplication(this.appname); for (var i = 0; i < et2.length; i++) { et2[i].widgetContainer.iterateOver(function (_widget) { // Firefox has trouble with spaces in search @@ -417,7 +402,7 @@ var EgwApp = /** @class */ (function () { } _widget.applyFilters(state.state || state.filter || {}); nextmatched = true; - }, this, et2_extension_nextmatch_1.et2_nextmatch); + }, this, et2_nextmatch); if (nextmatched) return false; } @@ -434,7 +419,7 @@ var EgwApp = /** @class */ (function () { } egw.open_link(url, undefined, undefined, this.appname); return false; - }; + } /** * Retrieve the current state of the application for future restoration * @@ -447,17 +432,17 @@ var EgwApp = /** @class */ (function () { * * @return {object} Application specific map representing the current state */ - EgwApp.prototype.getState = function () { + getState() { var state = {}; // Try and find a nextmatch widget, and set its filters - var et2 = etemplate2_1.etemplate2.getByApplication(this.appname); + var et2 = etemplate2.getByApplication(this.appname); for (var i = 0; i < et2.length; i++) { et2[i].widgetContainer.iterateOver(function (_widget) { state = _widget.getValue(); - }, this, et2_extension_nextmatch_1.et2_nextmatch); + }, this, et2_nextmatch); } return state; - }; + } /** * Function to load selected row from nm into a template view * @@ -466,7 +451,7 @@ var EgwApp = /** @class */ (function () { * @param {boolean} _noEdit defines whether to set edit button or not default is false * @param {function} et2_callback function to run after et2 is loaded */ - EgwApp.prototype.viewEntry = function (_action, _senders, _noEdit, et2_callback) { + viewEntry(_action, _senders, _noEdit, et2_callback) { //full id in nm var id = _senders[0].id; // flag for edit button @@ -551,7 +536,7 @@ var EgwApp = /** @class */ (function () { 'validation_errors': this.et2.getArrayMgr('validation_errors').data }; // etemplate2 object for view - this.et2_view = new etemplate2_1.etemplate2(this.viewTemplate[0], ''); + this.et2_view = new etemplate2(this.viewTemplate[0], ''); framework.pushState('view'); if (templateName) { this.et2_view.load(this.appname + '.' + templateName, templateURL, data, typeof et2_callback == 'function' ? et2_callback : function () { }, app); @@ -559,13 +544,13 @@ var EgwApp = /** @class */ (function () { // define a global close function for view template // in order to be able to destroy view on action this.et2_view.close = destroy; - }; + } /** * Initializes actions and handlers on sidebox (delete) * * @param {jQuery} sidebox jQuery of DOM node */ - EgwApp.prototype._init_sidebox = function (sidebox) { + _init_sidebox(sidebox) { // Initialize egw tutorial sidebox, but only for non-popups, as calendar edit app.js has this.et2 set to tutorial et2 object if (!this.egw.is_popup()) { var egw_fw = egw_getFramework(); @@ -638,7 +623,7 @@ var EgwApp = /** @class */ (function () { return true; } return false; - }; + } /** * Add a new favorite * @@ -648,7 +633,7 @@ var EgwApp = /** @class */ (function () { * * @param {object} [state] State settings to be merged into the application state */ - EgwApp.prototype.add_favorite = function (state) { + add_favorite(state) { if (typeof this.favorite_popup == "undefined" || // Create popup if it's not defined yet (this.favorite_popup && typeof this.favorite_popup.group != "undefined" && !this.favorite_popup.group.isAttached())) // recreate the favorite popup if the group selectbox is not attached (eg. after et2 submit) @@ -704,30 +689,30 @@ var EgwApp = /** @class */ (function () { console.log(this); // Stop the normal bubbling if this is called on click return false; - }; + } /** * Update favorite items in nm fav. menu * */ - EgwApp.prototype._refresh_fav_nm = function () { + _refresh_fav_nm() { var self = this; - if (etemplate2_1.etemplate2 && etemplate2_1.etemplate2.getByApplication) { - var et2 = etemplate2_1.etemplate2.getByApplication(self.appname); + if (etemplate2 && etemplate2.getByApplication) { + var et2 = etemplate2.getByApplication(self.appname); for (var i = 0; i < et2.length; i++) { et2[i].widgetContainer.iterateOver(function (_widget) { _widget.stored_filters = _widget.load_favorites(self.appname); _widget.init_filters(_widget); - }, self, et2_widget_favorites_1.et2_favorites); + }, self, et2_favorites); } } else { throw new Error("_refresh_fav_nm():Either et2 is not ready/ not there yet. Make sure that etemplate2 is ready before call this method."); } - }; + } /** * Create the "Add new" popup dialog */ - EgwApp.prototype._create_favorite_popup = function () { + _create_favorite_popup() { var self = this; var favorite_prefix = 'favorite_'; // Clear old, if existing @@ -758,7 +743,7 @@ var EgwApp = /** @class */ (function () { var apps = egw().user('apps'); var is_admin = (typeof apps['admin'] != "undefined"); if (is_admin) { - this.favorite_popup.group = et2_core_widget_1.et2_createWidget("select-account", { + this.favorite_popup.group = et2_createWidget("select-account", { id: "favorite[group]", account_type: "groups", empty_label: "Groups", @@ -855,14 +840,14 @@ var EgwApp = /** @class */ (function () { } }, this)); return false; - }; + } /** * Delete a favorite from the list and update preferences * Registered as a handler on the delete icons * * @param {jQuery.event} event event object */ - EgwApp.prototype.delete_favorite = function (event) { + delete_favorite(event) { // Don't do the menu event.stopImmediatePropagation(); var app = event.data; @@ -874,7 +859,7 @@ var EgwApp = /** @class */ (function () { line.addClass('loading'); // Make sure first var do_delete = function (button_id) { - if (button_id != et2_widget_dialog_1.et2_dialog.YES_BUTTON) { + if (button_id != et2_dialog.YES_BUTTON) { line.removeClass('loading'); return; } @@ -897,16 +882,16 @@ var EgwApp = /** @class */ (function () { }, jQuery(trash).parentsUntil("li").parent(), true, jQuery(trash).parentsUntil("li").parent()); request.sendRequest(true); }; - et2_widget_dialog_1.et2_dialog.show_dialog(do_delete, (egw.lang("Delete") + " " + name + "?"), egw.lang("Delete"), null, et2_widget_dialog_1.et2_dialog.BUTTONS_YES_NO, et2_widget_dialog_1.et2_dialog.QUESTION_MESSAGE); + et2_dialog.show_dialog(do_delete, (egw.lang("Delete") + " " + name + "?"), egw.lang("Delete"), null, et2_dialog.BUTTONS_YES_NO, et2_dialog.QUESTION_MESSAGE); return false; - }; + } /** * Mark the favorite closest matching the current state * * Closest matching takes into account not set values, so we pick the favorite * with the most matching values without a value that differs. */ - EgwApp.prototype.highlight_favorite = function () { + highlight_favorite() { if (!this.sidebox) return; var state = this.getState(); @@ -992,11 +977,11 @@ var EgwApp = /** @class */ (function () { if (best_match) { jQuery('li[data-id="' + best_match + '"]', this.sidebox).addClass('ui-state-highlight'); } - }; + } /** * Fix scrolling iframe browsed by iPhone/iPod/iPad touch devices */ - EgwApp.prototype._fix_iFrameScrolling = function () { + _fix_iFrameScrolling() { if (/iPhone|iPod|iPad/.test(navigator.userAgent)) { jQuery("iframe").on({ load: function () { @@ -1014,24 +999,24 @@ var EgwApp = /** @class */ (function () { } }); } - }; + } /** * Set document title, uses getWindowTitle to get the correct title, * otherwise set it with uniqueID as default title */ - EgwApp.prototype._set_Window_title = function () { + _set_Window_title() { var title = this.getWindowTitle(); if (title) { document.title = this.et2._inst.uniqueId + ": " + title; } - }; + } /** * Window title getter function in order to set the window title * this can be overridden on each application app.js file to customize the title value * * @returns {string} window title */ - EgwApp.prototype.getWindowTitle = function () { + getWindowTitle() { var titleWidget = this.et2.getWidgetById('title'); if (titleWidget) { return titleWidget.options.value; @@ -1039,7 +1024,7 @@ var EgwApp = /** @class */ (function () { else { return this.et2._inst.uniqueId; } - }; + } /** * Handler for drag and drop when dragging nextmatch rows from mail app * and dropped on a row in the current application. We copy the mail into @@ -1062,7 +1047,7 @@ var EgwApp = /** @class */ (function () { * @param {egwActionObject[]} _selected Dragged mail rows * @param {egwActionObject} _target Current application's nextmatch row the mail was dropped on */ - EgwApp.prototype.handle_dropped_mail = function (_action, _selected, _target) { + handle_dropped_mail(_action, _selected, _target) { /** * Mail doesn't support link system, so we copy it to VFS */ @@ -1081,13 +1066,13 @@ var EgwApp = /** @class */ (function () { egw.refresh(data.msg || '', ids[0], ids[1], 'update'); }).sendRequest(true); } - }; + } /** * Get json data for videos from the given url * * @return {Promise, object} return Promise, json object as resolved result and error message in case of failure */ - EgwApp.prototype.egwTutorialGetData = function () { + egwTutorialGetData() { var self = this; return new Promise(function (_resolve, _reject) { var resolve = _resolve; @@ -1099,7 +1084,7 @@ var EgwApp = /** @class */ (function () { }).sendRequest(); }, 0); }); - }; + } /** * Create and Render etemplate2 for egroupware tutorial * sidebox option. The .xet file is stored in api/templates/default/egw_tutorials @@ -1132,9 +1117,9 @@ var EgwApp = /** @class */ (function () { * * @param {DOMNode} div */ - EgwApp.prototype.egwTutorial_init = function (div) { + egwTutorial_init(div) { // et2 object - var etemplate = new etemplate2_1.etemplate2(div, ''); + var etemplate = new etemplate2(div, ''); var template = egw.webserverUrl + '/api/templates/default/egw_tutorial.xet?1'; this.egwTutorialGetData().then(function (_data) { var lang = egw.preference('lang'); @@ -1160,27 +1145,27 @@ var EgwApp = /** @class */ (function () { }, function (_err) { console.log(_err); }); - }; + } /** * Open popup to show given tutorial id * @param {string} _tuid tutorial object id * - tuid: appname-lang-index */ - EgwApp.prototype.egwTutorialPopup = function (_tuid) { + egwTutorialPopup(_tuid) { var url = egw.link('/index.php', 'menuaction=api.EGroupware\\Api\\Framework\\Tutorial.popup&tuid=' + _tuid); egw.open_link(url, '_blank', '960x580'); - }; + } /** * Function to set video iframe base on selected tutorial from tutorials box * * @param {string} _url */ - EgwApp.prototype.tutorial_videoOnClick = function (_url) { - var frame = etemplate2_1.etemplate2.getByApplication('api')[0].widgetContainer.getWidgetById('src'); + tutorial_videoOnClick(_url) { + var frame = etemplate2.getByApplication('api')[0].widgetContainer.getWidgetById('src'); if (frame) { frame.set_value(_url); } - }; + } /** * Function calls on discard checkbox and will set * the egw_tutorial_noautoload preference @@ -1188,17 +1173,17 @@ var EgwApp = /** @class */ (function () { * @param {type} egw * @param {type} widget */ - EgwApp.prototype.tutorial_autoloadDiscard = function (egw, widget) { + tutorial_autoloadDiscard(egw, widget) { if (widget) { this.egw.set_preference('common', 'egw_tutorial_noautoload', widget.get_value()); } - }; + } /** * Check if Mailvelope is available, open (or create) "egroupware" keyring and call callback with it * * @param {function} _callback called if and only if mailvelope is available (context is this!) */ - EgwApp.prototype.mailvelopeAvailable = function (_callback) { + mailvelopeAvailable(_callback) { var self = this; var callback = jQuery.proxy(_callback, this); if (typeof mailvelope !== 'undefined') { @@ -1209,7 +1194,7 @@ var EgwApp = /** @class */ (function () { self.mailvelopeOpenKeyring().then(callback); }); } - }; + } /** * mailvelope object contains SyncHandlers * @@ -1218,7 +1203,7 @@ var EgwApp = /** @class */ (function () { * @property {function} backup function called by Mailvelope to upload a public keyring backup * @property {function} restore function called by Mailvelope to restore a public keyring backup */ - EgwApp.prototype.mailvelopeSyncHandler = function () { + mailvelopeSyncHandler() { return { /** * function called by Mailvelope to upload a public keyring @@ -1304,7 +1289,7 @@ var EgwApp = /** @class */ (function () { }); } }; - }; + } /** * Function for backup file operations * @@ -1318,7 +1303,7 @@ var EgwApp = /** @class */ (function () { * @param {type} _errorCallback function called when the operation fails * @param {type} _data data which needs to be stored in file via PUT command */ - EgwApp.prototype._mailvelopeBackupFileOperator = function (_url, _cmd, _successCallback, _errorCallback, _data) { + _mailvelopeBackupFileOperator(_url, _cmd, _successCallback, _errorCallback, _data) { var ajaxObj = { url: _url || egw.webserverUrl + '/webdav.php/home/' + egw.user('account_lid') + '/.PGP-Key-Backup', method: _cmd, @@ -1341,7 +1326,7 @@ var EgwApp = /** @class */ (function () { break; } jQuery.ajax(ajaxObj); - }; + } /** * Create backup dialog * @param {string} _selector DOM selector to attach backupDialog @@ -1349,7 +1334,7 @@ var EgwApp = /** @class */ (function () { * * @returns {Promise.} */ - EgwApp.prototype.mailvelopeCreateBackupDialog = function (_selector, _initSetup) { + mailvelopeCreateBackupDialog(_selector, _initSetup) { var self = this; var selector = _selector || 'body'; var initSetup = _initSetup; @@ -1377,22 +1362,22 @@ var EgwApp = /** @class */ (function () { reject(_err); }); }); - }; + } /** * Delete backup key from filesystem */ - EgwApp.prototype.mailvelopeDeleteBackup = function () { + mailvelopeDeleteBackup() { var self = this; - et2_widget_dialog_1.et2_dialog.show_dialog(function (_button_id) { - if (_button_id == et2_widget_dialog_1.et2_dialog.YES_BUTTON) { + et2_dialog.show_dialog(function (_button_id) { + if (_button_id == et2_dialog.YES_BUTTON) { self._mailvelopeBackupFileOperator(undefined, 'DELETE', function () { self.egw.message(self.egw.lang('The backup key has been deleted.')); }, function (_err) { self.egw.message(self.egw.lang('Was not able to delete the backup key because %1', _err)); }); } - }, self.egw.lang('Are you sure, you would like to delete the backup key?'), self.egw.lang('Delete backup key'), {}, et2_widget_dialog_1.et2_dialog.BUTTONS_YES_NO_CANCEL, et2_widget_dialog_1.et2_dialog.QUESTION_MESSAGE, undefined, self.egw); - }; + }, self.egw.lang('Are you sure, you would like to delete the backup key?'), self.egw.lang('Delete backup key'), {}, et2_dialog.BUTTONS_YES_NO_CANCEL, et2_dialog.QUESTION_MESSAGE, undefined, self.egw); + } /** * Create mailvelope restore dialog * @param {string} _selector DOM selector to attach restorDialog @@ -1400,7 +1385,7 @@ var EgwApp = /** @class */ (function () { * * @returns {Promise} */ - EgwApp.prototype.mailvelopeCreateRestoreDialog = function (_selector, _restorePassword) { + mailvelopeCreateRestoreDialog(_selector, _restorePassword) { var self = this; var restorePassword = _restorePassword; var selector = _selector || 'body'; @@ -1425,13 +1410,13 @@ var EgwApp = /** @class */ (function () { reject(_err); }); }); - }; + } /** * Create a dialog to show all backup/restore options * * @returns {undefined} */ - EgwApp.prototype.mailvelopeCreateBackupRestoreDialog = function () { + mailvelopeCreateBackupRestoreDialog() { var self = this; var appname = egw.app_name(); var menu = [ @@ -1447,7 +1432,7 @@ var EgwApp = /** @class */ (function () { { label: "Backup Key", image: "save", onclick: "app." + appname + ".mailvelopeCreateBackupDialog('#_mvelo', false)" } ]; var dialog = function (_content, _callback) { - return et2_core_widget_1.et2_createWidget("dialog", { + return et2_createWidget("dialog", { callback: function (_button_id, _value) { if (typeof _callback == "function") { _callback.call(this, _button_id, _value.value); @@ -1482,18 +1467,18 @@ var EgwApp = /** @class */ (function () { else { this.mailvelopeInstallationOffer(); } - }; + } /** * Create a dialog and offers installation option for installing mailvelope plugin * plus it offers a video tutorials to get the user morte familiar with mailvelope */ - EgwApp.prototype.mailvelopeInstallationOffer = function () { + mailvelopeInstallationOffer() { var buttons = [ { "text": egw.lang('Install'), id: 'install', image: 'check', "default": true }, { "text": egw.lang('Close'), id: 'close', image: 'cancelled' } ]; var dialog = function (_content, _callback) { - return et2_core_widget_1.et2_createWidget("dialog", { + return et2_createWidget("dialog", { callback: function (_button_id, _value) { if (typeof _callback == "function") { _callback.call(this, _button_id, _value.value); @@ -1528,23 +1513,23 @@ var EgwApp = /** @class */ (function () { else if (typeof InstallTrigger != 'undefined' && InstallTrigger.enabled()) { InstallTrigger.install({ mailvelope: "https://download.mailvelope.com/releases/latest/mailvelope.firefox.xpi" }, function (_url, _status) { if (_status == 0) { - et2_widget_dialog_1.et2_dialog.alert(egw.lang('Mailvelope addon installation succeded. Now you may configure the options.')); + et2_dialog.alert(egw.lang('Mailvelope addon installation succeded. Now you may configure the options.')); return; } else { - et2_widget_dialog_1.et2_dialog.alert(egw.lang('Mailvelope addon installation failed! Please try again.')); + et2_dialog.alert(egw.lang('Mailvelope addon installation failed! Please try again.')); } }); } } }); - }; + } /** * Open (or create) "egroupware" keyring and call callback with it * * @returns {Promise.} Keyring or Error with message */ - EgwApp.prototype.mailvelopeOpenKeyring = function () { + mailvelopeOpenKeyring() { var self = this; return new Promise(function (_resolve, _reject) { if (self.mailvelope_keyring) @@ -1595,16 +1580,16 @@ var EgwApp = /** @class */ (function () { }); delete buttons[1].default; } - et2_widget_dialog_1.et2_dialog.show_dialog(function (_button_id) { - if (_button_id != et2_widget_dialog_1.et2_dialog.NO_BUTTON) { + et2_dialog.show_dialog(function (_button_id) { + if (_button_id != et2_dialog.NO_BUTTON) { var keys = {}; keys[self.egw.user('account_id')] = _pubKey; - self.egw.json('addressbook.addressbook_bo.ajax_set_pgp_keys', [keys, _button_id != et2_widget_dialog_1.et2_dialog.YES_BUTTON ? true : undefined]).sendRequest() + self.egw.json('addressbook.addressbook_bo.ajax_set_pgp_keys', [keys, _button_id != et2_dialog.YES_BUTTON ? true : undefined]).sendRequest() .then(function (_data) { self.egw.message(_data.response['0'].data); }); } - }, self.egw.lang('It is recommended to store your public key in addressbook, so other users can write you encrypted mails.'), self.egw.lang('Store your public key in Addressbook?'), {}, buttons, et2_widget_dialog_1.et2_dialog.QUESTION_MESSAGE, undefined, self.egw); + }, self.egw.lang('It is recommended to store your public key in addressbook, so other users can write you encrypted mails.'), self.egw.lang('Store your public key in Addressbook?'), {}, buttons, et2_dialog.QUESTION_MESSAGE, undefined, self.egw); }, function (_err) { self.egw.message(_err.message + "\n\n" + self.egw.lang("You will NOT be able to send or receive encrypted mails before completing that step!"), 'error'); @@ -1618,25 +1603,25 @@ var EgwApp = /** @class */ (function () { }); }); }); - }; + } /** * Mailvelope uses Domain without first part: eg. "stylite.de" for "egw.stylite.de" * * @returns {string} */ - EgwApp.prototype._mailvelopeDomain = function () { + _mailvelopeDomain() { var parts = document.location.hostname.split('.'); if (parts.length > 1) parts.shift(); return parts.join('.'); - }; + } /** * Check if we have a key for all recipients * * @param {Array} _recipients * @returns {Promise.} Array of recipients or Error with recipients without key */ - EgwApp.prototype.mailvelopeGetCheckRecipients = function (_recipients) { + mailvelopeGetCheckRecipients(_recipients) { // replace rfc822 addresses with raw email, as Mailvelop does not like them and lowercase all email var rfc822_preg = /<([^'" <>]+)>$/; var recipients = _recipients.map(function (_recipient) { @@ -1686,7 +1671,7 @@ var EgwApp = /** @class */ (function () { reject(_err); }); }); - }; + } /** * Check if the share action is enabled for this entry * @@ -1695,9 +1680,9 @@ var EgwApp = /** @class */ (function () { * @param {egwActionObject} _target * @returns {boolean} if action is enabled */ - EgwApp.prototype.is_share_enabled = function (_action, _entries, _target) { + is_share_enabled(_action, _entries, _target) { return true; - }; + } /** * create a share-link for the given entry * @@ -1710,7 +1695,7 @@ var EgwApp = /** @class */ (function () { * @param {Object} _extra Additional (app-specific or special) parameters * @returns {Boolean} returns false if not successful */ - EgwApp.prototype.share_link = function (_action, _senders, _target, _writable, _files, _callback, _extra) { + share_link(_action, _senders, _target, _writable, _files, _callback, _extra) { var path = _senders[0].id; if (!path) { return this.egw.message(this.egw.lang('Missing share path. Unable to create share.'), 'error'); @@ -1731,8 +1716,8 @@ var EgwApp = /** @class */ (function () { _extra = {}; } return egw.json('EGroupware\\Api\\Sharing::ajax_create', [_action.id, path, _writable, _files, _extra], _callback ? _callback : this._share_link_callback, this, true, this).sendRequest(); - }; - EgwApp.prototype.share_merge = function (_action, _senders, _target) { + } + share_merge(_action, _senders, _target) { var parent = _action.parent.parent; var _writable = false; var _files = false; @@ -1755,12 +1740,12 @@ var EgwApp = /** @class */ (function () { // Process document after all shares created return nm_action(_action, _senders, _target); }); - }; + } /** * Share-link callback * @param {object} _data */ - EgwApp.prototype._share_link_callback = function (_data) { + _share_link_callback(_data) { if (_data.msg || _data.share_link) window.egw_refresh(_data.msg, this.appname); var copy_link_to_clipboard = function (evt) { @@ -1777,7 +1762,7 @@ var EgwApp = /** @class */ (function () { egw.message('Failed to copy the link!'); }; jQuery("body").on("click", "[name=share_link]", copy_link_to_clipboard); - et2_core_widget_1.et2_createWidget("dialog", { + et2_createWidget("dialog", { callback: function (button_id, value) { jQuery("body").off("click", "[name=share_link]", copy_link_to_clipboard); return true; @@ -1787,7 +1772,7 @@ var EgwApp = /** @class */ (function () { width: 450, value: { content: { "share_link": _data.share_link } } }); - }; + } /** * Keep a list of all EgwApp instances * @@ -1796,27 +1781,25 @@ var EgwApp = /** @class */ (function () { * @private * @param app_obj */ - EgwApp._register_instance = function (app_obj) { + static _register_instance(app_obj) { // Reject improper objects if (!app_obj.appname) return; EgwApp._instances.push(app_obj); - }; + } /** * Iterator over all app instances * * Use for(const app of EgwApp) {...} to iterate over all app objects. */ - EgwApp[Symbol.iterator] = function () { + static [Symbol.iterator]() { return EgwApp._instances[Symbol.iterator](); - }; - /** - * In some cases (CRM) a private, disconnected app instance is created instead of - * using the global. We want to be able to access them for observer() & push(), so - * we track all instances. - */ - EgwApp._instances = []; - return EgwApp; -}()); -exports.EgwApp = EgwApp; + } +} +/** + * In some cases (CRM) a private, disconnected app instance is created instead of + * using the global. We want to be able to access them for observer() & push(), so + * we track all instances. + */ +EgwApp._instances = []; //# sourceMappingURL=egw_app.js.map \ No newline at end of file diff --git a/api/js/jsapi/egw_calendar.js b/api/js/jsapi/egw_calendar.js index 257ff2bdd4..3c20543ba3 100644 --- a/api/js/jsapi/egw_calendar.js +++ b/api/js/jsapi/egw_calendar.js @@ -19,6 +19,7 @@ // egw_jquery; egw_css; */ +import './egw_core.js'; /** * Date and timepicker diff --git a/api/js/jsapi/egw_config.js b/api/js/jsapi/egw_config.js index 01e5559ac7..277dd436c2 100644 --- a/api/js/jsapi/egw_config.js +++ b/api/js/jsapi/egw_config.js @@ -13,6 +13,7 @@ /*egw:uses egw_core; */ +import './egw_core.js'; egw.extend('config', egw.MODULE_GLOBAL, function() { diff --git a/api/js/jsapi/egw_css.js b/api/js/jsapi/egw_css.js index a6260e284b..868279b66d 100644 --- a/api/js/jsapi/egw_css.js +++ b/api/js/jsapi/egw_css.js @@ -13,6 +13,7 @@ /*egw:uses egw_core; */ +import './egw_core.js'; /** * Module which allows to add stylesheet rules at runtime. Exports the following diff --git a/api/js/jsapi/egw_data.js b/api/js/jsapi/egw_data.js index 4638ec7387..28a7f86631 100644 --- a/api/js/jsapi/egw_data.js +++ b/api/js/jsapi/egw_data.js @@ -14,6 +14,8 @@ egw_core; egw_debug; */ +import './egw_core.js'; +import './egw_json.js'; // for egw.registerJSONPlugin /** * Module storing and updating row data diff --git a/api/js/jsapi/egw_debug.js b/api/js/jsapi/egw_debug.js index f8763c50b8..92ed6582a2 100644 --- a/api/js/jsapi/egw_debug.js +++ b/api/js/jsapi/egw_debug.js @@ -13,6 +13,7 @@ /*egw:uses egw_core; */ +import './egw_core.js'; /** * Log debug messages to browser console and persistent html5 localStorage diff --git a/api/js/jsapi/egw_files.js b/api/js/jsapi/egw_files.js index 78cb64767b..4cd8a24883 100644 --- a/api/js/jsapi/egw_files.js +++ b/api/js/jsapi/egw_files.js @@ -15,6 +15,7 @@ egw_ready; egw_debug; */ +import './egw_core.js'; /** * @augments Class @@ -146,17 +147,19 @@ egw.extend('files', egw.MODULE_WND_LOCAL, function(_app, _wnd) * @param {function} _callback called after JS files are loaded and executed * @param {object} _context * @param {string} _prefix prefix for _jsFiles + * @return Promise */ includeJS: function(_jsFiles, _callback, _context, _prefix) { - // use egw_LAB object of correct window, not always the main window - var egw_LAB = (this.window || window).egw_LAB; - // Also allow including a single javascript file if (typeof _jsFiles === 'string') { _jsFiles = [_jsFiles]; } + const promise = import(_prefix ? _jsFiles.map((src) => _prefix+src) : _jsFiles); + return typeof _callback === 'undefined' ? promise : promise.then(_callback.call(_context)); + + // @todo check the prefix stuff // LABjs uses prefix only if url is not absolute, so removing leading / if necessary and add it to prefix if (_prefix) { diff --git a/api/js/jsapi/egw_images.js b/api/js/jsapi/egw_images.js index ddb27d726e..9d538b6f53 100644 --- a/api/js/jsapi/egw_images.js +++ b/api/js/jsapi/egw_images.js @@ -13,6 +13,7 @@ /*egw:uses egw_core; */ +import './egw_core.js'; egw.extend('images', egw.MODULE_GLOBAL, function() { diff --git a/api/js/jsapi/egw_jquery.js b/api/js/jsapi/egw_jquery.js index 8104a26908..27b1701fed 100644 --- a/api/js/jsapi/egw_jquery.js +++ b/api/js/jsapi/egw_jquery.js @@ -14,6 +14,7 @@ egw_files; egw_ready; */ +import './egw_core.js'; /** * NOT USED diff --git a/api/js/jsapi/egw_json.js b/api/js/jsapi/egw_json.js index 8f522e6b6b..58e5ed948c 100644 --- a/api/js/jsapi/egw_json.js +++ b/api/js/jsapi/egw_json.js @@ -17,6 +17,8 @@ egw_files; egw_debug; */ +import './egw_core.js'; +import './egw_utils.js'; /** * Module sending json requests @@ -57,7 +59,7 @@ egw.extend('json', egw.MODULE_WND_LOCAL, function(_app, _wnd) * @param {object} _sender * @param {egw} _egw */ - function json_request(_menuaction, _parameters, _callback, _context, + window.json_request = function(_menuaction, _parameters, _callback, _context, _async, _sender, _egw) { // Copy the parameters @@ -103,7 +105,7 @@ egw.extend('json', egw.MODULE_WND_LOCAL, function(_app, _wnd) * @param {function} error option error callback(_msg) used instead our default this.error * @param {int} reconnect timeout in ms (internal) */ - json_request.prototype.openWebSocket = function(url, tokens, account_id, error, reconnect) + window.json_request.prototype.openWebSocket = function(url, tokens, account_id, error, reconnect) { const min_reconnect_time = 1000; const max_reconnect_time = 300000; @@ -191,7 +193,7 @@ egw.extend('json', egw.MODULE_WND_LOCAL, function(_app, _wnd) * * @return {jqXHR|boolean} jQuery jqXHR request object or for async==="keepalive" boolean is returned */ - json_request.prototype.sendRequest = function(async, method, error) + window.json_request.prototype.sendRequest = function(async, method, error) { if(typeof async != "undefined") { @@ -242,7 +244,7 @@ egw.extend('json', egw.MODULE_WND_LOCAL, function(_app, _wnd) * @param {XMLHTTP} _xmlhttp * @param {string} _err */ - json_request.prototype.handleError = function(_xmlhttp, _err) { + window.json_request.prototype.handleError = function(_xmlhttp, _err) { // Don't error about an abort if(_err !== 'abort') { @@ -269,7 +271,7 @@ egw.extend('json', egw.MODULE_WND_LOCAL, function(_app, _wnd) } }; - json_request.prototype.handleResponse = function(data) { + window.json_request.prototype.handleResponse = function(data) { if (data && typeof data.response != 'undefined') { if (egw.preference('show_generation_time', 'common', false) == "1") diff --git a/api/js/jsapi/egw_jsonq.js b/api/js/jsapi/egw_jsonq.js index b5cf0daf06..880fd25c41 100644 --- a/api/js/jsapi/egw_jsonq.js +++ b/api/js/jsapi/egw_jsonq.js @@ -14,6 +14,7 @@ egw_core; egw_debug; */ +import './egw_core.js'; egw.extend('jsonq', egw.MODULE_GLOBAL, function() { diff --git a/api/js/jsapi/egw_lang.js b/api/js/jsapi/egw_lang.js index 6a6b96d877..1b2456a96c 100644 --- a/api/js/jsapi/egw_lang.js +++ b/api/js/jsapi/egw_lang.js @@ -15,6 +15,7 @@ egw_files; egw_ready; */ +import './egw_core.js'; /** * @augments Class diff --git a/api/js/jsapi/egw_links.js b/api/js/jsapi/egw_links.js index 12e11c5906..0513cb34e3 100644 --- a/api/js/jsapi/egw_links.js +++ b/api/js/jsapi/egw_links.js @@ -13,6 +13,7 @@ /*egw:uses egw_core; */ +import './egw_core.js'; /** * @augments Class diff --git a/api/js/jsapi/egw_message.js b/api/js/jsapi/egw_message.js index 9857e0a077..9dce3e6be9 100644 --- a/api/js/jsapi/egw_message.js +++ b/api/js/jsapi/egw_message.js @@ -12,6 +12,8 @@ /*egw:uses egw_core; */ +import './egw_core.js'; +import './egw_json.js'; // for registerJSONPlugin /** * Methods to display a success or error message and the app-header diff --git a/api/js/jsapi/egw_notification.js b/api/js/jsapi/egw_notification.js index 32add97b8c..5ac13b21d4 100644 --- a/api/js/jsapi/egw_notification.js +++ b/api/js/jsapi/egw_notification.js @@ -12,6 +12,7 @@ /*egw:uses egw_core; */ +import './egw_core.js'; /** * Methods to display browser notification diff --git a/api/js/jsapi/egw_open.js b/api/js/jsapi/egw_open.js index 31de272fca..7c920093d3 100644 --- a/api/js/jsapi/egw_open.js +++ b/api/js/jsapi/egw_open.js @@ -14,6 +14,7 @@ egw_core; egw_links; */ +import './egw_core.js'; /** * @augments Class diff --git a/api/js/jsapi/egw_preferences.js b/api/js/jsapi/egw_preferences.js index 3695616b55..a57cdf54f7 100644 --- a/api/js/jsapi/egw_preferences.js +++ b/api/js/jsapi/egw_preferences.js @@ -13,6 +13,7 @@ /*egw:uses egw_core; */ +import './egw_core.js'; egw.extend('preferences', egw.MODULE_GLOBAL, function() { diff --git a/api/js/jsapi/egw_ready.js b/api/js/jsapi/egw_ready.js index 04cbd08139..84d82b9c66 100644 --- a/api/js/jsapi/egw_ready.js +++ b/api/js/jsapi/egw_ready.js @@ -14,6 +14,7 @@ egw_utils; egw_debug; */ +import './egw_core.js'; /** * @augments Class diff --git a/api/js/jsapi/egw_store.js b/api/js/jsapi/egw_store.js index bf4709c1df..30864ad835 100644 --- a/api/js/jsapi/egw_store.js +++ b/api/js/jsapi/egw_store.js @@ -14,6 +14,7 @@ egw_ready; egw_debug; */ +import './egw_core.js'; /** * Store is a wrapper around browser based, persistant storage. diff --git a/api/js/jsapi/egw_tail.js b/api/js/jsapi/egw_tail.js index b4fe73477e..e6c437a18b 100644 --- a/api/js/jsapi/egw_tail.js +++ b/api/js/jsapi/egw_tail.js @@ -10,6 +10,8 @@ * @version $Id$ */ +import '../../../vendor/bower-asset/jquery/dist/jquery.js'; +import './egw_json.js'; jQuery(function() { @@ -73,7 +75,7 @@ jQuery(function() jQuery('input[id^="empty_log"]').on('click',function(){ button_log(this.getAttribute('id')); }); - egw_LAB.wait(function() { + //egw_LAB.wait(function() { jQuery(document).ready(function() { if (typeof filename !='undefined' && filename.length > 0) @@ -83,5 +85,5 @@ jQuery(function() } }); jQuery(window).resize(resize_log); - }); + //}); }); diff --git a/api/js/jsapi/egw_tooltip.js b/api/js/jsapi/egw_tooltip.js index 64a76365d7..e159b88112 100644 --- a/api/js/jsapi/egw_tooltip.js +++ b/api/js/jsapi/egw_tooltip.js @@ -14,6 +14,7 @@ vendor.bower-asset.jquery.dist.jquery; egw_core; */ +import './egw_core.js'; /** * diff --git a/api/js/jsapi/egw_user.js b/api/js/jsapi/egw_user.js index 69167ddcda..0fc37b7456 100644 --- a/api/js/jsapi/egw_user.js +++ b/api/js/jsapi/egw_user.js @@ -13,6 +13,7 @@ /*egw:uses egw_core; */ +import './egw_core.js'; egw.extend('user', egw.MODULE_GLOBAL, function() { diff --git a/api/js/jsapi/egw_utils.js b/api/js/jsapi/egw_utils.js index d3af201ba0..d83b3ec0d3 100644 --- a/api/js/jsapi/egw_utils.js +++ b/api/js/jsapi/egw_utils.js @@ -12,6 +12,7 @@ /*egw:uses egw_core; */ +import './egw_core.js'; egw.extend('utils', egw.MODULE_GLOBAL, function() { diff --git a/api/js/jsapi/jsapi.js b/api/js/jsapi/jsapi.js index 135789c8f3..a0287485dd 100644 --- a/api/js/jsapi/jsapi.js +++ b/api/js/jsapi/jsapi.js @@ -11,35 +11,9 @@ * @version $Id$ */ -/***********************************************\ -* INITIALIZATION * -\***********************************************/ -if (document.all) -{ - navigator.userAgent.toLowerCase().indexOf('msie 5') != -1 ? is_ie5 = true : is_ie5 = false; - is_ie = true; - is_moz1_6 = false; - is_mozilla = false; - is_ns4 = false; -} -else if (document.getElementById) -{ - navigator.userAgent.toLowerCase().match('mozilla.*rv[:]1\.6.*gecko') ? is_moz1_6 = true : is_moz1_6 = false; - is_ie = false; - is_ie5 = false; - is_mozilla = true; - is_ns4 = false; -} -else if (document.layers) -{ - is_ie = false; - is_ie5 = false; - is_moz1_6 = false; - is_mozilla = false; - is_ns4 = true; -} +'use strict'; -//console.log('is_ie='+is_ie+', is_ie5='+is_ie5+', is_mozilla='+is_mozilla+', is_moz1_6='+is_moz1_6+', is_ns4='+is_ns4); +import '../../../vendor/bower-asset/jquery/dist/jquery.js'; /** * Check whether the console object is defined - if not, define one @@ -67,7 +41,7 @@ if (typeof window.console == 'undefined') * the result js will be written to _html.js. */ -egw_seperateJavaScript = function(_html) +window.egw_seperateJavaScript = function(_html) { var html = typeof _html.html == 'string'?_html.html:''; @@ -95,7 +69,7 @@ egw_seperateJavaScript = function(_html) /** * Inserts the script tags inside the given html into the dom tree */ -function egw_insertJS(_html) +window.egw_insertJS = function(_html) { // Insert each script element seperately if (_html) @@ -147,7 +121,7 @@ function egw_insertJS(_html) /** * Returns the top window which contains the current egw_instance, even for popup windows */ -function egw_topWindow() +window.egw_topWindow = function() { return egw.top; } @@ -156,7 +130,7 @@ function egw_topWindow() * Returns the window object of the current application * @param string _app is the name of the application which requests the window object */ -function egw_appWindow(_app) +window.egw_appWindow = function(_app) { var framework = egw_getFramework(); if(framework && framework.egw_appWindow) return framework.egw_appWindow(_app); @@ -168,7 +142,7 @@ function egw_appWindow(_app) * @param _app * @param _url */ -function egw_appWindowOpen(_app, _url) +window.egw_appWindowOpen = function(_app, _url) { if (typeof _url == "undefined") { _url = "about:blank"; @@ -180,7 +154,7 @@ function egw_appWindowOpen(_app, _url) * Returns the current egw application * @param string _name is only used for fallback, if an onlder version of jdots is used. */ -function egw_getApp(_name) +window.egw_getApp = function(_name) { return window.parent.framework.getApplicationByName(_name); } @@ -190,7 +164,7 @@ function egw_getApp(_name) * * @deprecated use egw(window).app_name() */ -function egw_getAppName() +window.egw_getAppName = function() { if (typeof egw_appName == 'undefined') { @@ -222,7 +196,7 @@ function egw_getAppName() * @param {string} _msg_type 'error', 'warning' or 'success' (default) * @deprecated use egw(window).refresh() instead */ -function egw_refresh(_msg, _app, _id, _type, _targetapp, _replace, _with, _msg_type) +window.egw_refresh = function(_msg, _app, _id, _type, _targetapp, _replace, _with, _msg_type) { egw(window).refresh(_msg, _app, _id, _type, _targetapp, _replace, _with, _msg_type); } @@ -234,7 +208,7 @@ function egw_refresh(_msg, _app, _id, _type, _targetapp, _replace, _with, _msg_t * @param {string} _type 'error', 'warning' or 'success' (default) * @deprecated use egw(window).message(_msg, _type) */ -function egw_message(_msg, _type) +window.egw_message = function(_msg, _type) { egw(window).message(_msg, _type); } @@ -246,7 +220,7 @@ function egw_message(_msg, _type) * @param {string} _app Application name, if not for the current app @deprecated use egw(window).app_header(_header, _app) */ -function egw_app_header(_header,_app) +window.egw_app_header = function(_header,_app) { egw(window).app_header(_header, _app); } @@ -267,7 +241,7 @@ function egw_app_header(_header,_app) * @param string target target of window to open * @deprecated use egw.open() */ -function egw_open(id, app, type, extra, target) +window.egw_open = function(id, app, type, extra, target) { window.egw.open(id, app, type, extra, target); } @@ -332,7 +306,7 @@ window.register_app_refresh = function(appname, refresh_func) } -function egw_set_checkbox_multiselect_enabled(_id, _enabled) +window.egw_set_checkbox_multiselect_enabled = function(_id, _enabled) { //Retrieve the checkbox_multiselect base div var ms = document.getElementById('exec['+_id+']'); @@ -381,7 +355,7 @@ function egw_set_checkbox_multiselect_enabled(_id, _enabled) * @returns {DOMWindow|undefined} * @deprecated use egw.openPopup(_url, _width, _height, _windowName, _app, _returnID, _status) */ -function egw_openWindowCentered2(_url, _windowName, _width, _height, _status, _app, _returnID) +window.egw_openWindowCentered2 = function(_url, _windowName, _width, _height, _status, _app, _returnID) { return egw(window).openPopup(_url, _width, _height, _windowName, _app, _returnID, _status); } @@ -389,17 +363,17 @@ function egw_openWindowCentered2(_url, _windowName, _width, _height, _status, _a /** * @deprecated use egw.openPopup(_url, _width, _height, _windowName, _app, _returnID, _status) */ -function egw_openWindowCentered(_url, _windowName, _width, _height) +window.egw_openWindowCentered = function(_url, _windowName, _width, _height) { return egw_openWindowCentered2(_url, _windowName, _width, _height, 'no', false, true); } // return the left position of the window -function egw_getWindowLeft() +window.egw_getWindowLeft = function() { // workaround for Fennec bug https://bugzilla.mozilla.org/show_bug.cgi?format=multiple&id=648250 window.(outerHeight|outerWidth|screenX|screenY) throw exception try { - if(is_mozilla) return window.screenX; + return window.screenX; } catch (e) {} @@ -407,11 +381,11 @@ function egw_getWindowLeft() } // return the left position of the window -function egw_getWindowTop() +window.egw_getWindowTop = function() { // workaround for Fennec bug https://bugzilla.mozilla.org/show_bug.cgi?format=multiple&id=648250 window.(outerHeight|outerWidth|screenX|screenY) throw exception try { - if(is_mozilla) return window.screenY; + return window.screenY; } catch (e) {} @@ -419,43 +393,23 @@ function egw_getWindowTop() } // get the outerWidth of the browser window. For IE we simply return the innerWidth -function egw_getWindowInnerWidth() +window.egw_getWindowInnerWidth = function() { - if (is_mozilla) - { - return window.innerWidth; - } - else - { - // works only after the body has parsed - //return document.body.offsetWidth; - return document.body.clientWidth; - //return document.documentElement.clientWidth; - } + return window.innerWidth; } // get the outerHeight of the browser window. For IE we simply return the innerHeight -function egw_getWindowInnerHeight() +window.egw_getWindowInnerHeight = function() { - if (is_mozilla) - { - return window.innerHeight; - } - else - { - // works only after the body has parsed - //return document.body.offsetHeight; - //return document.body.clientHeight; - return document.documentElement.clientHeight; - } + return window.innerHeight; } // get the outerWidth of the browser window. For IE we simply return the innerWidth -function egw_getWindowOuterWidth() +window.egw_getWindowOuterWidth = function() { // workaround for Fennec bug https://bugzilla.mozilla.org/show_bug.cgi?format=multiple&id=648250 window.(outerHeight|outerWidth|screenX|screenY) throw exception try { - if (is_mozilla) return window.outerWidth; + return window.outerWidth; } catch (e) {} @@ -463,11 +417,11 @@ function egw_getWindowOuterWidth() } // get the outerHeight of the browser window. For IE we simply return the innerHeight -function egw_getWindowOuterHeight() +window.egw_getWindowOuterHeight = function() { // workaround for Fennec bug https://bugzilla.mozilla.org/show_bug.cgi?format=multiple&id=648250 window.(outerHeight|outerWidth|screenX|screenY) throw exception try { - if (is_mozilla) return window.outerHeight; + return window.outerHeight; } catch (e) {} @@ -477,7 +431,7 @@ function egw_getWindowOuterHeight() // ie selectbox dropdown menu hack. as ie is not able to resize dropdown menus from selectboxes, we // read the content of the dropdown menu and present it as popup resized for the user. if the user // clicks/seleckts a value, the selection is posted back to the origial selectbox -function dropdown_menu_hack(el) +window.dropdown_menu_hack = function(el) { if(el.runtimeStyle) { @@ -536,14 +490,13 @@ function dropdown_menu_hack(el) } - f_hide = function(e) + f.hide = function(e) { if(window.event && window.event.srcElement && window.event.srcElement.tagName && window.event.srcElement.tagName.toLowerCase()=="select"){return true;} fwin.style.display="none"; } - f.hide = f_hide; - document.attachEvent("onclick",f_hide); - document.attachEvent("onkeydown",f_hide); + document.attachEvent("onclick",f.hide); + document.attachEvent("onkeydown",f.hide); } return f; @@ -654,7 +607,6 @@ function dropdown_menu_hack(el) } self.focus(); el.menu.show( mx , my , mw, mh , el); - sync=null; if(mb.options.selected) { mb.scrollTop = mb.options.selected.offsetTop; @@ -718,7 +670,7 @@ function dropdown_menu_hack(el) * @param _app * @deprecated use egw(window).link_handler(_link, _app) instead */ -function egw_link_handler(_link, _app) +window.egw_link_handler = function(_link, _app) { egw(window).link_handler(_link, _app); } @@ -728,9 +680,9 @@ function egw_link_handler(_link, _app) * * @ToDo: should be removed if uiaccountsel class is no longer in use */ -function addOption(id,label,value,do_onchange) +window.addOption = function(id,label,value,do_onchange) { - selectBox = document.getElementById(id); + let selectBox = document.getElementById(id); for (var i=0; i < selectBox.length; i++) { // check existing entries if they're already there and only select them in that case if (selectBox.options[i].value == value) { @@ -754,7 +706,7 @@ function addOption(id,label,value,do_onchange) * @param {string} _mime current mime type * @returns {object|null} returns object of filemanager editor hook */ -function egw_get_file_editor_prefered_mimes(_mime) +window.egw_get_file_editor_prefered_mimes = function(_mime) { var fe = jQuery.extend(true, {},egw.link_get_registry('filemanager-editor')); var ex_mimes = egw.preference('collab_excluded_mimes', 'filemanager'); diff --git a/api/js/labjs/LAB-debug.min.js b/api/js/labjs/LAB-debug.min.js deleted file mode 100755 index 99e7b142fe..0000000000 --- a/api/js/labjs/LAB-debug.min.js +++ /dev/null @@ -1,5 +0,0 @@ -/*! 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/api/js/labjs/LAB.js b/api/js/labjs/LAB.js deleted file mode 100755 index e710dfea28..0000000000 --- a/api/js/labjs/LAB.js +++ /dev/null @@ -1,5 +0,0 @@ -/*! 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/api/js/labjs/LAB.min.js b/api/js/labjs/LAB.min.js deleted file mode 100755 index e710dfea28..0000000000 --- a/api/js/labjs/LAB.min.js +++ /dev/null @@ -1,5 +0,0 @@ -/*! 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/api/js/labjs/LAB.src.js b/api/js/labjs/LAB.src.js deleted file mode 100755 index 99807cd222..0000000000 --- a/api/js/labjs/LAB.src.js +++ /dev/null @@ -1,514 +0,0 @@ -/*! 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 diff --git a/api/js/login.js b/api/js/login.js index e7f77755f2..cbad4ff11d 100644 --- a/api/js/login.js +++ b/api/js/login.js @@ -7,6 +7,8 @@ * @link https://www.egroupware.org */ +import '../../vendor/bower-asset/jquery/dist/jquery.js'; // also ensures egw_LAB.wait exists! + /* if login page is not in top window, set top windows location to it */ if (top !== window) top.location = window.location; diff --git a/api/lang.php b/api/lang.php index d208ae054d..55a477dd50 100644 --- a/api/lang.php +++ b/api/lang.php @@ -60,10 +60,11 @@ if (!count(Api\Translation::$lang_arr)) Api\Translation::add_app($_GET['app'], 'en'); } +$content = "import './js/jsapi/egw_lang.js';\n\n"; // fix for phrases containing \n -$content = 'egw.set_lang_arr("'.$_GET['app'].'", '.str_replace('\\\\n', '\\n', +$content .= 'window.egw.set_lang_arr("'.$_GET['app'].'", '.str_replace('\\\\n', '\\n', json_encode(Api\Translation::$lang_arr, JSON_PARTIAL_OUTPUT_ON_ERROR|JSON_UNESCAPED_SLASHES|JSON_UNESCAPED_UNICODE)). - ', egw && egw.window !== window);'; + ', window.egw && window.egw.window !== window);'; // we run our own gzip compression, to set a correct Content-Length of the encoded content if (in_array('gzip', explode(',',$_SERVER['HTTP_ACCEPT_ENCODING'])) && function_exists('gzencode')) diff --git a/api/src/Framework.php b/api/src/Framework.php index a2fc76daa5..3b0f4fc1c7 100644 --- a/api/src/Framework.php +++ b/api/src/Framework.php @@ -58,7 +58,7 @@ abstract class Framework extends Framework\Extra /** * Application specific template directories to try in given order for CSS * - * @var string + * @var string[] */ var $template_dirs = array(); @@ -1053,7 +1053,7 @@ abstract class Framework extends Framework\Extra { $java_script .= $GLOBALS['egw_info']['flags']['java_script_thirst'] . "\n"; } - // add configuration, link-registry, images, user-data and -perferences for non-popup windows + // add configuration, link-registry, images, user-data and -preferences for non-popup windows // specifying etag in url to force reload, as we send expires header if ($GLOBALS['egw_info']['flags']['js_link_registry'] || isset($_GET['cd']) && $_GET['cd'] === 'popup') { @@ -1074,13 +1074,19 @@ abstract class Framework extends Framework\Extra } $extra['url'] = $GLOBALS['egw_info']['server']['webserver_url']; - $extra['include'] = array_map(function($str){return substr($str,1);}, self::get_script_links(true), array(1)); + $map = null; + $extra['include'] = array_map(static function($str){ + return substr($str,1); + }, self::get_script_links(true, false, $map), array(1)); $extra['app'] = $GLOBALS['egw_info']['flags']['currentapp']; - // Load LABjs ONCE here - $java_script .= '\n". - '\n"; + + // load our clientside entrypoint egw.js + $java_script .= ''; echo '