replace LAB.js with native es5 loading

This commit is contained in:
Ralf Becker 2021-06-05 20:39:39 +02:00
parent 688f970ec0
commit 592b7fb97d
54 changed files with 1258 additions and 1785 deletions

View File

@ -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'))

View File

@ -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'))

View File

@ -451,7 +451,7 @@ egwFnct.prototype.exec = function()
*/
var _egw_mobileBrowser = null;
function egwIsMobile() {
window.egwIsMobile = function() {
if (_egw_mobileBrowser == null)
{

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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

View File

@ -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);
};

View File

@ -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)
{

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -12,5 +12,6 @@
/*egw:uses
/vendor/bower-asset/jquery/dist/jquery.js;
*/
import '../../../vendor/bower-asset/jquery/dist/jquery.js';
jQuery.noConflict();

View File

@ -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

View File

@ -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 <RalfBecker@outdoor-training.de>
* @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<Promise<unknown>[]>}
*/
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);
}

View File

@ -1,4 +1,3 @@
"use strict";
/**
* EGroupware clientside Application javascript base object
*
@ -10,16 +9,13 @@
* @author Hadi Nategh <hn@groupware.org>
* @author Nathan Gray <ng@groupware.org>
*/
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.<backupPopupId, Error>}
*/
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, Error>} 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, Error>} 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

View File

