2010-06-09 20:36:14 +02:00
|
|
|
/**
|
|
|
|
* eGroupware JavaScript Framework
|
|
|
|
*
|
|
|
|
* @link http://www.egroupware.org
|
|
|
|
* @author Andreas Stoeckel <as@stylite.de>
|
|
|
|
* @version $Id$
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
2010-06-21 11:08:41 +02:00
|
|
|
/**
|
|
|
|
* Some constant definitions
|
|
|
|
*/
|
|
|
|
|
|
|
|
EGW_LINK_SOURCE_FRAMEWORK = 0;
|
|
|
|
EGW_LINK_SOURCE_LEGACY_IFRAME = 1;
|
|
|
|
EGW_LINK_SOURCE_POPUP = 2;
|
|
|
|
|
2010-06-09 20:36:14 +02:00
|
|
|
/**
|
|
|
|
* Class: egw_fw
|
|
|
|
* The egw_fw class is the base framework class. It wraps around all egw_fw_ui and
|
|
|
|
* egw_fw_classes. It creates both, a side bar and a tab area and cares about linking.
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The constructor of the egw_fw class.
|
|
|
|
*
|
|
|
|
* @param string _sidemenuId specifies the name of the div container which should contain the sidebar menu
|
|
|
|
* @param string _tabsId specifies the name of the div container which should cotain the tab area
|
|
|
|
* @param string _webserverUrl specifies the egroupware root url
|
|
|
|
*/
|
2010-06-16 16:57:04 +02:00
|
|
|
function egw_fw(_sidemenuId, _tabsId, _splitterId, _webserverUrl, _sideboxSizeCallback,
|
|
|
|
_sideboxStartSize)
|
2010-06-09 20:36:14 +02:00
|
|
|
{
|
|
|
|
/* Get the base div */
|
|
|
|
this.sidemenuDiv = document.getElementById(_sidemenuId);
|
|
|
|
this.tabsDiv = document.getElementById(_tabsId);
|
2010-06-16 16:57:04 +02:00
|
|
|
this.splitterDiv = document.getElementById(_splitterId);
|
2010-06-09 20:36:14 +02:00
|
|
|
this.webserverUrl = _webserverUrl;
|
2010-06-16 16:57:04 +02:00
|
|
|
this.sideboxSizeCallback = _sideboxSizeCallback;
|
2010-06-09 20:36:14 +02:00
|
|
|
window.egw_webserverUrl = _webserverUrl;
|
|
|
|
|
|
|
|
this.sidemenuUi = null;
|
|
|
|
this.tabsUi = null;
|
|
|
|
|
|
|
|
this.categoryOpenCache = new Object();
|
|
|
|
|
|
|
|
this.applications = new Object();
|
|
|
|
this.activeApp = null;
|
|
|
|
|
2010-06-16 16:57:04 +02:00
|
|
|
if (this.sidemenuDiv && this.tabsDiv && this.splitterDiv)
|
2010-06-09 20:36:14 +02:00
|
|
|
{
|
2010-06-16 16:57:04 +02:00
|
|
|
//Wrap a scroll area handler around the applications
|
|
|
|
this.scrollAreaUi = new egw_fw_ui_scrollarea(this.sidemenuDiv);
|
|
|
|
|
|
|
|
//Create the sidemenu, the tabs area and the splitter
|
|
|
|
this.sidemenuUi = new egw_fw_ui_sidemenu(this.scrollAreaUi.contentDiv,
|
|
|
|
this.sortCallback);
|
2010-06-09 20:36:14 +02:00
|
|
|
this.tabsUi = new egw_fw_ui_tabs(this.tabsDiv);
|
2010-06-16 16:57:04 +02:00
|
|
|
this.splitterUi = new egw_fw_ui_splitter(this.splitterDiv,
|
|
|
|
EGW_SPLITTER_VERTICAL, this.splitterResize,
|
|
|
|
[
|
|
|
|
{
|
|
|
|
"size": _sideboxStartSize,
|
|
|
|
"minsize": 225,
|
|
|
|
"maxsize": 0
|
|
|
|
},
|
|
|
|
], this);
|
|
|
|
|
2010-06-09 20:36:14 +02:00
|
|
|
|
|
|
|
this.loadApplications("home.jdots_framework.ajax_navbar_apps");
|
|
|
|
}
|
|
|
|
|
2010-06-16 16:57:04 +02:00
|
|
|
_sideboxSizeCallback(_sideboxStartSize);
|
|
|
|
|
2010-06-09 20:36:14 +02:00
|
|
|
//Register the resize handler
|
|
|
|
$(window).resize(function(){window.framework.resizeHandler()});
|
|
|
|
|
|
|
|
//Register the global alert handler
|
|
|
|
window.egw_alertHandler = this.alertHandler;
|
|
|
|
|
|
|
|
//Register the key press handler
|
2010-06-09 23:24:37 +02:00
|
|
|
//$(document).keypress(this.keyPressHandler);
|
2010-06-09 20:36:14 +02:00
|
|
|
|
|
|
|
//Override the old egw_openWindowCentered2
|
|
|
|
window.egw_openWindowCentered2 = this.egw_openWindowCentered2;
|
|
|
|
|
|
|
|
//Override the app_window function
|
|
|
|
window.egw_appWindow = this.egw_appWindow;
|
|
|
|
}
|
|
|
|
|
|
|
|
egw_fw.prototype.alertHandler = function(_message, _details)
|
|
|
|
{
|
|
|
|
alert('Error:\n ' + _message + '\n\nDetails:\n ' + _details);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Function called whenever F1 is pressed inside the framework
|
|
|
|
* @returns boolean true if the call manual function could be called, false if the manual is not available
|
|
|
|
*/
|
|
|
|
egw_fw.prototype.f1Handler = function()
|
|
|
|
{
|
|
|
|
if (typeof window.callManual != 'undefined')
|
|
|
|
{
|
|
|
|
window.callManual();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Function called whenever a key is pressed
|
|
|
|
* @param object event describes the key press event
|
|
|
|
*/
|
|
|
|
egw_fw.prototype.keyPressHandler = function(event)
|
|
|
|
{
|
|
|
|
switch (event.keyCode)
|
|
|
|
{
|
|
|
|
case 112: //F1
|
|
|
|
{
|
|
|
|
event.preventDefault();
|
|
|
|
framework.f1Handler();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-06-16 16:57:04 +02:00
|
|
|
/**
|
|
|
|
* Sets the active framework application to the application specified by _app
|
|
|
|
*/
|
|
|
|
egw_fw.prototype.setActiveApp = function(_app)
|
|
|
|
{
|
|
|
|
//Only perform the following commands if a new application is activated
|
|
|
|
if (_app != this.activeApp)
|
|
|
|
{
|
|
|
|
this.activeApp = _app;
|
|
|
|
|
|
|
|
//Set the sidebox width if a application specific sidebox width is set
|
|
|
|
if (_app.sideboxWidth !== false)
|
|
|
|
{
|
|
|
|
this.sideboxSizeCallback(_app.sideboxWidth);
|
|
|
|
this.splitterUi.constraints[0].size = _app.sideboxWidth;
|
|
|
|
}
|
|
|
|
|
|
|
|
//Open the sidemenuUi that belongs to the app, if no sidemenu is attached
|
|
|
|
//to the app, close the sidemenuUi
|
|
|
|
if (_app.sidemenuEntry)
|
|
|
|
{
|
|
|
|
if (_app.hasSideboxMenuContent)
|
|
|
|
{
|
|
|
|
this.sidemenuUi.open(_app.sidemenuEntry);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
this.sidemenuUi.open(null);
|
|
|
|
}
|
|
|
|
|
|
|
|
//Set the website title
|
|
|
|
if (_app.website_title)
|
|
|
|
{
|
|
|
|
document.title = _app.website_title;
|
|
|
|
}
|
|
|
|
|
|
|
|
//Show the application tab
|
|
|
|
if (_app.tab)
|
|
|
|
{
|
|
|
|
this.tabsUi.showTab(_app.tab);
|
|
|
|
}
|
|
|
|
|
|
|
|
//Resize the scroll area...
|
|
|
|
this.scrollAreaUi.update();
|
|
|
|
|
|
|
|
//...and scroll to the top
|
|
|
|
this.scrollAreaUi.setScrollPos(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Function called whenever the sidemenu entries are sorted
|
|
|
|
*/
|
|
|
|
egw_fw.prototype.sortCallback = function(_entriesArray)
|
|
|
|
{
|
|
|
|
//Create an array with the names of the applications in their sort order
|
|
|
|
var name_array = new Array();
|
|
|
|
for (var i = 0; i < _entriesArray.length; i++)
|
|
|
|
{
|
|
|
|
name_array.push(_entriesArray[i].tag.appName);
|
|
|
|
}
|
|
|
|
|
|
|
|
//Send the sort order to the server via ajax
|
|
|
|
var req = new egw_json_request('home.jdots_framework.ajax_appsort',
|
|
|
|
[name_array]);
|
|
|
|
req.sendRequest(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Function called whenever the sidebox is resized
|
|
|
|
*/
|
|
|
|
egw_fw.prototype.splitterResize = function(_width)
|
|
|
|
{
|
|
|
|
if (this.tag.activeApp)
|
|
|
|
{
|
|
|
|
app_name = this.tag.activeApp.appName;
|
|
|
|
var req = new egw_json_request(app_name + '.jdots_framework.ajax_sideboxwidth',
|
|
|
|
[app_name, _width]);
|
|
|
|
req.sendRequest(true);
|
|
|
|
|
|
|
|
//If there are no global application width values, set the sidebox width of
|
|
|
|
//the application every time the splitter is resized
|
|
|
|
if (this.tag.activeApp.sideboxWidth !== false)
|
|
|
|
{
|
|
|
|
this.tag.activeApp.sideboxWidth = _width;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
this.tag.sideboxSizeCallback(_width);
|
|
|
|
}
|
|
|
|
|
2010-06-09 20:36:14 +02:00
|
|
|
/**
|
|
|
|
* tabCloseClickCallback is used internally by egw_fw in order to handle clicks
|
|
|
|
* on the close button of every tab.
|
|
|
|
*
|
|
|
|
* @param egw_fw_ui_tab _sender specifies the tab ui object, the user has clicked
|
|
|
|
*/
|
|
|
|
egw_fw.prototype.tabCloseClickCallback = function(_sender)
|
|
|
|
{
|
|
|
|
//Save references to the application and the tabsUi as "this" will be deleted
|
|
|
|
var app = this.tag;
|
|
|
|
var tabsUi = this.parent;
|
|
|
|
|
|
|
|
//At least one tab must stay open
|
|
|
|
if (tabsUi.tabs.length > 1)
|
|
|
|
{
|
|
|
|
tabsUi.removeTab(this);
|
|
|
|
app.tab = null;
|
2010-06-21 11:08:41 +02:00
|
|
|
app.browser = null;
|
|
|
|
|
|
|
|
if (app.sidemenuEntry)
|
|
|
|
app.sidemenuEntry.hideAjaxLoader();
|
2010-06-09 20:36:14 +02:00
|
|
|
|
2010-06-16 16:57:04 +02:00
|
|
|
//Set the active application to the application of the currently active tab
|
|
|
|
app.parentFw.setActiveApp(tabsUi.activeTab.tag);
|
2010-06-09 20:36:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
tabsUi.setCloseable(tabsUi.tabs.length > 1);
|
|
|
|
|
2010-06-21 11:08:41 +02:00
|
|
|
//As a new tab might remove a row from the tab header, we have to resize all tab content browsers
|
2010-06-09 20:36:14 +02:00
|
|
|
this.tag.parentFw.resizeHandler();
|
|
|
|
}
|
|
|
|
|
|
|
|
egw_fw.prototype.resizeHandler = function()
|
|
|
|
{
|
2010-06-21 11:08:41 +02:00
|
|
|
//Resize the browser area of the applications
|
2010-06-09 20:36:14 +02:00
|
|
|
for (var app in this.applications)
|
|
|
|
{
|
2010-06-21 11:08:41 +02:00
|
|
|
if (this.applications[app].browser != null)
|
2010-06-09 20:36:14 +02:00
|
|
|
{
|
2010-06-21 11:08:41 +02:00
|
|
|
this.applications[app].browser.resize();
|
2010-06-09 20:36:14 +02:00
|
|
|
}
|
|
|
|
}
|
2010-06-21 11:08:41 +02:00
|
|
|
|
|
|
|
//Update the scroll area
|
|
|
|
this.scrollAreaUi.update();
|
2010-06-09 20:36:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
egw_fw.prototype.getIFrameHeight = function()
|
|
|
|
{
|
|
|
|
var height = $(window).height() - (this.tabsUi.contHeaderDiv.offsetTop +
|
|
|
|
this.tabsUi.contHeaderDiv.offsetHeight + 30); /* 30 is the height of the footer */
|
|
|
|
return height;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* tabClickCallback is used internally by egw_fw in order to handle clicks on
|
|
|
|
* a tab.
|
|
|
|
*
|
|
|
|
* @param egw_fw_ui_tab _sender specifies the tab ui object, the user has clicked
|
|
|
|
*/
|
|
|
|
egw_fw.prototype.tabClickCallback = function(_sender)
|
|
|
|
{
|
2010-06-16 16:57:04 +02:00
|
|
|
//Set the active application in the framework
|
|
|
|
this.tag.parentFw.setActiveApp(this.tag);
|
2010-06-09 20:36:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* applicationClickCallback is used internally by egw_fw in order to handle clicks on
|
|
|
|
* an application in the sidebox menu.
|
|
|
|
*
|
|
|
|
* @param egw_fw_ui_tab _sender specifies the tab ui object, the user has clicked
|
|
|
|
*/
|
|
|
|
egw_fw.prototype.applicationClickCallback = function(_sender)
|
|
|
|
{
|
2010-06-21 11:08:41 +02:00
|
|
|
this.tag.parentFw.applicationTabNavigate(this.tag, this.tag.indexUrl);
|
2010-06-09 20:36:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2010-06-21 11:08:41 +02:00
|
|
|
* Checks whether the application already owns a tab and creates one if it doesn't exist
|
2010-06-09 20:36:14 +02:00
|
|
|
*/
|
2010-06-21 11:08:41 +02:00
|
|
|
egw_fw.prototype.createApplicationTab = function(_app)
|
2010-06-09 20:36:14 +02:00
|
|
|
{
|
2010-06-21 11:08:41 +02:00
|
|
|
if (_app.tab == null)
|
2010-06-09 20:36:14 +02:00
|
|
|
{
|
2010-06-21 11:08:41 +02:00
|
|
|
//Create the tab
|
2010-06-09 20:36:14 +02:00
|
|
|
_app.tab = this.tabsUi.addTab(_app.icon, this.tabClickCallback, this.tabCloseClickCallback,
|
|
|
|
_app);
|
|
|
|
_app.tab.setTitle(_app.displayName);
|
|
|
|
|
2010-06-21 11:08:41 +02:00
|
|
|
//Set the tab closeable if there's more than one tab
|
2010-06-09 20:36:14 +02:00
|
|
|
this.tabsUi.setCloseable(this.tabsUi.tabs.length > 1);
|
2010-06-21 11:08:41 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Navigate to the tab of an application (opening the tab if not yet open)
|
|
|
|
*
|
|
|
|
* @param egw_fw_class_application _app
|
|
|
|
* @param string _url optional url, default index page of app
|
|
|
|
*/
|
|
|
|
egw_fw.prototype.applicationTabNavigate = function(_app, _url, _useIframe)
|
|
|
|
{
|
|
|
|
//Create the tab for that application
|
|
|
|
this.createApplicationTab(_app);
|
|
|
|
|
|
|
|
if (typeof _url == 'undefined')
|
|
|
|
_url = _app.indexUrl;
|
|
|
|
|
|
|
|
if (typeof _useIframe == 'undefined')
|
|
|
|
{
|
|
|
|
if (!_url.match(/menuaction=/))
|
|
|
|
{
|
|
|
|
_useIframe = true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
_useIframe = _app.legacyApp;
|
|
|
|
}
|
|
|
|
}
|
2010-06-09 20:36:14 +02:00
|
|
|
|
2010-06-21 11:08:41 +02:00
|
|
|
if (_app.browser == null)
|
|
|
|
{
|
|
|
|
//Create a new browser ui and set it as application tab callback
|
|
|
|
var callback = new egw_fw_class_callback(this, this.getIFrameHeight);
|
|
|
|
_app.browser = new egw_fw_content_browser(_app, callback);
|
|
|
|
_app.tab.setContent(_app.browser.baseDiv);
|
2010-06-09 20:36:14 +02:00
|
|
|
}
|
|
|
|
|
2010-06-21 11:08:41 +02:00
|
|
|
_app.browser.browse(_url, true);//_useIframe);
|
2010-06-09 20:36:14 +02:00
|
|
|
|
2010-06-21 11:08:41 +02:00
|
|
|
this.setActiveApp(_app);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Tries to obtain the application from a menuaction
|
|
|
|
*/
|
|
|
|
egw_fw.prototype.parseAppFromUrl = function(_url)
|
|
|
|
{
|
|
|
|
var _app = null;
|
|
|
|
|
|
|
|
//Read the menuaction parts from the url and check whether the first part
|
|
|
|
//of the url contains a valid app name
|
|
|
|
var matches = _url.match(/menuaction=([a-z0-9_-]+)\./i);
|
|
|
|
if (matches && (_app = this.getApplicationByName(matches[1])))
|
|
|
|
{
|
|
|
|
return _app;
|
|
|
|
}
|
|
|
|
|
|
|
|
//Check the url for a scheme of "/app/something.php" and check this one for a valid app
|
|
|
|
//name
|
|
|
|
var matches = _url.match(/\/([^\/]+)\/[^\/]+\.php/i);
|
|
|
|
if (matches && (_app = this.getApplicationByName(matches[1])))
|
|
|
|
{
|
|
|
|
return _app;
|
|
|
|
}
|
|
|
|
return null;
|
2010-06-09 20:36:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* loadApplicationsCallback is internally used by egw_fw in order to handle the
|
|
|
|
* receiving of the application list.
|
|
|
|
*
|
|
|
|
* @param object apps contains the parsed JSON data describing the applications.
|
|
|
|
* The JSON object should have the following structure
|
|
|
|
* apps = array[
|
|
|
|
* {
|
|
|
|
* string name (the internal name of the application)
|
|
|
|
* string title (the name of the application how it should be viewed)
|
|
|
|
* string icon (path to the icon of the application)
|
|
|
|
* string url (path to the application) //TODO: Change this
|
|
|
|
* [boolean isDefault] (whether this entry is the default entry which should be opened)
|
|
|
|
* }
|
|
|
|
* ]
|
|
|
|
*/
|
|
|
|
egw_fw.prototype.loadApplicationsCallback = function(apps)
|
|
|
|
{
|
|
|
|
var defaultApp = null;
|
|
|
|
|
|
|
|
//Iterate through the application array returned
|
|
|
|
for (var i = 0; i < apps.length; i++)
|
|
|
|
{
|
|
|
|
var app = apps[i];
|
|
|
|
|
2010-06-21 11:08:41 +02:00
|
|
|
//Check for the "legacyApp" flag - if it is not set, default it to true
|
|
|
|
var legacyApp = true;
|
|
|
|
if (typeof app.legacyApp != 'undefined')
|
|
|
|
legacyApp = app.legacyApp;
|
|
|
|
|
2010-06-09 20:36:14 +02:00
|
|
|
appData = new egw_fw_class_application(this,
|
2010-06-21 11:08:41 +02:00
|
|
|
app.name, app.title, app.icon, app.url, app.sideboxwidth, legacyApp);
|
2010-06-09 20:36:14 +02:00
|
|
|
|
|
|
|
//Create a sidebox menu entry for each application
|
|
|
|
if (!app.noNavbar)
|
|
|
|
{
|
|
|
|
appData.sidemenuEntry = this.sidemenuUi.addEntry(
|
|
|
|
appData.displayName, appData.icon,
|
|
|
|
this.applicationClickCallback, appData);
|
|
|
|
}
|
|
|
|
|
|
|
|
//If this entry is the default entry, show it using the click callback
|
|
|
|
if (app.isDefault && (app.isDefault === true))
|
|
|
|
{
|
|
|
|
defaultApp = appData;
|
|
|
|
}
|
|
|
|
|
|
|
|
this.applications[appData.appName] = appData;
|
|
|
|
}
|
|
|
|
|
|
|
|
// check if a menuaction or app is specified in the url --> display that
|
2010-06-21 11:08:41 +02:00
|
|
|
var _app = this.parseAppFromUrl(window.location.href);
|
|
|
|
if (_app)
|
2010-06-09 20:36:14 +02:00
|
|
|
{
|
|
|
|
_url = window.location.href.replace(/&?cd=yes/,'');
|
2010-06-21 11:08:41 +02:00
|
|
|
this.applicationTabNavigate(_app, _url);
|
2010-06-09 20:36:14 +02:00
|
|
|
}
|
|
|
|
// else display the default application
|
|
|
|
else if (defaultApp)
|
|
|
|
{
|
|
|
|
this.applicationTabNavigate(defaultApp);
|
|
|
|
}
|
2010-06-16 16:57:04 +02:00
|
|
|
|
|
|
|
this.scrollAreaUi.update();
|
2010-06-09 20:36:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* loadApplications refreshes the list of applications. Upon calling, all existing applications
|
|
|
|
* will be deleted from the list, and all open tabs will be closed. Then an AJAX request to the
|
|
|
|
* given URL will be send in order to obtain the application list with JSON encoding.
|
|
|
|
*
|
|
|
|
* @param string _menuaction specifies the menuaction
|
|
|
|
*/
|
|
|
|
egw_fw.prototype.loadApplications = function(_menuaction)
|
|
|
|
{
|
|
|
|
//Close all open tabs, remove all applications from the application list
|
|
|
|
this.sidemenuUi.clean();
|
|
|
|
this.tabsUi.clean();
|
|
|
|
|
|
|
|
//Perform an AJAX request loading all available applications
|
|
|
|
var req = new egw_json_request(_menuaction)
|
|
|
|
req.sendRequest(true, this.loadApplicationsCallback, this);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Goes through all applications and returns the application with the specified name.
|
|
|
|
* @param string _name the name of the application which should be returned.
|
|
|
|
* @return object or null if application is not found.
|
|
|
|
*/
|
|
|
|
egw_fw.prototype.getApplicationByName = function(_name)
|
|
|
|
{
|
|
|
|
if (typeof this.applications[_name] != 'undefined')
|
|
|
|
{
|
2010-06-21 11:08:41 +02:00
|
|
|
return this.applications[_name];
|
2010-06-09 20:36:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Seperates all script tags from the given html code and returns the seperately
|
|
|
|
* @param object _html object that the html code from which the script should be seperated. The html code has to be stored in _html.html, the result js will be written to _html.js
|
|
|
|
*/
|
|
|
|
|
|
|
|
egw_fw.prototype.seperateJavaScript = function(_html)
|
|
|
|
{
|
|
|
|
var html = _html.html;
|
|
|
|
|
|
|
|
var in_pos = html.search(/<script/im);
|
|
|
|
var out_pos = html.search(/<\/script>/im);
|
|
|
|
while (in_pos > -1 && out_pos > -1)
|
|
|
|
{
|
|
|
|
/*Seperate the whole <script...</script> tag */
|
|
|
|
var js_str = html.substring(in_pos, out_pos+9);
|
|
|
|
|
|
|
|
/*Remove the initial tag */
|
|
|
|
/*js_str = js_str.substring(js_str.search(/>/) + 1);*/
|
|
|
|
_html.js += js_str;
|
|
|
|
|
|
|
|
|
|
|
|
html = html.substring(0, in_pos - 1) + html.substring(out_pos + 9);
|
|
|
|
|
|
|
|
var in_pos = html.search(/<script/im);
|
|
|
|
var out_pos = html.search(/<\/script>/im);
|
|
|
|
}
|
|
|
|
|
|
|
|
_html.html = html;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Sends sidemenu entry category open/close information to the server using an AJAX request
|
|
|
|
*/
|
|
|
|
egw_fw.prototype.categoryOpenCloseCallback = function(_opened)
|
|
|
|
{
|
|
|
|
// switched off, 'til we start using it
|
|
|
|
//var req = new egw_json_request("home.jdots_framework.ajax_sidebox_menu_opened",
|
|
|
|
// [this.tag.appName, this.catName, _opened]);
|
|
|
|
//req.sendRequest(true);
|
|
|
|
|
|
|
|
/* Store the state of the category lokaly */
|
|
|
|
this.tag.parentFw.categoryOpenCache[this.tag.appName + '#' + this.catName] = _opened;
|
2010-06-16 16:57:04 +02:00
|
|
|
// this.tag.parentFw.scrollAreaUi.update();
|
|
|
|
}
|
|
|
|
|
|
|
|
egw_fw.prototype.categoryAnimationCallback = function()
|
|
|
|
{
|
|
|
|
this.tag.parentFw.scrollAreaUi.update();
|
2010-06-09 20:36:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Sets the sidebox data of an application
|
|
|
|
* @param object _app the application whose sidebox content should be set.
|
|
|
|
* @param object _data an array/object containing the data of the sidebox content
|
|
|
|
* @param string _md5 an md5 hash of the sidebox menu content: Only if this hash differs between two setSidebox calles, the sidebox menu will be updated.
|
|
|
|
*/
|
|
|
|
egw_fw.prototype.setSidebox = function(_app, _data, _md5)
|
|
|
|
{
|
|
|
|
if ((_app != null) && (_app.sidebox_md5 != _md5) && (_app.sidemenuEntry != null))
|
|
|
|
{
|
|
|
|
//Parse the sidebox data
|
|
|
|
if (_data != null)
|
|
|
|
{
|
|
|
|
var contDiv = document.createElement('div');
|
|
|
|
var contJS = ''; //new Array();
|
|
|
|
for (var i = 0; i < _data.length; i++)
|
|
|
|
{
|
|
|
|
var catContent = '';
|
|
|
|
for (var j = 0; j < _data[i].entries.length; j++)
|
|
|
|
{
|
|
|
|
/* As jquery executes all script tags which are found inside
|
|
|
|
the html and removes them afterwards, we have to seperate the
|
|
|
|
javaScript from the html in lang_item and add it manually. */
|
|
|
|
html = new Object();
|
|
|
|
html.html = _data[i].entries[j].lang_item;
|
|
|
|
html.js = '';
|
|
|
|
|
|
|
|
this.seperateJavaScript(html);
|
|
|
|
contJS += html.js;//contJS.concat(html.js);
|
|
|
|
|
|
|
|
if (_data[i].entries[j].icon_or_star)
|
|
|
|
{
|
|
|
|
catContent += '<div class="egw_fw_ui_sidemenu_listitem"><img class="egw_fw_ui_sidemenu_listitem_icon" src="' + _data[i].entries[j].icon_or_star + '" />';
|
|
|
|
}
|
|
|
|
if (_data[i].entries[j].item_link == '')
|
|
|
|
{
|
|
|
|
catContent += html.html;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
catContent += '<a href="' + _data[i].entries[j].item_link +
|
|
|
|
(_data[i].entries[j].target ? '" target="'+_data[i].entries[j].target : '') +
|
|
|
|
'">' + html.html + '</a>';
|
|
|
|
}
|
|
|
|
if (_data[i].entries[j].icon_or_star)
|
|
|
|
{
|
|
|
|
catContent += '</div>';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Append the category content */
|
|
|
|
if (catContent != '')
|
|
|
|
{
|
|
|
|
var categoryUi = new egw_fw_ui_category(contDiv,_data[i].menu_name,
|
2010-06-16 16:57:04 +02:00
|
|
|
_data[i].title, catContent, this.categoryOpenCloseCallback,
|
|
|
|
this.categoryAnimationCallback, _app);
|
2010-06-09 20:36:14 +02:00
|
|
|
|
|
|
|
//Lookup whether this entry was opened before. If no data is
|
|
|
|
//stored about this, use the information we got from the server
|
|
|
|
var opened = this.categoryOpenCache[
|
|
|
|
_app.appName + '#' + _data[i].menu_name];
|
|
|
|
if (typeof opened == 'undefined')
|
|
|
|
{
|
|
|
|
opened = _data[i].opened;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (opened)
|
|
|
|
{
|
|
|
|
categoryUi.open(true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
_app.sidemenuEntry.setContent(contDiv);
|
|
|
|
_app.sidebox_md5 = _md5;
|
|
|
|
|
|
|
|
$(contDiv).append(contJS);
|
|
|
|
}
|
|
|
|
|
|
|
|
_app.hasSideboxMenuContent = true;
|
|
|
|
_app.sidemenuEntry.parent.open(_app.sidemenuEntry);
|
2010-06-16 16:57:04 +02:00
|
|
|
|
|
|
|
_app.parentFw.scrollAreaUi.update();
|
|
|
|
_app.parentFw.scrollAreaUi.setScrollPos(0);
|
2010-06-09 20:36:14 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Sets the website title of an application
|
|
|
|
* @param object _app the application whose title should be set.
|
|
|
|
* @param string _title title to set
|
|
|
|
*/
|
|
|
|
egw_fw.prototype.setWebsiteTitle = function(_app,_title)
|
|
|
|
{
|
2010-06-14 16:12:31 +02:00
|
|
|
document.title = _title;
|
|
|
|
if (_app) _app.website_title = _title;
|
2010-06-09 20:36:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Change timezone and refresh current app
|
|
|
|
* @param _tz
|
|
|
|
*/
|
|
|
|
egw_fw.prototype.tzSelection = function(_tz)
|
|
|
|
{
|
|
|
|
//Perform an AJAX request to tell server
|
|
|
|
var req = new egw_json_request('home.jdots_framework.ajax_tz_selection.template',[_tz]);
|
|
|
|
req.sendRequest(false); // false = synchron
|
|
|
|
|
2010-06-21 11:08:41 +02:00
|
|
|
if (this.activeApp.browser)
|
2010-06-09 20:36:14 +02:00
|
|
|
{
|
2010-06-21 11:08:41 +02:00
|
|
|
this.activeApp.browser.relode();
|
2010-06-09 20:36:14 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-06-21 11:08:41 +02:00
|
|
|
egw_fw.prototype.linkHandler = function(_link, _app, _useIframe, _linkSource)
|
2010-06-09 20:36:14 +02:00
|
|
|
{
|
2010-06-21 11:08:41 +02:00
|
|
|
//Determine the app string from the application parameter
|
|
|
|
var app = null;
|
|
|
|
if (_app && typeof _app == 'string')
|
|
|
|
{
|
|
|
|
app = this.getApplicationByName(_app);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!app)
|
|
|
|
{
|
|
|
|
//The app parameter was false or not a string or the application specified did not exists.
|
|
|
|
//Determine the target application from the link that had been passed to this function
|
|
|
|
app = this.parseAppFromUrl(_link);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (app)
|
2010-06-09 20:36:14 +02:00
|
|
|
{
|
|
|
|
this.applicationTabNavigate(app, _link);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-06-21 11:08:41 +02:00
|
|
|
//Display some error messages to have visible feedback
|
|
|
|
if (typeof _app == 'string')
|
|
|
|
{
|
|
|
|
egw_alertHandler('Application "' + _app + '" not found.',
|
|
|
|
'The application "' + _app + '" the link "' + _link + '" points to is not registered.');
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
egw_alertHandler("No appropriate target application has been found.",
|
|
|
|
"Target link: " + _link);
|
|
|
|
}
|
2010-06-09 20:36:14 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-06-11 14:35:49 +02:00
|
|
|
egw_fw.prototype.egw_openWindowCentered2 = function(_url, _windowName, _width, _height, _status, _app, _returnID)
|
2010-06-09 20:36:14 +02:00
|
|
|
{
|
2010-06-11 14:35:49 +02:00
|
|
|
if (typeof _returnID == 'undefined') _returnID = false;
|
2010-06-09 20:36:14 +02:00
|
|
|
windowWidth = egw_getWindowOuterWidth();
|
|
|
|
windowHeight = egw_getWindowOuterHeight();
|
|
|
|
|
|
|
|
positionLeft = (windowWidth/2)-(_width/2)+egw_getWindowLeft();
|
|
|
|
positionTop = (windowHeight/2)-(_height/2)+egw_getWindowTop();
|
|
|
|
|
|
|
|
//Determine the window the popup should be opened in - normally this is the iframe of the currently active application
|
|
|
|
var parentWindow = window;
|
|
|
|
var navigate = false;
|
2010-06-11 14:35:49 +02:00
|
|
|
if (typeof _app != 'undefined' && _app !== false)
|
2010-06-09 20:36:14 +02:00
|
|
|
{
|
|
|
|
var appEntry = framework.getApplicationByName(_app);
|
2010-06-21 11:08:41 +02:00
|
|
|
if (appEntry && appEntry.browser == null)
|
2010-06-09 20:36:14 +02:00
|
|
|
{
|
|
|
|
navigate = true;
|
2010-06-21 11:08:41 +02:00
|
|
|
framework.applicationTabNavigate(appEntry, 'about:blank', appEntry.legacyApp);
|
2010-06-09 20:36:14 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
var appEntry = framework.activeApp;
|
|
|
|
}
|
|
|
|
|
2010-06-21 11:08:41 +02:00
|
|
|
if (appEntry != null && appEntry.browser.iframe != null)
|
|
|
|
parentWindow = appEntry.browser.iframe.contentWindow;
|
2010-06-09 20:36:14 +02:00
|
|
|
|
|
|
|
windowID = parentWindow.open(_url, _windowName, "width=" + _width + ",height=" + _height +
|
|
|
|
",screenX=" + positionLeft + ",left=" + positionLeft + ",screenY=" + positionTop + ",top=" + positionTop +
|
|
|
|
",location=no,menubar=no,directories=no,toolbar=no,scrollbars=yes,resizable=yes,status="+_status);
|
|
|
|
|
|
|
|
if (navigate)
|
|
|
|
{
|
2010-06-21 11:08:41 +02:00
|
|
|
window.setTimeout("framework.applicationTabNavigate(framework.activeApp, framework.activeApp.indexUrl);", 500);
|
2010-06-09 20:36:14 +02:00
|
|
|
}
|
2010-06-21 11:08:41 +02:00
|
|
|
|
2010-06-11 14:35:49 +02:00
|
|
|
if (_returnID === false)
|
|
|
|
{
|
|
|
|
// return nothing
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return windowID;
|
|
|
|
}
|
2010-06-09 20:36:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
egw_fw.prototype.egw_appWindow = function(_app)
|
|
|
|
{
|
|
|
|
var app = framework.getApplicationByName(_app);
|
|
|
|
var result = null;
|
2010-06-21 11:08:41 +02:00
|
|
|
if (app != null && app.browser != null && app.browser.iframe != null)
|
2010-06-09 20:36:14 +02:00
|
|
|
{
|
2010-06-21 11:08:41 +02:00
|
|
|
result = app.browser.iframe.contentWindow;
|
2010-06-09 20:36:14 +02:00
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2010-06-21 11:08:41 +02:00
|
|
|
/**
|
|
|
|
* egw_fw_content_browser class
|
|
|
|
*/
|
|
|
|
|
|
|
|
EGW_BROWSER_TYPE_NONE = 0;
|
|
|
|
EGW_BROWSER_TYPE_IFRAME = 1;
|
|
|
|
EGW_BROWSER_TYPE_DIV = 2;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Creates a new content browser ui, _heightCallback must either be a function
|
|
|
|
* or an egw_fw_class_callback object.
|
|
|
|
*/
|
|
|
|
function egw_fw_content_browser(_app, _heightCallback)
|
2010-06-09 20:36:14 +02:00
|
|
|
{
|
2010-06-21 11:08:41 +02:00
|
|
|
//Create a div which contains both, the legacy iframe and the contentDiv
|
|
|
|
this.baseDiv = document.createElement('div');
|
|
|
|
this.type = EGW_BROWSER_TYPE_NONE;
|
|
|
|
this.iframe = null;
|
|
|
|
this.contentDiv = null;
|
|
|
|
this.heightCallback = _heightCallback;
|
|
|
|
this.app = _app;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Resizes both, the contentDiv and the iframe to the size returned from the heightCallback
|
|
|
|
*/
|
|
|
|
egw_fw_content_browser.prototype.resize = function()
|
|
|
|
{
|
|
|
|
var height = this.heightCallback.call() + 'px';
|
|
|
|
|
|
|
|
//Set the height of the content div or the iframe
|
|
|
|
if (this.contentDiv)
|
|
|
|
{
|
|
|
|
this.contentDiv.style.height = height;
|
|
|
|
}
|
|
|
|
if (this.iframe)
|
|
|
|
{
|
|
|
|
this.iframe.style.height = height;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
egw_fw_content_browser.prototype.setBrowserType = function(_type)
|
|
|
|
{
|
|
|
|
//Only do anything if the browser type has changed
|
|
|
|
if (_type != this.type)
|
|
|
|
{
|
|
|
|
//Destroy the iframe and/or the contentDiv
|
|
|
|
$(this.baseDiv).empty();
|
|
|
|
this.iframe = null;
|
|
|
|
this.contentDiv = null;
|
|
|
|
this.ajaxLoaderDiv = null;
|
|
|
|
|
|
|
|
switch (_type)
|
|
|
|
{
|
|
|
|
//Create the div for displaying the content
|
|
|
|
case EGW_BROWSER_TYPE_DIV:
|
|
|
|
this.contentDiv = document.createElement('div');
|
|
|
|
$(this.contentDiv).addClass('egw_fw_content_browser_div');
|
|
|
|
$(this.baseDiv).append(this.contentDiv);
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case EGW_BROWSER_TYPE_IFRAME:
|
|
|
|
//Create the iframe
|
|
|
|
this.iframe = document.createElement('iframe');
|
|
|
|
this.iframe.style.width = "100%";
|
|
|
|
this.iframe.style.borderWidth = 0;
|
|
|
|
this.iframe.frameBorder = 0;
|
|
|
|
$(this.iframe).addClass('egw_fw_content_browser_iframe');
|
|
|
|
$(this.baseDiv).append(this.iframe);
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
this.resize();
|
|
|
|
this.type = _type;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
egw_fw_content_browser.prototype.browse = function(_url, _useIframe)
|
|
|
|
{
|
|
|
|
//Set the browser type
|
|
|
|
if (_useIframe)
|
2010-06-09 20:36:14 +02:00
|
|
|
{
|
2010-06-21 11:08:41 +02:00
|
|
|
this.setBrowserType(EGW_BROWSER_TYPE_IFRAME);
|
|
|
|
|
|
|
|
//Perform the actual "navigation"
|
|
|
|
this.iframe.src = _url;
|
|
|
|
|
|
|
|
//Set the "_legacy_iframe" flag to allow link handlers to easily determine
|
|
|
|
//the type of the link source
|
|
|
|
this.iframe.contentWindow._legacy_iframe = true;
|
2010-06-09 20:36:14 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-06-21 11:08:41 +02:00
|
|
|
this.setBrowserType(EGW_BROWSER_TYPE_DIV)
|
|
|
|
|
|
|
|
//Special treatement of "about:blank"
|
|
|
|
if (_url == "about:blank")
|
|
|
|
{
|
|
|
|
$(this.contentDiv).empty();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
//Perform an AJAX request loading application output
|
|
|
|
if (this.app.sidemenuEntry)
|
|
|
|
this.app.sidemenuEntry.showAjaxLoader();
|
|
|
|
var req = new egw_json_request(
|
|
|
|
this.app.appName + '.jdots_framework.ajax_exec',
|
|
|
|
[_url], this.contentDiv);
|
|
|
|
req.sendRequest(true, this.browse_callback, this);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
egw_fw_content_browser.prototype.browse_callback = function(_data)
|
|
|
|
{
|
|
|
|
if (this.app.sidemenuEntry)
|
|
|
|
this.app.sidemenuEntry.hideAjaxLoader();
|
|
|
|
$(this.contentDiv).empty();
|
|
|
|
$(this.contentDiv).append(_data);
|
|
|
|
// console.log(_data);
|
|
|
|
}
|
|
|
|
|
|
|
|
egw_fw_content_browser.prototype.reload = function()
|
|
|
|
{
|
|
|
|
switch (_type)
|
|
|
|
{
|
|
|
|
case EGW_BROWSER_TYPE_DIV:
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case EGW_BROWSER_TYPE_IFRAME:
|
|
|
|
//Do a simple reload in the iframe case
|
|
|
|
this.iframe.contentWindow.location.reload();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
egw_fw_content_browser.prototype.blank = function()
|
|
|
|
{
|
|
|
|
this.browse('about:blank', this.type = EGW_BROWSER_TYPE_IFRAME);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Global funcitons
|
|
|
|
*/
|
|
|
|
|
|
|
|
window.egw_link_handler = function(_link, _app)
|
|
|
|
{
|
|
|
|
//Determine where the link came from
|
|
|
|
var link_source = EGW_LINK_SOURCE_FRAMEWORK;
|
|
|
|
if (window.framework == 'undefined')
|
|
|
|
{
|
|
|
|
if (typeof window._legacy_iframe != 'undefined')
|
|
|
|
{
|
|
|
|
var link_source = EGW_LINK_SOURCE_LEGACY_IFRAME //1, iframe ==> legacy application
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
var link_source = EGW_LINK_SOURCE_POPUP; //2, popup
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//Default the application parameter to false
|
|
|
|
if (typeof _app == 'undefined')
|
|
|
|
{
|
|
|
|
_app = false;
|
|
|
|
}
|
2010-06-09 20:36:14 +02:00
|
|
|
|
2010-06-21 11:08:41 +02:00
|
|
|
//Default the _useIframe parameter to true
|
|
|
|
if (typeof _useIframe == 'undefined')
|
2010-06-09 20:36:14 +02:00
|
|
|
{
|
2010-06-21 11:08:41 +02:00
|
|
|
_useIframe = true;
|
2010-06-09 20:36:14 +02:00
|
|
|
}
|
2010-06-21 11:08:41 +02:00
|
|
|
|
|
|
|
var frmwrk = getFramework();
|
|
|
|
if (frmwrk != null)
|
2010-06-09 20:36:14 +02:00
|
|
|
{
|
2010-06-21 11:08:41 +02:00
|
|
|
frmwrk.linkHandler(_link, _app, link_source)
|
2010-06-09 20:36:14 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
window.location = _link;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
window.getFramework = function()
|
|
|
|
{
|
|
|
|
if (typeof window.framework != 'undefined')
|
|
|
|
{
|
|
|
|
return framework;
|
|
|
|
}
|
|
|
|
else if (typeof window.parent.getFramework != "undefined")
|
|
|
|
{
|
|
|
|
return window.parent.getFramework();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|