mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-11-08 00:54:15 +01:00
phpgwapi:
* Changed way of how "webserverUrl" gets set - any type of data can now be injected into the egw object by creating an object with the data and an entry "prefsOnly" set to true. This allows to ensure, that "webserverUrl" is the first thing that is being set in the egw object (as needed when including new JS/CSS files at runtime) jsapi: * Fixed including JS/CSS files at runtime in other windows than the root window * Added "ready" function/module, which provides an alternative to the $j("ready") function. The ready module provides the functionality to postpone calling the "ready" until certain events happened. * using jQuery calendar object instead of jscalendar in the calendar function. * added "jquery" module which takes care of including all jQuery modules in all windows * added possibility for modules to update constants using the "constant" function. * added possibility for modules to access certain other modules using the "module" function etemplate: * Using new egw(window).ready function to build the template first if loading has finished.
This commit is contained in:
parent
4b83719907
commit
d486e50a57
@ -145,7 +145,7 @@ class etemplate_new extends etemplate_widget_template
|
||||
else // first call
|
||||
{
|
||||
// missing dependency, thought egw:uses jquery.jquery.tools does NOT work, maybe we should rename it to jquery-tools
|
||||
egw_framework::validate_file('jquery','jquery.tools.min');
|
||||
// egw_framework::validate_file('jquery','jquery.tools.min');
|
||||
|
||||
egw_framework::includeCSS('/etemplate/js/test/test.css');
|
||||
common::egw_header();
|
||||
@ -156,8 +156,10 @@ class etemplate_new extends etemplate_widget_template
|
||||
echo '
|
||||
<div id="container"></div>
|
||||
<script>
|
||||
var et2 = new (egw().etemplate2)(document.getElementById("container"), "etemplate_new::ajax_process_content");
|
||||
et2.load("'.$GLOBALS['egw_info']['server']['webserver_url'].$this->rel_path.'",'.json_encode($data).');
|
||||
egw(window).ready(function() {
|
||||
var et2 = new (egw().etemplate2)(document.getElementById("container"), "etemplate_new::ajax_process_content");
|
||||
et2.load("'.$GLOBALS['egw_info']['server']['webserver_url'].$this->rel_path.'",'.json_encode($data).');
|
||||
}, null, true);
|
||||
</script>
|
||||
';
|
||||
common::egw_footer();
|
||||
|
@ -1,5 +1,5 @@
|
||||
/**
|
||||
* eGroupWare eTemplate2 - A simple PHP expression parser written in JS
|
||||
* eGroupWare eTemplate2 - Execution layer for legacy event code
|
||||
*
|
||||
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||
* @package etemplate
|
||||
@ -114,8 +114,14 @@
|
||||
context = _widget.getDOMNode();
|
||||
}
|
||||
|
||||
// Generate the function itself
|
||||
var func = new Function('egw', 'widget', 'window', _code);
|
||||
// Generate the function itself, if it fails, log the error message and
|
||||
// return a function which always returns false
|
||||
try {
|
||||
var func = new Function('egw', 'widget', 'window', 'document', _code);
|
||||
} catch(e) {
|
||||
_widget.egw().debug('error', 'Error while compiling JS code ', _code);
|
||||
return (function() {return false});
|
||||
}
|
||||
|
||||
// Execute the code and return its results, pass the egw instance and
|
||||
// the widget
|
||||
@ -127,7 +133,8 @@
|
||||
egw.debug('log', 'Executing legacy JS code: ', _code);
|
||||
|
||||
// Return the result of the called function
|
||||
return func.call(context, egw, _widget, egw.window);
|
||||
return func.call(context, egw, _widget, egw.window,
|
||||
egw.window.document);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -65,7 +65,7 @@ var et2_date = et2_inputWidget.extend({
|
||||
if(input_time.attr("type") == "time")
|
||||
{
|
||||
this.input_time = input_time;
|
||||
this.input_time.appendTo(node).attr("size", 5);
|
||||
this.input_time.appendTo(this.span).attr("size", 5);
|
||||
// Update internal value if control changes
|
||||
this.input_time.change(this,function(e){e.data.set_value($j(e.target).val());});
|
||||
}
|
||||
@ -78,88 +78,7 @@ var et2_date = et2_inputWidget.extend({
|
||||
this.setDOMNode(this.span[0]);
|
||||
|
||||
// jQuery-UI date picker
|
||||
this.setupPopup(this.input_date, this._type == "date-time");
|
||||
},
|
||||
|
||||
/**
|
||||
* Setup the date-picker popup
|
||||
*/
|
||||
setupPopup: function(node, include_time) {
|
||||
|
||||
if(typeof include_time === "undefined") include_time = false;
|
||||
|
||||
if(this.type == "date" || this.type == "date-time") {
|
||||
// Date format in jQuery UI date format
|
||||
var dateformat = egw().preference("dateformat").replace("Y","yy").replace("d","dd").replace("m","mm").replace("M", "M");
|
||||
|
||||
// First day of the week
|
||||
var first_day = {"Monday": 1, "Sunday": 0, "Saturday": 6};
|
||||
var first_day_pref = this.egw().preference("weekdaystarts","calendar");
|
||||
|
||||
var self = this;
|
||||
|
||||
// Initialize
|
||||
node.datepicker({
|
||||
dateFormat: dateformat,
|
||||
autoSize: true,
|
||||
firstDay: first_day_pref ? first_day[first_day_pref] : 0,
|
||||
showButtonPanel: true, // Today, Done buttons
|
||||
nextText: this.egw().lang("Next"),
|
||||
currentText: this.egw().lang("today"),
|
||||
prevText: this.egw().lang("Prev"),
|
||||
closeText: this.egw().lang("Done"),
|
||||
|
||||
showOtherMonths: true,
|
||||
selectOtherMonths: true,
|
||||
|
||||
showWeek: true, // Week numbers
|
||||
changeMonth: true, // Month selectbox
|
||||
changeYear: true, // Year selectbox
|
||||
|
||||
onClose: function(date_text, picker) {
|
||||
// Only update if there's a change - "" if no date selected
|
||||
if(date_text != "") self.set_value(new Date(
|
||||
picker.selectedYear,
|
||||
picker.selectedMonth,
|
||||
picker.selectedDay,
|
||||
self.input_hours ? self.input_hours.val() : 0,
|
||||
self.input_minutes ? self.input_minutes.val() : 0,
|
||||
0,0
|
||||
));
|
||||
},
|
||||
// Trigger button
|
||||
showOn: "both",
|
||||
buttonImage: this.egw().image('datepopup','phpgwapi'),
|
||||
buttonImageOnly: true
|
||||
});
|
||||
|
||||
// Translate (after initialize has its way)
|
||||
var translate_fields = {
|
||||
"dayNames": false,
|
||||
"dayNamesShort":3,
|
||||
"dayNamesMin": 2,
|
||||
"monthNames": false,
|
||||
"monthNamesShort": 3
|
||||
}
|
||||
var full = [];
|
||||
for(var i in translate_fields)
|
||||
{
|
||||
var trans = this.input_date.datepicker("option",i);
|
||||
// Keep the full one for missing short ones
|
||||
for(var key in trans) {
|
||||
if(translate_fields[i] === false)
|
||||
{
|
||||
trans[key] = this.egw().lang(trans[key]);
|
||||
}
|
||||
else
|
||||
{
|
||||
trans[key] = full[key].substr(0,translate_fields[i]);
|
||||
}
|
||||
}
|
||||
if(translate_fields[i] === false) full = trans;
|
||||
node.datepicker("option",i,trans);
|
||||
}
|
||||
}
|
||||
this.egw().calendar(this.input_date, this._type == "date-time");
|
||||
},
|
||||
|
||||
_make_time_selects: function (node) {
|
||||
|
@ -781,13 +781,39 @@ abstract class egw_framework
|
||||
self::validate_file('/phpgwapi/config.php');
|
||||
self::validate_file('/phpgwapi/images.php',array('template' => $GLOBALS['egw_info']['user']['preferences']['common']['template_set']));
|
||||
}
|
||||
$java_script .= self::get_script_links();
|
||||
|
||||
// set webserver_url for json
|
||||
$java_script .= "<script type=\"text/javascript\">\nwindow.egw_webserverUrl = egw.webserverUrl = '".
|
||||
$java_script .= "<script type=\"text/javascript\">
|
||||
var url = '".
|
||||
($GLOBALS['egw_info']['server']['enforce_ssl'] && substr($GLOBALS['egw_info']['server']['webserver_url'],0,8) != 'https://' ? 'https://'.$_SERVER['HTTP_HOST'] : '').
|
||||
$GLOBALS['egw_info']['server']['webserver_url']."';\n";
|
||||
$java_script .= 'window.egw_appName = "'.$GLOBALS['egw_info']['flags']['currentapp'].'";'."\n";
|
||||
$GLOBALS['egw_info']['server']['webserver_url']."';
|
||||
|
||||
// legacy code
|
||||
egw_webserverUrl = url;
|
||||
|
||||
// reference the egw object from the parent window or set the
|
||||
// webserver url
|
||||
if (window.opener && typeof window.opener.egw != 'undefined')
|
||||
{
|
||||
window['egw'] = window.opener.egw;
|
||||
}
|
||||
else if (window.top && typeof window.top.egw != 'undefined')
|
||||
{
|
||||
window['egw'] = window.top.egw;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create a \"preferences only\" egw object
|
||||
window['egw'] = {
|
||||
'prefsOnly': true,
|
||||
'webserverUrl': url
|
||||
};
|
||||
}
|
||||
</script>";
|
||||
|
||||
$java_script .= self::get_script_links();
|
||||
|
||||
$java_script .= '<script type="text/javascript">window.egw_appName = "'.$GLOBALS['egw_info']['flags']['currentapp'].'";'."\n";
|
||||
|
||||
// add link registry to non-popup windows, if explicit requested (idots_framework::navbar() loads it, if not explicit specified!)
|
||||
if ($GLOBALS['egw_info']['flags']['js_link_registry'])
|
||||
|
@ -27,5 +27,7 @@
|
||||
egw_tooltip;
|
||||
egw_css;
|
||||
egw_calendar;
|
||||
egw_ready;
|
||||
egw_jquery;
|
||||
*/
|
||||
|
||||
|
@ -15,119 +15,106 @@
|
||||
/*egw:uses
|
||||
egw_core;
|
||||
egw_preferences;
|
||||
|
||||
jscalendar.calendar;
|
||||
/phpgwapi/js/jscalendar/lang/calendar-en.js;
|
||||
|
||||
egw_jquery;
|
||||
*/
|
||||
|
||||
egw.extend('calendar', egw.MODULE_WND_LOCAL, function(_app, _wnd) {
|
||||
|
||||
// Instanciate the calendar for this window
|
||||
calendar_closure(_wnd, _wnd.document);
|
||||
|
||||
// Load the translation
|
||||
calendar_lang_closure(_wnd);
|
||||
|
||||
function calendarPreferences()
|
||||
function calendarPreferences(_egw)
|
||||
{
|
||||
// Load the date format from the preferences
|
||||
var dateformat = egw.preference("dateformat");
|
||||
if (!dateformat)
|
||||
{
|
||||
dateformat = "Y-m-d";
|
||||
}
|
||||
// Date format in jQuery UI date format
|
||||
var dateformat = _egw.preference("dateformat")
|
||||
.replace("Y","yy")
|
||||
.replace("d","dd")
|
||||
.replace("m","mm")
|
||||
.replace("M", "M");
|
||||
|
||||
// Transform the given format to the correct date format
|
||||
dateformat = dateformat
|
||||
.replace("Y","%Y")
|
||||
.replace("d","%d")
|
||||
.replace("m","%m")
|
||||
.replace("M", "%b");
|
||||
|
||||
// Load the first weekday from the calendar application preferences
|
||||
var firstDay = egw.preference("weekdaystarts","calendar");
|
||||
// First day of the week
|
||||
var first_day = {"Monday": 1, "Sunday": 0, "Saturday": 6};
|
||||
var first_day_pref = _egw.preference("weekdaystarts","calendar");
|
||||
|
||||
return {
|
||||
"format": dateformat,
|
||||
"firstDay": firstDay,
|
||||
"ifFormat": "%Y/%m/%d",
|
||||
"daFormat": "%Y/%m/%d",
|
||||
"titleFormat": "%B, %Y"
|
||||
'dateformat': dateformat,
|
||||
'firstDay': first_day_pref ? first_day[first_day_pref] : 0
|
||||
}
|
||||
}
|
||||
|
||||
function calendarPopup(_input, _button, _callback, _context)
|
||||
function setupCalendar(_egw, _input, _time, _callback, _context)
|
||||
{
|
||||
var prefs = calendarPreferences(_egw);
|
||||
|
||||
function calendarUpdate(_cal)
|
||||
{
|
||||
// Update the input value
|
||||
_input.value = _cal.date.print(_cal.params.format);
|
||||
var params = {
|
||||
dateFormat: prefs.dateformat,
|
||||
firstDay: prefs.firstDay,
|
||||
|
||||
// Close the popup if a date has been clicked
|
||||
if (_cal.dateClicked)
|
||||
{
|
||||
cal.callCloseHandler();
|
||||
autoSize: true,
|
||||
showButtonPanel: true, // Today, Done buttons
|
||||
showOtherMonths: true,
|
||||
selectOtherMonths: true,
|
||||
showWeek: true, // Week numbers
|
||||
changeMonth: true, // Month selectbox
|
||||
changeYear: true, // Year selectbox
|
||||
|
||||
// Trigger button
|
||||
showOn: "both",
|
||||
buttonImage: _egw.image('datepopup','phpgwapi'),
|
||||
buttonImageOnly: true,
|
||||
|
||||
nextText: _egw.lang('Next'),
|
||||
currentText: _egw.lang('today'),
|
||||
prevText: _egw.lang('Prev'),
|
||||
closeText: _egw.lang('Done'),
|
||||
|
||||
}
|
||||
|
||||
// Get the preferences
|
||||
_egw.$j(_input).datepicker(params);
|
||||
/*
|
||||
onClose: function(date_text, picker) {
|
||||
// Only update if there's a change - "" if no date selected
|
||||
if(date_text != "") self.set_value(new Date(
|
||||
picker.selectedYear,
|
||||
picker.selectedMonth,
|
||||
picker.selectedDay,
|
||||
self.input_hours ? self.input_hours.val() : 0,
|
||||
self.input_minutes ? self.input_minutes.val() : 0,
|
||||
0,0
|
||||
));
|
||||
},
|
||||
});
|
||||
|
||||
// Translate (after initialize has its way)
|
||||
var translate_fields = {
|
||||
"dayNames": false,
|
||||
"dayNamesShort":3,
|
||||
"dayNamesMin": 2,
|
||||
"monthNames": false,
|
||||
"monthNamesShort": 3
|
||||
}
|
||||
|
||||
// Call the callback
|
||||
_callback.call(_context, _cal);
|
||||
}
|
||||
|
||||
function calendarHide(_cal)
|
||||
{
|
||||
_cal.hide();
|
||||
}
|
||||
|
||||
// Read the calendar parameters
|
||||
var params = calendarPreferences();
|
||||
|
||||
// Destroy any existing calendar
|
||||
if (_wnd.calendar)
|
||||
{
|
||||
_wnd.calendar.destroy();
|
||||
}
|
||||
|
||||
// Create a new calendar instance
|
||||
_wnd.calendar = new Calendar(
|
||||
params.firstDay,
|
||||
null,
|
||||
calendarUpdate,
|
||||
calendarHide
|
||||
);
|
||||
_wnd.calendar.showsTime = false;
|
||||
_wnd.calendar.weekNumbers = true;
|
||||
_wnd.calendar.yearStep = 2;
|
||||
_wnd.calendar.setRange(1900, 2999);
|
||||
_wnd.calendar.params = params;
|
||||
|
||||
_wnd.calendar.create();
|
||||
|
||||
_wnd.calendar.setDateFormat(params.format);
|
||||
_wnd.calendar.parseDate($j(_input).val());
|
||||
|
||||
_wnd.calendar.refresh();
|
||||
_wnd.calendar.showAtElement(_button || _input);
|
||||
var full = [];
|
||||
for(var i in translate_fields)
|
||||
{
|
||||
var trans = this.input_date.datepicker("option",i);
|
||||
// Keep the full one for missing short ones
|
||||
for(var key in trans) {
|
||||
if(translate_fields[i] === false)
|
||||
{
|
||||
trans[key] = this.egw().lang(trans[key]);
|
||||
}
|
||||
else
|
||||
{
|
||||
trans[key] = full[key].substr(0,translate_fields[i]);
|
||||
}
|
||||
}
|
||||
if(translate_fields[i] === false) full = trans;
|
||||
node.datepicker("option",i,trans);
|
||||
}*/
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
/**
|
||||
* Transforms either the given input element into a date input or
|
||||
* displays the calendar when clicking on the given input button. When
|
||||
* the date changes, the given callback function is called.
|
||||
*/
|
||||
calendar: function(_input, _button, _callback, _context) {
|
||||
/* $j([_input, _button]).bind('click.calendar', function() {
|
||||
calendarPopup(_input, _button, _callback, _context);
|
||||
})*/
|
||||
$j(_input).bind('click', function() {
|
||||
calendarPopup(_input, _button, _callback, _context);
|
||||
});
|
||||
$j(_button).bind('click', function() {
|
||||
calendarPopup(_input, _button, _callback, _context);
|
||||
});
|
||||
calendar: function(_input, _time, _callback, _context) {
|
||||
setupCalendar(this, _input, _time, _callback, _context);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -71,23 +71,42 @@
|
||||
if (typeof _moduleInstances.app[_app] === 'undefined')
|
||||
{
|
||||
var modInsts = {};
|
||||
_moduleInstances.app[_app] = modInsts;
|
||||
|
||||
// Otherwise create the application specific instances
|
||||
for (var key in _modules)
|
||||
{
|
||||
var mod = _modules[key];
|
||||
if (mod.flags === _egw.MODULE_APP_LOCAL)
|
||||
|
||||
// Check whether the module is actually an application local
|
||||
// instance. As the module instance may already have been
|
||||
// created by another extension (when calling the egw.module
|
||||
// function) we're doing the second check.
|
||||
if (mod.flags === _egw.MODULE_APP_LOCAL
|
||||
&& typeof modInsts[key] === 'undefined')
|
||||
{
|
||||
modInsts[key] = mod.code.call(_egw, _app, window);
|
||||
}
|
||||
}
|
||||
|
||||
_moduleInstances.app[_app] = modInsts;
|
||||
}
|
||||
|
||||
return _moduleInstances.app[_app];
|
||||
}
|
||||
|
||||
function getExistingWndModules(_moduleInstances, _window)
|
||||
{
|
||||
// Search for the specific window instance
|
||||
for (var i = 0; i < _moduleInstances.wnd.length; i++)
|
||||
{
|
||||
if (_moduleInstances.wnd[i].window === _window)
|
||||
{
|
||||
return _moduleInstances.wnd[i].modules;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The getWndModules function returns all window specific api modules for
|
||||
* the given window. If those window specific api instances were not created
|
||||
@ -104,19 +123,13 @@
|
||||
*/
|
||||
function getWndModules(_egw, _modules, _moduleInstances, _instances, _window)
|
||||
{
|
||||
// Search for the specific window instance
|
||||
for (var i = 0; i < _moduleInstances.wnd.length; i++)
|
||||
{
|
||||
var descr = _moduleInstances.wnd[i];
|
||||
|
||||
if (descr.window === _window)
|
||||
{
|
||||
return descr.modules;
|
||||
}
|
||||
var mods = getExistingWndModules(_moduleInstances, _window);
|
||||
if (mods) {
|
||||
return mods;
|
||||
}
|
||||
|
||||
// If none was found, create the slot
|
||||
var mods = {};
|
||||
mods = {};
|
||||
_moduleInstances.wnd.push({
|
||||
'window': _window,
|
||||
'modules': mods
|
||||
@ -133,7 +146,13 @@
|
||||
for (var key in _modules)
|
||||
{
|
||||
var mod = _modules[key];
|
||||
if (mod.flags === _egw.MODULE_WND_LOCAL)
|
||||
|
||||
// Check whether the module is actually a window local instance. As
|
||||
// the module instance may already have been created by another
|
||||
// extension (when calling the egw.module function) we're doing the
|
||||
// second check.
|
||||
if (mod.flags === _egw.MODULE_WND_LOCAL
|
||||
&& typeof mods[key] === 'undefined')
|
||||
{
|
||||
mods[key] = mod.code.call(_egw, null, _window);
|
||||
}
|
||||
@ -279,6 +298,9 @@
|
||||
// Generate the global extension
|
||||
var globalExtension = _code.call(egw, null, window);
|
||||
|
||||
// Store the global extension module
|
||||
_moduleInstances.glo[_module] = globalExtension;
|
||||
|
||||
for (var key in _instances)
|
||||
{
|
||||
for (var i = 0; i < _instances[key].length; i++)
|
||||
@ -294,6 +316,9 @@
|
||||
// Generate the global extension
|
||||
var globalExtension = _code.call(egw, null, window);
|
||||
|
||||
// Store the global extension module
|
||||
_moduleInstances.glo[_module] = globalExtension;
|
||||
|
||||
// Merge the extension into the global instances
|
||||
for (var i = 0; i < _instances['~global~'].length; i++)
|
||||
{
|
||||
@ -344,16 +369,17 @@
|
||||
}
|
||||
}
|
||||
|
||||
if (window.opener && typeof window.opener.egw !== 'undefined')
|
||||
{
|
||||
this['egw'] = window.opener.egw;
|
||||
}
|
||||
else if (window.top && typeof window.top.egw !== 'undefined')
|
||||
{
|
||||
this['egw'] = window.top.egw;
|
||||
}
|
||||
else
|
||||
/**
|
||||
* Creates the egw object --- if the egw object should be created, some data
|
||||
* has already been set inside the object by the egw_framework::header
|
||||
* function and the instance has been marked as "prefsOnly".
|
||||
*/
|
||||
if (typeof window.egw != "undefined" && window.egw.prefsOnly)
|
||||
{
|
||||
// Rescue the old egw object
|
||||
var prefs = window.egw;
|
||||
delete prefs['prefsOnly'];
|
||||
|
||||
/**
|
||||
* Modules contains all currently loaded egw extension modules. A module
|
||||
* is stored as an object of the following form:
|
||||
@ -367,7 +393,8 @@
|
||||
|
||||
var moduleInstances = {
|
||||
'app': {},
|
||||
'wnd': []
|
||||
'wnd': [],
|
||||
'glo': {}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -480,13 +507,6 @@
|
||||
return this.appName;
|
||||
},
|
||||
|
||||
/**
|
||||
* base-URL of the EGroupware installation
|
||||
*
|
||||
* get set via egw_framework::header()
|
||||
*/
|
||||
webserverUrl: "/egroupware",
|
||||
|
||||
/**
|
||||
* The extend function can be used to extend the egw object.
|
||||
*
|
||||
@ -541,6 +561,106 @@
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Very similar to the egw function itself, but the module function
|
||||
* returns just the functions exported by a single extension -- in
|
||||
* this way extensions themselve are capable of accessing each
|
||||
* others functions while they are being instanciated. Yet you
|
||||
* should be carefull not to create any cyclic dependencies.
|
||||
*
|
||||
* @param _module is the name of the module
|
||||
* @param _for may either be a string describing an application,
|
||||
* an object referencing to a window or evaluate to false, in which
|
||||
* case the global instance will be returned.
|
||||
*/
|
||||
module: function(_module, _for) {
|
||||
if (typeof modules[_module] !== 'undefined')
|
||||
{
|
||||
// Return the global instance of the module if _for
|
||||
// evaluates to false
|
||||
if (!_for)
|
||||
{
|
||||
return moduleInstances.glo[_module];
|
||||
}
|
||||
|
||||
// Assume _for is an application name if it is a string.
|
||||
// Check whether the given application instance actually
|
||||
// exists.
|
||||
if (typeof _for === 'string'
|
||||
&& typeof moduleInstances.app[_for] !== 'undefined')
|
||||
{
|
||||
var mods = moduleInstances.app[_for];
|
||||
|
||||
// Otherwise just instanciate the module if it has not
|
||||
// been created yet.
|
||||
if (typeof mods[_module] === 'undefined')
|
||||
{
|
||||
var mod = modules[_module];
|
||||
mods[_module] = mod.code.call(this, _app, window);
|
||||
}
|
||||
|
||||
return mods[_module];
|
||||
}
|
||||
|
||||
// If _for is an object, assume it is a window.
|
||||
if (typeof _for === 'object')
|
||||
{
|
||||
var mods = getExistingWndModules(moduleInstances, _for);
|
||||
|
||||
// Check whether the module container for that window
|
||||
// has been found
|
||||
if (mods != null)
|
||||
{
|
||||
// If the given module has not been instanciated for
|
||||
// this window,
|
||||
if (typeof mods[_module] === 'undefined')
|
||||
{
|
||||
var mod = modules[_module];
|
||||
mods[_module] = mod.code.call(this, null, _for);
|
||||
}
|
||||
|
||||
return mods[_module];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
|
||||
/**
|
||||
* The "constant" function can be used to update a constant in all
|
||||
* egw instances.
|
||||
*
|
||||
* @param _module is the module for which the constant should be set
|
||||
* @param _name is the name of the constant
|
||||
* @param _value is the value to which it should be set
|
||||
* @param _window if set, updating the constant is restricted to
|
||||
* those api instances which belong to the given window, if _window
|
||||
* evaluates to false, all instances will be updated.
|
||||
*/
|
||||
constant: function(_module, _name, _value, _window) {
|
||||
// Update the module instances first
|
||||
for (var i = 0; i < moduleInstances.wnd.length; i++)
|
||||
{
|
||||
if (!_window || _window === moduleInstances.wnd[i].window)
|
||||
{
|
||||
moduleInstances.wnd[i].modules[_module][_name] = _value;
|
||||
}
|
||||
}
|
||||
|
||||
// Now update all already instanciated instances
|
||||
for (var key in instances)
|
||||
{
|
||||
for (var i = 0; i < instances[key].length; i++)
|
||||
{
|
||||
if (!_window || _window === instances[key][i].window)
|
||||
{
|
||||
instances[key][i].instance[_name] = _value;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
dumpModules: function() {
|
||||
return modules;
|
||||
},
|
||||
@ -557,6 +677,9 @@
|
||||
// Merge the globalEgw functions into the egw object.
|
||||
mergeObjects(egw, globalEgw);
|
||||
|
||||
// Merge the preferences into the egw object.
|
||||
mergeObjects(egw, prefs);
|
||||
|
||||
// Create the entry for the root window in the module instances
|
||||
moduleInstances.wnd.push({
|
||||
'window': window,
|
||||
|
@ -68,3 +68,4 @@ egw.extend('debug', egw.MODULE_GLOBAL, function(_app, _wnd) {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -13,12 +13,14 @@
|
||||
"use strict";
|
||||
|
||||
/*egw:uses
|
||||
jquery.jquery; // Used for traversing the DOM
|
||||
egw_core;
|
||||
egw_ready;
|
||||
egw_debug;
|
||||
*/
|
||||
|
||||
egw.extend('files', egw.MODULE_WND_LOCAL, function() {
|
||||
egw.extend('files', egw.MODULE_WND_LOCAL, function(_app, _wnd) {
|
||||
|
||||
var egw = this;
|
||||
|
||||
/**
|
||||
* Array which contains all currently bound in javascript and css files.
|
||||
@ -31,21 +33,30 @@ egw.extend('files', egw.MODULE_WND_LOCAL, function() {
|
||||
* TODO: Currently this can only contain the JS files present in the main
|
||||
* window.
|
||||
*/
|
||||
$j(document).ready(function() {
|
||||
$j("script, link").each(function() {
|
||||
var elem = $j(this);
|
||||
this.module('ready', _wnd).ready(function() {
|
||||
// Iterate over the script tags
|
||||
var scripts = _wnd.document.getElementsByTagName('script');
|
||||
for (var i = 0; i < scripts.length; i++)
|
||||
{
|
||||
var src = scripts[i].getAttribute('src');
|
||||
|
||||
if (elem.attr("src"))
|
||||
if (src)
|
||||
{
|
||||
files[elem.attr("src")] = true;
|
||||
files[src] = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (elem.attr("href"))
|
||||
// Iterate over the link tags
|
||||
var links = _wnd.document.getElementsByTagName('link');
|
||||
for (var i = 0; i < links.length; i++)
|
||||
{
|
||||
var src = links[i].getAttribute('href');
|
||||
|
||||
if (src)
|
||||
{
|
||||
files[elem.attr("href")] = true;
|
||||
files[src] = true;
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
function includeJSFile(_jsFile, _callback, _context)
|
||||
@ -55,14 +66,14 @@ egw.extend('files', egw.MODULE_WND_LOCAL, function() {
|
||||
if (typeof files[_jsFile] === 'undefined')
|
||||
{
|
||||
// Create the script node which contains the new file
|
||||
var scriptnode = document.createElement('script');
|
||||
var scriptnode = _wnd.document.createElement('script');
|
||||
scriptnode.type = "text/javascript";
|
||||
scriptnode.src = _jsFile;
|
||||
scriptnode._originalSrc = _jsFile;
|
||||
|
||||
// Setup the 'onload' handler for FF, Opera, Chrome
|
||||
scriptnode.onload = function(e) {
|
||||
this.debug('info', 'Retrieved JS file "%s" from server', _jsFile);
|
||||
egw.debug('info', 'Retrieved JS file "%s" from server', _jsFile);
|
||||
_callback.call(_context, _jsFile);
|
||||
};
|
||||
|
||||
@ -73,10 +84,10 @@ egw.extend('files', egw.MODULE_WND_LOCAL, function() {
|
||||
scriptnode.readyState != 'loaded')
|
||||
{
|
||||
scriptnode.onreadystatechange = function() {
|
||||
var node = window.event.srcElement;
|
||||
var node = _wnd.event.srcElement;
|
||||
if (node.readyState == 'complete' || node.readyState == 'loaded')
|
||||
{
|
||||
this.debug('info', 'Retrieved JS file "%s" from server', _jsFile);
|
||||
egw.debug('info', 'Retrieved JS file "%s" from server', _jsFile);
|
||||
_callback.call(_context, _jsFile);
|
||||
}
|
||||
};
|
||||
@ -88,17 +99,17 @@ egw.extend('files', egw.MODULE_WND_LOCAL, function() {
|
||||
}
|
||||
|
||||
// Append the newly create script node to the head
|
||||
var head = document.getElementsByTagName('head')[0];
|
||||
var head = _wnd.document.getElementsByTagName('head')[0];
|
||||
head.appendChild(scriptnode);
|
||||
|
||||
// Request the given javascript file
|
||||
this.debug('info', 'Requested JS file "%s" from server', _jsFile);
|
||||
egw.debug('info', 'Requested JS file "%s" from server', _jsFile);
|
||||
}
|
||||
|
||||
// If the file is already loaded, call the callback
|
||||
if (alreadyLoaded)
|
||||
{
|
||||
window.setTimeout(
|
||||
_wnd.setTimeout(
|
||||
function() {
|
||||
_callback.call(_context, _jsFile);
|
||||
}, 0);
|
||||
@ -135,14 +146,14 @@ egw.extend('files', egw.MODULE_WND_LOCAL, function() {
|
||||
files[_cssFile] = true;
|
||||
|
||||
// Create the node which is used to include the css fiel
|
||||
var cssnode = document.createElement('link');
|
||||
var cssnode = _wnd.document.createElement('link');
|
||||
cssnode.type = "text/css";
|
||||
cssnode.rel = "stylesheet";
|
||||
cssnode.href = _cssFile;
|
||||
|
||||
// Get the head node and append the newly created "link" node
|
||||
// to it.
|
||||
var head = document.getElementsByTagName('head')[0];
|
||||
var head = _wnd.document.getElementsByTagName('head')[0];
|
||||
head.appendChild(cssnode);
|
||||
}
|
||||
}
|
||||
|
45
phpgwapi/js/jsapi/egw_jquery.js
Normal file
45
phpgwapi/js/jsapi/egw_jquery.js
Normal file
@ -0,0 +1,45 @@
|
||||
/**
|
||||
* EGroupware clientside API object
|
||||
*
|
||||
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||
* @package etemplate
|
||||
* @subpackage api
|
||||
* @link http://www.egroupware.org
|
||||
* @author Andreas Stöckel (as AT stylite.de)
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
"use strict"
|
||||
|
||||
/*egw:uses
|
||||
egw_core;
|
||||
egw_files;
|
||||
egw_ready;
|
||||
*/
|
||||
|
||||
egw.extend('jquery', egw.MODULE_WND_LOCAL, function(_app, _wnd) {
|
||||
|
||||
// Get the reference to the "files" and the "ready" module for the current
|
||||
// window
|
||||
var files = this.module('files', _wnd);
|
||||
var ready = this.module('ready', _wnd);
|
||||
|
||||
// Include the jQuery and jQuery UI library.
|
||||
var token = ready.readyWaitFor();
|
||||
files.includeJS([
|
||||
this.webserverUrl + '/phpgwapi/js/jquery/jquery.js',
|
||||
this.webserverUrl + '/phpgwapi/js/jquery/jquery-ui.js',
|
||||
this.webserverUrl + '/phpgwapi/js/jquery/jquery.html5_upload.js'
|
||||
], function () {
|
||||
this.constant('jquery', '$j', _wnd.$j, _wnd);
|
||||
ready.readyDone(token);
|
||||
}, this);
|
||||
|
||||
return {
|
||||
'$j': null
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
217
phpgwapi/js/jsapi/egw_ready.js
Normal file
217
phpgwapi/js/jsapi/egw_ready.js
Normal file
@ -0,0 +1,217 @@
|
||||
/**
|
||||
* EGroupware clientside API object
|
||||
*
|
||||
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||
* @package etemplate
|
||||
* @subpackage api
|
||||
* @link http://www.egroupware.org
|
||||
* @author Andreas Stöckel (as AT stylite.de)
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
"use strict"
|
||||
|
||||
/*egw:uses
|
||||
egw_core;
|
||||
egw_utils;
|
||||
egw_debug;
|
||||
*/
|
||||
|
||||
egw.extend('ready', egw.MODULE_WND_LOCAL, function(_app, _wnd) {
|
||||
|
||||
var egw = this;
|
||||
|
||||
var registeredCallbacks = [];
|
||||
var registeredProgress = [];
|
||||
var readyPending = {'readyEvent': true};
|
||||
var readyPendingCnt = 1;
|
||||
var readyDoneCnt = 0;
|
||||
var isReady = false;
|
||||
|
||||
function doReadyWaitFor() {
|
||||
if (!isReady)
|
||||
{
|
||||
var uid = egw.uid();
|
||||
readyPending[uid] = true;
|
||||
readyPendingCnt++;
|
||||
|
||||
readyProgressChange();
|
||||
|
||||
return uid;
|
||||
}
|
||||
|
||||
this.debug('warning', 'ready has already been called!');
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function doReadyDone(_token) {
|
||||
if (typeof readyPending[_token] !== 'undefined')
|
||||
{
|
||||
delete readyPending[_token];
|
||||
readyPendingCnt--;
|
||||
readyDoneCnt++;
|
||||
|
||||
readyProgressChange();
|
||||
|
||||
testCallReady();
|
||||
}
|
||||
}
|
||||
|
||||
function readyProgressChange()
|
||||
{
|
||||
// Call all registered progress callbacks
|
||||
for (var i = 0; i < registeredProgress.length; i++)
|
||||
{
|
||||
registeredProgress[i].callback.call(
|
||||
registeredProgress[i].context,
|
||||
readyDoneCnt,
|
||||
readyPendingCnt
|
||||
);
|
||||
}
|
||||
|
||||
egw.debug('log', 'Ready events, processed %s/%s', readyDoneCnt,
|
||||
readyPendingCnt + readyDoneCnt);
|
||||
}
|
||||
|
||||
function readyEventHandler() {
|
||||
doReadyDone('readyEvent');
|
||||
}
|
||||
|
||||
function testCallReady()
|
||||
{
|
||||
// Check whether no further event is pending
|
||||
if (readyPendingCnt <= 1 && !isReady)
|
||||
{
|
||||
// If exactly one event is pending and that one is not the ready
|
||||
// event, abort
|
||||
if (readyPendingCnt === 1 && !readyPending['readyEvent'])
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Set "isReady" to true, if readyPendingCnt is zero
|
||||
var isReady = readyPendingCnt === 0;
|
||||
|
||||
// Call all registered callbacks
|
||||
for (var i = registeredCallbacks.length - 1; i >= 0; i--)
|
||||
{
|
||||
if (registeredCallbacks[i].before || readyPendingCnt === 0)
|
||||
{
|
||||
registeredCallbacks[i].callback.call(
|
||||
registeredCallbacks[i].context
|
||||
);
|
||||
|
||||
// Delete the callback from the list
|
||||
registeredCallbacks.splice(i, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Register the event handler for "ready" (code adapted from jQuery)
|
||||
|
||||
// Mozilla, Opera and webkit nightlies currently support this event
|
||||
if (_wnd.document.addEventListener) {
|
||||
// Use the handy event callback
|
||||
_wnd.document.addEventListener("DOMContentLoaded", readyEventHandler, false);
|
||||
|
||||
// A fallback to window.onload, that will always work
|
||||
_wnd.addEventListener("load", readyEventHandler, false);
|
||||
|
||||
// If IE event model is used
|
||||
} else if (_wnd.document.attachEvent) {
|
||||
// ensure firing before onload,
|
||||
// maybe late but safe also for iframes
|
||||
_wnd.document.attachEvent("onreadystatechange", readyEventHandler);
|
||||
|
||||
// A fallback to window.onload, that will always work
|
||||
_wnd.attachEvent("onload", readyEventHandler);
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
/**
|
||||
* The readyWaitFor function can be used to register an event, that has
|
||||
* to be marked as "done" before the ready function will call its
|
||||
* registered callbacks. The function returns an id that has to be
|
||||
* passed to the "readDone" function once
|
||||
*/
|
||||
readyWaitFor: function() {
|
||||
return doReadyWaitFor();
|
||||
},
|
||||
|
||||
/**
|
||||
* The readyDone function can be used to mark a event token as
|
||||
* previously requested by "readyWaitFor" as done.
|
||||
*
|
||||
* @param _token is the token which has now been processed.
|
||||
*/
|
||||
readyDone: function(_token) {
|
||||
doReadyDone(_token);
|
||||
},
|
||||
|
||||
/**
|
||||
* The ready function can be used to register a function that will be
|
||||
* called, when the window is completely loaded. All ready handlers will
|
||||
* be called exactly once. If the ready handler has already been called,
|
||||
* the given function will be called defered using setTimeout.
|
||||
*
|
||||
* @param _callback is the function which will be called when the page
|
||||
* is ready. No parameters will be passed.
|
||||
* @param _context is the context in which the callback function should
|
||||
* get called.
|
||||
* @param _beforeDOMContentLoaded specifies, whether the callback should
|
||||
* get called, before the DOMContentLoaded event has been fired.
|
||||
*/
|
||||
ready: function(_callback, _context, _beforeDOMContentLoaded) {
|
||||
if (!isReady)
|
||||
{
|
||||
registeredCallbacks.push({
|
||||
'callback': _callback,
|
||||
'context': _context ? _context : null,
|
||||
'before': _beforeDOMContentLoaded ? true : false
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
setTimeout(function() {
|
||||
_callback.call(_context)
|
||||
}, 1);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* The readyProgress function can be used to register a function that
|
||||
* will be called whenever a ready event is done or registered.
|
||||
*
|
||||
* @param _callback is the function which will be called when the
|
||||
* progress changes.
|
||||
* @param _context is the context in which the callback function which
|
||||
* should get called.
|
||||
*/
|
||||
readyProgress: function(_callback, _context) {
|
||||
if (!isReady)
|
||||
{
|
||||
registeredProgress.unshift({
|
||||
'callback': _callback,
|
||||
'context': _context ? _context : null
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
this.debug('warning', 'ready has already been called!');
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns whether the ready events have already been called.
|
||||
*/
|
||||
isReady: function() {
|
||||
return isReady;
|
||||
}
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user