@ -19,6 +19,7 @@
// egw_jquery;
egw_css;
*/
import './egw_core.js';
/**
* Date and timepicker

View File

@ -13,6 +13,7 @@
/*egw:uses
egw_core;
*/
import './egw_core.js';
egw.extend('config', egw.MODULE_GLOBAL, function()
{

View File

@ -13,6 +13,7 @@
/*egw:uses
egw_core;
*/
import './egw_core.js';
/**
* Module which allows to add stylesheet rules at runtime. Exports the following

View File

@ -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

View File

@ -13,6 +13,7 @@
/*egw:uses
egw_core;
*/
import './egw_core.js';
/**
* Log debug messages to browser console and persistent html5 localStorage

View File

@ -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)
{

View File

@ -13,6 +13,7 @@
/*egw:uses
egw_core;
*/
import './egw_core.js';
egw.extend('images', egw.MODULE_GLOBAL, function()
{

View File

@ -14,6 +14,7 @@
egw_files;
egw_ready;
*/
import './egw_core.js';
/**
* NOT USED

View File

@ -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")

View File

@ -14,6 +14,7 @@
egw_core;
egw_debug;
*/
import './egw_core.js';
egw.extend('jsonq', egw.MODULE_GLOBAL, function()
{

View File

@ -15,6 +15,7 @@
egw_files;
egw_ready;
*/
import './egw_core.js';
/**
* @augments Class

View File

@ -13,6 +13,7 @@
/*egw:uses
egw_core;
*/
import './egw_core.js';
/**
* @augments Class

View File

@ -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

View File

@ -12,6 +12,7 @@
/*egw:uses
egw_core;
*/
import './egw_core.js';
/**
* Methods to display browser notification

View File

@ -14,6 +14,7 @@
egw_core;
egw_links;
*/
import './egw_core.js';
/**
* @augments Class

View File

@ -13,6 +13,7 @@
/*egw:uses
egw_core;
*/
import './egw_core.js';
egw.extend('preferences', egw.MODULE_GLOBAL, function()
{

View File

@ -14,6 +14,7 @@
egw_utils;
egw_debug;
*/
import './egw_core.js';
/**
* @augments Class

View File

@ -14,6 +14,7 @@
egw_ready;
egw_debug;
*/
import './egw_core.js';
/**
* Store is a wrapper around browser based, persistant storage.

View File

@ -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);
});
//});
});

View File

@ -14,6 +14,7 @@
vendor.bower-asset.jquery.dist.jquery;
egw_core;
*/
import './egw_core.js';
/**
*

View File

@ -13,6 +13,7 @@
/*egw:uses
egw_core;
*/
import './egw_core.js';
egw.extend('user', egw.MODULE_GLOBAL, function()
{

View File

@ -12,6 +12,7 @@
/*egw:uses
egw_core;
*/
import './egw_core.js';
egw.extend('utils', egw.MODULE_GLOBAL, function()
{

View File

@ -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');

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -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<chain_group.scripts.length; i++) {
if (chain_group.scripts[i].ready && chain_group.scripts[i].exec_trigger) {
any_scripts_ready = true;
chain_group.scripts[i].exec_trigger();
chain_group.scripts[i].exec_trigger = null;
}
}
return any_scripts_ready;
}
// creates a script load listener
function create_script_load_listener(elem,registry_item,flag,onload) {
elem.onload = elem.onreadystatechange = function() {
if ((elem.readyState && elem.readyState != "complete" && elem.readyState != "loaded") || registry_item[flag]) return;
elem.onload = elem.onreadystatechange = null;
onload();
};
}
// script executed handler
function script_executed(registry_item) {
registry_item.ready = registry_item.finished = true;
for (var i=0; i<registry_item.finished_listeners.length; i++) {
registry_item.finished_listeners[i]();
}
registry_item.ready_listeners = [];
registry_item.finished_listeners = [];
}
// make the request for a scriptha
function request_script(chain_opts,script_obj,registry_item,onload,preload_this_script) {
// setTimeout() "yielding" prevents some weird race/crash conditions in older browsers
setTimeout(function(){
var script, src = script_obj.real_src, xhr;
// don't proceed until `append_to` is ready to append to
if ("item" in append_to) { // check if `append_to` ref is still a live node list
if (!append_to[0]) { // `append_to` node not yet ready
// try again in a little bit -- note: will re-call the anonymous function in the outer setTimeout, not the parent `request_script()`
setTimeout(arguments.callee,25);
return;
}
// reassign from live node list ref to pure node ref -- avoids nasty IE bug where changes to DOM invalidate live node lists
append_to = append_to[0];
}
script = document.createElement("script");
if (script_obj.type) script.type = script_obj.type;
if (script_obj.charset) script.charset = script_obj.charset;
// should preloading be used for this script?
if (preload_this_script) {
// real script preloading?
if (real_preloading) {
/*!START_DEBUG*/if (chain_opts[_Debug]) log_msg("start script preload: "+src);/*!END_DEBUG*/
registry_item.elem = script;
if (explicit_preloading) { // explicit preloading (aka, Zakas' proposal)
script.preload = true;
script.onpreload = onload;
}
else {
script.onreadystatechange = function(){
if (script.readyState == "loaded") onload();
};
}
script.src = src;
// NOTE: no append to DOM yet, appending will happen when ready to execute
}
// same-domain and XHR allowed? use XHR preloading
else if (preload_this_script && src.indexOf(root_domain) == 0 && chain_opts[_UseLocalXHR]) {
xhr = new XMLHttpRequest(); // note: IE never uses XHR (it supports true preloading), so no more need for ActiveXObject fallback for IE <= 7
/*!START_DEBUG*/if (chain_opts[_Debug]) log_msg("start script preload (xhr): "+src);/*!END_DEBUG*/
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
xhr.onreadystatechange = function(){}; // fix a memory leak in IE
registry_item.text = xhr.responseText + "\n//@ sourceURL=" + src; // http://blog.getfirebug.com/2009/08/11/give-your-eval-a-name-with-sourceurl/
onload();
}
};
xhr.open("GET",src);
xhr.send();
}
// as a last resort, use cache-preloading
else {
/*!START_DEBUG*/if (chain_opts[_Debug]) log_msg("start script preload (cache): "+src);/*!END_DEBUG*/
script.type = "text/cache-script";
create_script_load_listener(script,registry_item,"ready",function() {
append_to.removeChild(script);
onload();
});
script.src = src;
append_to.insertBefore(script,append_to.firstChild);
}
}
// use async=false for ordered async? parallel-load-serial-execute http://wiki.whatwg.org/wiki/Dynamic_Script_Execution_Order
else if (script_ordered_async) {
/*!START_DEBUG*/if (chain_opts[_Debug]) log_msg("start script load (ordered async): "+src);/*!END_DEBUG*/
script.async = false;
create_script_load_listener(script,registry_item,"finished",onload);
script.src = src;
append_to.insertBefore(script,append_to.firstChild);
}
// otherwise, just a normal script element
else {
/*!START_DEBUG*/if (chain_opts[_Debug]) log_msg("start script load: "+src);/*!END_DEBUG*/
create_script_load_listener(script,registry_item,"finished",onload);
script.src = src;
append_to.insertBefore(script,append_to.firstChild);
}
},0);
}
// create a clean instance of $LAB
function create_sandbox() {
var global_defaults = {},
can_use_preloading = real_preloading || xhr_or_cache_preloading,
queue = [],
registry = {},
instanceAPI
;
// global defaults
global_defaults[_UseLocalXHR] = true;
global_defaults[_AlwaysPreserveOrder] = false;
global_defaults[_AllowDuplicates] = false;
global_defaults[_CacheBust] = false;
/*!START_DEBUG*/global_defaults[_Debug] = false;/*!END_DEBUG*/
global_defaults[_BasePath] = "";
// execute a script that has been preloaded already
function execute_preloaded_script(chain_opts,script_obj,registry_item) {
var script;
function preload_execute_finished() {
if (script != null) { // make sure this only ever fires once
script = null;
script_executed(registry_item);
}
}
if (registry[script_obj.src].finished) return;
if (!chain_opts[_AllowDuplicates]) registry[script_obj.src].finished = true;
script = registry_item.elem || document.createElement("script");
if (script_obj.type) script.type = script_obj.type;
if (script_obj.charset) script.charset = script_obj.charset;
create_script_load_listener(script,registry_item,"finished",preload_execute_finished);
// script elem was real-preloaded
if (registry_item.elem) {
registry_item.elem = null;
}
// script was XHR preloaded
else if (registry_item.text) {
script.onload = script.onreadystatechange = null; // script injection doesn't fire these events
script.text = registry_item.text;
}
// script was cache-preloaded
else {
script.src = script_obj.real_src;
}
append_to.insertBefore(script,append_to.firstChild);
// manually fire execution callback for injected scripts, since events don't fire
if (registry_item.text) {
preload_execute_finished();
}
}
// process the script request setup
function do_script(chain_opts,script_obj,chain_group,preload_this_script) {
var registry_item,
registry_items,
ready_cb = function(){ script_obj.ready_cb(script_obj,function(){ execute_preloaded_script(chain_opts,script_obj,registry_item); }); },
finished_cb = function(){ script_obj.finished_cb(script_obj,chain_group); }
;
script_obj.src = canonical_uri(script_obj.src,chain_opts[_BasePath]);
script_obj.real_src = script_obj.src +
// append cache-bust param to URL?
(chain_opts[_CacheBust] ? ((/\?.*$/.test(script_obj.src) ? "&_" : "?_") + ~~(Math.random()*1E9) + "=") : "")
;
if (!registry[script_obj.src]) registry[script_obj.src] = {items:[],finished:false};
registry_items = registry[script_obj.src].items;
// allowing duplicates, or is this the first recorded load of this script?
if (chain_opts[_AllowDuplicates] || registry_items.length == 0) {
registry_item = registry_items[registry_items.length] = {
ready:false,
finished:false,
ready_listeners:[ready_cb],
finished_listeners:[finished_cb]
};
request_script(chain_opts,script_obj,registry_item,
// which callback type to pass?
(
(preload_this_script) ? // depends on script-preloading
function(){
registry_item.ready = true;
for (var i=0; i<registry_item.ready_listeners.length; i++) {
registry_item.ready_listeners[i]();
}
registry_item.ready_listeners = [];
} :
function(){ script_executed(registry_item); }
),
// signal if script-preloading should be used or not
preload_this_script
);
}
else {
registry_item = registry_items[0];
if (registry_item.finished) {
finished_cb();
}
else {
registry_item.finished_listeners.push(finished_cb);
}
}
}
// creates a closure for each separate chain spawned from this $LAB instance, to keep state cleanly separated between chains
function create_chain() {
var chainedAPI,
chain_opts = merge_objs(global_defaults,{}),
chain = [],
exec_cursor = 0,
scripts_currently_loading = false,
group
;
// called when a script has finished preloading
function chain_script_ready(script_obj,exec_trigger) {
/*!START_DEBUG*/if (chain_opts[_Debug]) log_msg("script preload finished: "+script_obj.real_src);/*!END_DEBUG*/
script_obj.ready = true;
script_obj.exec_trigger = exec_trigger;
advance_exec_cursor(); // will only check for 'ready' scripts to be executed
}
// called when a script has finished executing
function chain_script_executed(script_obj,chain_group) {
/*!START_DEBUG*/if (chain_opts[_Debug]) log_msg("script execution finished: "+script_obj.real_src);/*!END_DEBUG*/
script_obj.ready = script_obj.finished = true;
script_obj.exec_trigger = null;
// check if chain group is all finished
for (var i=0; i<chain_group.scripts.length; i++) {
if (!chain_group.scripts[i].finished) return;
}
// chain_group is all finished if we get this far
chain_group.finished = true;
advance_exec_cursor();
}
// main driver for executing each part of the chain
function advance_exec_cursor() {
while (exec_cursor < chain.length) {
if (is_func(chain[exec_cursor])) {
/*!START_DEBUG*/if (chain_opts[_Debug]) log_msg("$LAB.wait() executing: "+chain[exec_cursor]);/*!END_DEBUG*/
try { chain[exec_cursor++](); } catch (err) {
/*!START_DEBUG*/if (chain_opts[_Debug]) log_error("$LAB.wait() error caught: ",err);/*!END_DEBUG*/
}
continue;
}
else if (!chain[exec_cursor].finished) {
if (check_chain_group_scripts_ready(chain[exec_cursor])) continue;
break;
}
exec_cursor++;
}
// we've reached the end of the chain (so far)
if (exec_cursor == chain.length) {
scripts_currently_loading = false;
group = false;
}
}
// setup next chain script group
function init_script_chain_group() {
if (!group || !group.scripts) {
chain.push(group = {scripts:[],finished:true});
}
}
// API for $LAB chains
chainedAPI = {
// start loading one or more scripts
script:function(){
for (var i=0; i<arguments.length; i++) {
(function(script_obj,script_list){
var splice_args;
if (!is_array(script_obj)) {
script_list = [script_obj];
}
for (var j=0; j<script_list.length; j++) {
init_script_chain_group();
script_obj = script_list[j];
if (is_func(script_obj)) script_obj = script_obj();
if (!script_obj) continue;
if (is_array(script_obj)) {
// set up an array of arguments to pass to splice()
splice_args = [].slice.call(script_obj); // first include the actual array elements we want to splice in
splice_args.unshift(j,1); // next, put the `index` and `howMany` parameters onto the beginning of the splice-arguments array
[].splice.apply(script_list,splice_args); // use the splice-arguments array as arguments for splice()
j--; // adjust `j` to account for the loop's subsequent `j++`, so that the next loop iteration uses the same `j` index value
continue;
}
if (typeof script_obj == "string") script_obj = {src:script_obj};
script_obj = merge_objs(script_obj,{
ready:false,
ready_cb:chain_script_ready,
finished:false,
finished_cb:chain_script_executed
});
group.finished = false;
group.scripts.push(script_obj);
do_script(chain_opts,script_obj,group,(can_use_preloading && scripts_currently_loading));
scripts_currently_loading = true;
if (chain_opts[_AlwaysPreserveOrder]) chainedAPI.wait();
}
})(arguments[i],arguments[i]);
}
return chainedAPI;
},
// force LABjs to pause in execution at this point in the chain, until the execution thus far finishes, before proceeding
wait:function(){
if (arguments.length > 0) {
for (var i=0; i<arguments.length; i++) {
chain.push(arguments[i]);
}
group = chain[chain.length-1];
}
else group = false;
advance_exec_cursor();
return chainedAPI;
}
};
// the first chain link API (includes `setOptions` only this first time)
return {
script:chainedAPI.script,
wait:chainedAPI.wait,
setOptions:function(opts){
merge_objs(opts,chain_opts);
return chainedAPI;
}
};
}
// API for each initial $LAB instance (before chaining starts)
instanceAPI = {
// main API functions
setGlobalDefaults:function(opts){
merge_objs(opts,global_defaults);
return instanceAPI;
},
setOptions:function(){
return create_chain().setOptions.apply(null,arguments);
},
script:function(){
return create_chain().script.apply(null,arguments);
},
wait:function(){
return create_chain().wait.apply(null,arguments);
},
// built-in queuing for $LAB `script()` and `wait()` calls
// useful for building up a chain programmatically across various script locations, and simulating
// execution of the chain
queueScript:function(){
queue[queue.length] = {type:"script", args:[].slice.call(arguments)};
return instanceAPI;
},
queueWait:function(){
queue[queue.length] = {type:"wait", args:[].slice.call(arguments)};
return instanceAPI;
},
runQueue:function(){
var $L = instanceAPI, len=queue.length, i=len, val;
for (;--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);

View File

@ -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;

View File

@ -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'))

View File

@ -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 .= '<script type="text/javascript" src="'.$GLOBALS['egw_info']['server']['webserver_url'].
'/api/js/labjs/LAB.src.js?'.filemtime(EGW_SERVER_ROOT.'/api/js/labjs/LAB.src.js')."\"></script>\n".
'<script type="text/javascript" src="'.$GLOBALS['egw_info']['server']['webserver_url'].
// add import-map before (!) first module
$java_script .= '<script type="importmap" nonce="'.htmlspecialchars(ContentSecurityPolicy::addNonce('script-src')).'">'."\n".
json_encode(['imports' => self::addUrlPrefix($map)], JSON_UNESCAPED_SLASHES|JSON_PRETTY_PRINT)."\n".
"</script>\n";
// load our clientside entrypoint egw.js
$java_script .= '<script type="module" src="'.$GLOBALS['egw_info']['server']['webserver_url'].
'/api/js/jsapi/egw.js?'.filemtime(EGW_SERVER_ROOT.'/api/js/jsapi/egw.js').'" id="egw_script_id"';
// add values of extra parameter and class var as data attributes to script tag of egw.js
@ -1114,6 +1120,27 @@ abstract class Framework extends Framework\Extra
return $java_script;
}
/**
* Add EGroupware URL prefix eg. '/egroupware' to files AND bundles
*
* @param array $map
* @return array
*/
protected static function addUrlPrefix(array $map)
{
if (substr($prefix = $GLOBALS['egw_info']['server']['webserver_url'], 0, 4) === 'http')
{
$prefix = parse_url($prefix, PHP_URL_PATH);
}
$ret = [];
foreach($map as $file => $bundle)
{
$ret[$prefix.$file] = $prefix.$bundle;
}
$ret['jsapi/egw_json'] = $ret['/egw-test/api/js/jsapi/egw_json.js'];
return $ret;
}
/**
* List available themes
*
@ -1466,11 +1493,12 @@ abstract class Framework extends Framework\Extra
*
* @param boolean $return_pathes =false false: return Html script tags, true: return array of file pathes relative to webserver_url
* @param boolean $clear_files =false true clear files after returning them
* @param array& $map on return map file => bundle
* @return string|array see $return_pathes parameter
*/
static public function get_script_links($return_pathes=false, $clear_files=false)
static public function get_script_links($return_pathes=false, $clear_files=false, array &$map=null)
{
$to_include = Framework\Bundle::js_includes(self::$js_include_mgr->get_included_files($clear_files));
$to_include = Framework\Bundle::js_includes(self::$js_include_mgr->get_included_files($clear_files), $map);
if ($return_pathes)
{

View File

@ -183,8 +183,6 @@ abstract class Ajax extends Api\Framework
if (self::$header_done) return '';
self::$header_done = true;
$this->send_headers();
// catch error echo'ed before the header, ob_start'ed in the header.inc.php
$content = ob_get_contents();
ob_end_clean();
@ -267,6 +265,8 @@ abstract class Ajax extends Api\Framework
$this->tpl->set_var($this->_get_header($extra));
$content = $this->tpl->fp('out','head').$content;
$this->send_headers();
if (!$do_framework)
{
return $content;

View File

@ -39,9 +39,10 @@ class Bundle
* Devide js-includes in bundles of javascript files to include eg. api or etemplate2, if minifying is enabled
*
* @param array $js_includes files to include with egw relative url
* @param array& $to_include on return map file => bundle
* @return array egw relative urls to include incl. bundels/minify urls, if enabled
*/
public static function js_includes(array $js_includes)
public static function js_includes(array $js_includes, array &$to_include=null)
{
$file2bundle = array();
if ($GLOBALS['egw_info']['server']['debug_minify'] !== 'True')

View File

@ -1,7 +1,7 @@
<?php
/**
* EGroupware: Class which manages including js files and modules
* (lateron this might be extended to css)
* (later on this might be extended to css)
*
* @link http://www.egroupware.org
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
@ -9,7 +9,6 @@
* @subpackage framework
* @author Andreas Stöckel
* @copyright (c) 2011 Stylite
* @version $Id$
*/
namespace EGroupware\Api\Framework;
@ -18,8 +17,15 @@ namespace EGroupware\Api\Framework;
* Syntax for including JS files form others
* -----------------------------------------
*
* Write a comment starting with "/*egw:uses". A linebreak has to follow.
* Then write all files which have to be included seperated by ";". A JS file
* a) ES5 or TypeScript module imports: import {...} from '<relative path or EGroupware absolute path>'
*
* - import './egw_core.js';
* - import { something } from '../../vendor/class.js';
* - import { something } from './other'; (in TS without extension!)
* @ToDo import { something } from 'module/sub'
*
* b) Write a comment starting with "/*egw:uses". A linebreak has to follow.
* Then write all files which have to be included separated by ";". A JS file
* include may have the following syntax:
*
* 1) File in the same directory as the current file. Simply write the filename
@ -76,6 +82,11 @@ class IncludeMgr
*/
private $debug_processing_file = false;
/**
* @var bool true: echo out debug info, for direct call see end of this file
*/
private $debug_parsing_imports = false;
/**
* Parses the js file for includes and returns all required files
*/
@ -87,68 +98,58 @@ class IncludeMgr
// Mark the file as parsed
$this->parsed_files[$file] = true;
// extension to add, if dependency has none
$extension = substr($file, -3) === '.ts' ? '.ts' : '.js';
$modules = $modules2 = [];
// Try to open the given file
$f = fopen(EGW_SERVER_ROOT.$file, "r");
if ($f !== false)
if (($header = file_get_contents(EGW_SERVER_ROOT.$file, false, null, 0, 2048)))
{
// Only read a maximum of 32 lines until the comment occurs.
$cnt = 0;
$in_uses = false;
$uses = "";
// Read a line
$line = fgets($f);
while ($cnt < 32 && $line !== false)
if ($this->debug_parsing_imports) echo "<p>$file</p>\n";
$matches = null;
if (preg_match_all('/import\s+({[^}]+}\s*from\s+)?["\']([^;\s]+)["\']/', $header, $matches))
{
// Remove everything behind "//"
$pos = strpos($line, "//");
if ($pos !== false)
{
$line = substr($line, 0, $pos);
}
if (!$in_uses)
{
$cnt++;
$in_uses = strpos($line, "/*egw:uses") !== false;
}
else
{
// Check whether we are at the end of the comment
$pos = strpos($line, "*/");
if ($pos === false)
{
$uses .= $line;
}
else
{
$uses .= substr($line, 0, $pos);
break;
}
}
$line = fgets($f);
if ($this->debug_parsing_imports) echo "imports:<div style='white-space: pre'>".json_encode($matches, JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES)."</div>\n";
$modules = $matches[2];
}
// either use es5 import or old /*egw:uses */ annotation
elseif (preg_match('#/\*egw:uses(.*);\s+\*/#sU', $header, $matches) &&
($matches = array_filter(preg_split('/;[^\n]*\n\s*/', trim($matches[1])), static function($use)
{
return !preg_match('#^\s*//#', $use); // filter out commented out ones
})))
{
if ($this->debug_parsing_imports) echo "egw:uses:<div style='white-space: pre'>".json_encode($matches, JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES)."</div>\n";
$modules = array_merge($modules, $matches);
}
// Close the file again
fclose($f);
// Split the "require" string at ";"
$modules = explode(";", $uses);
$modules2 = array();
// Split all modules at "." and remove entries with empty parts
foreach ($modules as $mod)
{
// Remove trailing space characters
$mod = trim($mod);
if ($mod)
{
if ($mod !== trim($mod))
{
throw new \Exception("'$mod' contains whitespace!");
}
// Split the given module string at the dot, if this isn't
// an absolute path (initialized by "/").
if ($mod[0] != '/')
// an relative (starting ./) or absolute path (initialized by "/").
if (substr($mod, 0, 2) === './')
{
if (!preg_match('/\.(js|ts)$/', $mod)) $mod .= $extension;
$mod = [dirname($file).substr($mod, 1)];
}
elseif (substr($mod, 0, 3) === '../')
{
if (!preg_match('/\.(js|ts)$/', $mod)) $mod .= $extension;
$dir = dirname($file);
while(substr($mod, 0, 3) === '../')
{
$mod = substr($mod, 3);
$dir = dirname($dir);
}
$mod = [($dir !== '/' ? $dir : '').'/'.$mod];
}
elseif ($mod[0] != '/')
{
$mod = explode(".", $mod, 3);
}
@ -419,13 +420,29 @@ class IncludeMgr
return $ret;
}
/**
* Get importMap for browser
*/
public function getImportMap()
{
$files = $this->get_included_files();
$imports = array_combine(array_map(static function($url)
{
return parse_url($url, PHP_URL_PATH);
}, $files), $files);
return ['imports' => $imports];
}
/**
* Constructor
*
* @param array $files =null optional files to include as for include_files method
* @param bool $debug_parsing_imports =false true: echo out debug infos
*/
public function __construct(array $files = null)
public function __construct(array $files = null, bool $debug_parsing_imports=false)
{
$this->debug_parsing_imports = $debug_parsing_imports;
if (isset($files) && is_array($files))
{
$this->include_files($files);
@ -438,9 +455,10 @@ class IncludeMgr
if (isset($_SERVER['SCRIPT_FILENAME']) && $_SERVER['SCRIPT_FILENAME'] == __FILE__)
{
define('EGW_SERVER_ROOT', dirname(dirname(dirname(__DIR__))));
include_once(EGW_SERVER_ROOT.'/phpgwapi/inc/common_functions.inc.php');
define('EGW_INCLUDE_ROOT', dirname(dirname(dirname(__DIR__))));
include_once(EGW_SERVER_ROOT.'/api/src/loader/common.php');
$mgr = new IncludeMgr();
$mgr = new IncludeMgr(null, true);
echo "<html>\n<head>\n\t<title>Dependencies</title>\n</head>\n<body>\n";
$paths = !empty($_GET['path']) ? (array)$_GET['path'] : (array)'/stylite/js/filemanager/filemanager.js';

View File

@ -99,6 +99,24 @@ class ContentSecurityPolicy
}
}
/**
* Add a nonce to a given source
*
* @param string $source
* @return string
* @throws \Exception
*/
public static function addNonce($source='script-src')
{
static $nonce=null;
if (!isset($nonce))
{
$nonce = base64_encode(random_bytes(16));
self::add($source, "'nonce-$nonce'");
}
return $nonce;
}
/**
* Set Content-Security-Policy attributes for script-src: 'unsafe-eval' and/or 'unsafe-inline'
*

View File

@ -44,9 +44,10 @@ if (isset($_SERVER['HTTP_IF_NONE_MATCH']) && $_SERVER['HTTP_IF_NONE_MATCH'] == $
exit;
}
$content = 'egw.set_preferences('.$preferences.", 'common', egw && egw.window !== window);\n";
$content .= 'egw.set_preferences('.$ab_preferences.", 'addressbook', egw && egw.window !== window);\n";
$content .= 'egw.set_user('.$user.", egw && egw.window !== window);\n";
$content = "import './js/jsapi/egw_preferences.js';\nimport './js/jsapi/egw_user.js';\n\n";
$content .= 'window.egw.set_preferences('.$preferences.", 'common', window.egw && window.egw.window !== window);\n";
$content .= 'window.egw.set_preferences('.$ab_preferences.", 'addressbook', window.egw && window.egw.window !== window);\n";
$content .= 'window.egw.set_user('.$user.", window.egw && egw.window !== 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'))

View File

@ -28,7 +28,7 @@ if ($GLOBALS['egw_info']['user']['apps']['notifications'])
$minjs = $GLOBALS['egw_info']['server']['debug_minify'] === 'True' ? '' : '.min';
echo '<script src="'. $GLOBALS['egw_info']['server']['webserver_url']. '/notifications/js/notificationajaxpopup'.$minjs.'.js?'.
filemtime(EGW_SERVER_ROOT.'/notifications/js/notificationajaxpopup'.$minjs.'.js').
'" type="text/javascript" id="notifications_script_id" data-poll-interval="'.$popup_poll_interval.
'" type="module" id="notifications_script_id" data-poll-interval="'.$popup_poll_interval.
'" data-langRequire="'. htmlspecialchars(json_encode($langRequire)).'"></script>';
echo '
<div id="egwpopup" style="display: none; z-index: 999;">

View File

@ -9,11 +9,17 @@
* @version $Id$
*/
'use strict';
import '../../vendor/bower-asset/jquery/dist/jquery.js';
/**
* Installs app.notifications used to poll notifications from server and display them
*/
(function()
{
const egw = window.egw; // fix undefined egw
var notifymessages = {};
var _currentRawData = [];
@ -905,9 +911,9 @@
return counter;
};
var lab = egw_LAB || $LAB;
var self = notifications;
lab.wait(function(){
window.egw_ready.then(function()
{
var langRequire = jQuery('#notifications_script_id').attr('data-langRequire');
egw.langRequire(window, [JSON.parse(langRequire)], function()
{

View File

@ -13,6 +13,10 @@
framework.fw_desktop;
/pixelegg/js/slider.js;
*/
import '../../vendor/bower-asset/jquery/dist/jquery.js';
import '../../api/js/framework/fw_desktop.js';
import './slider.js';
(function(window){
"use strict";
@ -20,7 +24,7 @@
* jdots framework object defenition
* here we can add framework methods and also override fw_desktop methods if it is neccessary
*/
var fw_pixelegg = fw_desktop.extend(
window.fw_pixelegg = fw_desktop.extend(
{
/**
* Callback to calculate height of browser iframe or div
@ -111,7 +115,7 @@
/**
* Initialise framework
*/
egw_LAB.wait(function() {
window.egw_ready.then(function() {
function egw_setSideboxSize(_size)
{
document.getElementById('egw_fw_main').style.marginLeft = _size + 'px';

View File

@ -1,4 +1,4 @@
<script src="./api/js/login.js" type="text/javascript"></script>
<script src="./api/js/login.js" type="module"></script>
<div id="loginMainDiv" style="background-image:url({background_file})" class="{stock_background_class}">