Synchronized jdots with trunk

This commit is contained in:
Andreas Stöckel 2010-06-16 14:57:04 +00:00
parent 9b6b5627aa
commit c01b280dea
13 changed files with 901 additions and 65 deletions

View File

@ -32,13 +32,10 @@ body {
position: fixed; position: fixed;
overflow: hidden; overflow: hidden;
left: 0px;
top: 0px; top: 0px;
left: 0px;
bottom: 20px; bottom: 20px;
width: 225px; /* width: 225px;*/
padding: 0px 4px 4px 4px;
margin: 0px 0px 0px 0px;
} }
#egw_divLogo { #egw_divLogo {
@ -65,9 +62,22 @@ body {
} }
#egw_fw_sidemenu { #egw_fw_sidemenu {
display: block; position: absolute;
width: 205px; top: 53px;
padding-top: 3px; bottom: 4px;
left: 4px;
right: 8px;
overflow: hidden;
z-index: 0;
}
#egw_fw_splitter {
position: absolute;
/* background-color: RGB(200, 200, 255);*/
/* width: 5px;*/
top: 53px;
bottom: 4px;
right: 6px;
} }
#egw_fw_topmenu { #egw_fw_topmenu {
@ -115,19 +125,18 @@ body {
} }
#egw_fw_main { #egw_fw_main {
margin-left: 225px; /* margin-left: 240px;*/
} }
#egw_fw_tabs { #egw_fw_tabs {
/* margin: 5px 5px 5px 0px; */ /* margin: 5px 5px 5px 0px;*/
} }
.egw_fw_ui_sidemenu_entry_header { .egw_fw_ui_sidemenu_entry_header {
display: block; display: block;
width: 195px;
height: 20px; height: 20px;
padding: 2px 5px 2px 5px; padding: 2px 5px 2px 5px;
margin: 0px 5px 0px 5px; margin: 0;
border-width: 0px 1px 0px 1px; border-width: 0px 1px 0px 1px;
border-style: solid; border-style: solid;
border-color: #c6ced6; border-color: #c6ced6;
@ -160,8 +169,9 @@ body {
} }
.egw_fw_ui_sidemenu_entry_content { .egw_fw_ui_sidemenu_entry_content {
width: 203px; /* width: 203px;*/
margin: 0px 5px 0px 5px; display: block;
margin: 0;
border-style: solid; border-style: solid;
border-color: #b4c5e6; border-color: #b4c5e6;
border-width: 2px; border-width: 2px;
@ -206,12 +216,28 @@ body {
float: right; float: right;
} }
.egw_fw_ui_sidemenu_entry_header h1 { .egw_fw_ui_sidemenu_entry_header h1, .egw_fw_ui_sidemenu_marker h1{
display: inline; display: inline;
font-size: 10pt; font-size: 10pt;
font-weight: bold; font-weight: bold;
} }
.egw_fw_ui_sidemenu_marker {
display: block;
height: 20px;
padding: 2px 5px 2px 34px;
margin: 0;
border-width: 0px 1px 0px 1px;
border-style: solid;
border-color: #c6ced6;
cursor: pointer;
color: gray;
background-color: RGB(250, 250, 250);
-moz-border-radius:5px;
-webkit-border-radius:5px;
border-radius:5px;
}
.egw_fw_ui_tab_header { .egw_fw_ui_tab_header {
-moz-border-radius-topright:3px; -moz-border-radius-topright:3px;
-webkit-border-top-right-radius:3px; -webkit-border-top-right-radius:3px;
@ -340,3 +366,82 @@ body {
height: 12px; height: 12px;
float: left; float: left;
} }
.egw_fw_ui_scrollarea
{
overflow: hidden;
z-index: 0;
}
.egw_fw_ui_scrollarea_button
{
position: absolute;
display: block;
width: 100%;
height: 12px;
z-index: 2;
}
.egw_fw_ui_scrollarea_button_up.egw_fw_ui_scrollarea_button_hover
{
background-image:url(images/gradient_scroll_up_hover.png);
}
.egw_fw_ui_scrollarea_button_down.egw_fw_ui_scrollarea_button_hover
{
background-image:url(images/gradient_scroll_down_hover.png);
}
.egw_fw_ui_scrollarea_button_disabled
{
display: none !important;
}
.egw_fw_ui_scrollarea_button_up
{
top: 0px;
background-image:url(images/gradient_scroll_up.png);
background-repeat: no-repeat;
background-position: center;
}
.egw_fw_ui_scrollarea_button_down
{
bottom: 0px;
background-image:url(images/gradient_scroll_down.png);
background-repeat: no-repeat;
background-position: center;
}
.egw_fw_ui_scrollarea_outerdiv
{
height: 100%;
}
.egw_fw_ui_splitter {
background-color: RGB(250, 250, 250);
}
.egw_fw_ui_splitter_hover {
background-color: RGB(220, 220, 220);
}
.egw_fw_ui_splitter_horizontal {
background-image:url(images/splitter_horz.png);
background-position:center;
background-repeat:no-repeat;
position: absolute;
width: 100%;
height: 5px;
cursor: row-resize;
}
.egw_fw_ui_splitter_vertical {
background-image:url(images/splitter_vert.png);
background-position:center;
background-repeat:no-repeat;
position: absolute;
width: 5px;
height: 100%;
cursor: col-resize;
}

View File

@ -30,5 +30,14 @@ $GLOBALS['settings'] = array(
'admin' => False, 'admin' => False,
'forced' => false, 'forced' => false,
), ),
'app_specific_sidebar_width' => array(
'type' => 'check',
'label' => 'Sidebar width stored for each application',
'name' => 'app_specific_sidebar_width',
'help' => 'When set, the width of the sidebar menu is not stored globaly but independently for each application',
'xmlrpc' => false,
'admin' => false,
'default'=> '0',
),
'navbar_format' => false, // not used in JDots (defined in common prefs) 'navbar_format' => false, // not used in JDots (defined in common prefs)
); );

Binary file not shown.

After

Width:  |  Height:  |  Size: 555 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 500 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 549 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 522 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 395 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 398 B

View File

@ -32,9 +32,77 @@ class jdots_framework extends egw_framework
function __construct($template='jdots') function __construct($template='jdots')
{ {
parent::__construct($template); // call the constructor of the extended class parent::__construct($template); // call the constructor of the extended class
$this->template_dir = '/jdots'; // we are packaged as an application $this->template_dir = '/jdots'; // we are packaged as an application
} }
/**
* Reads an returns the width of the sidebox or false if the width is not set
*/
private static function get_sidebar_width($app)
{
//If the global_sidebar_width option is set, we'll simply return false
if ($GLOBALS['egw_info']['user']['preferences']['common']['app_specific_sidebar_width'])
{
$width = 225;
//Check whether the width had been stored explicitly for the jdots template, use that value
if ($GLOBALS['egw_info']['user']['preferences'][$app]['jdotssideboxwidth'])
{
$width = (int)$GLOBALS['egw_info']['user']['preferences'][$app]['jdotssideboxwidth'];
// error_log(__METHOD__.__LINE__."($app):$width --> reading jdotssideboxwidth");
}
//Otherwise use the legacy "idotssideboxwidth" value
else if ($GLOBALS['egw_info']['user']['preferences'][$app]['idotssideboxwidth'])
{
$width = (int)$GLOBALS['egw_info']['user']['preferences'][$app]['idotssideboxwidth'];
// error_log(__METHOD__.__LINE__."($app):$width --> reading idotssideboxwidth");
}
//Width may not be smaller than 225
if ($width < 225)
$width = 225;
return $width;
}
return false;
}
/**
* Returns the global width of the sidebox. If the app_specific_sidebar_width had been switched
* on, the default width will be returned
*/
private static function get_global_sidebar_width()
{
if (!$GLOBALS['egw_info']['user']['preferences']['common']['app_specific_sidebar_width'] &&
$GLOBALS['egw_info']['user']['preferences']['common']['global_sidebar_width_value'])
{
return $GLOBALS['egw_info']['user']['preferences']['common']['global_sidebar_width_value'];
}
return 225;
}
/**
* Sets the sidebox width accoringly to the app_specific_sidebar_width setting, either
* in the current application or globaly
*/
private static function set_sidebar_width($app, $val)
{
$GLOBALS['egw']->preferences->read_repository();
if ($GLOBALS['egw_info']['user']['preferences']['common']['app_specific_sidebar_width'])
{
// error_log(__METHOD__.__LINE__."($app, $val) --> setting jdotssideboxwidth");
$GLOBALS['egw']->preferences->change($app, 'jdotssideboxwidth', $val);
}
else
{
// error_log(__METHOD__.__LINE__."($app, $val) --> setting global sidebar width value");
$GLOBALS['egw']->preferences->change('common', 'global_sidebar_width_value', $val);
}
$GLOBALS['egw']->preferences->save_repository(True);
}
/** /**
* Extract applicaton name from given url (incl. GET parameters) * Extract applicaton name from given url (incl. GET parameters)
@ -122,6 +190,7 @@ class jdots_framework extends egw_framework
if ($do_framework) if ($do_framework)
{ {
// framework javascript classes only need for framework // framework javascript classes only need for framework
self::validate_file('jquery','jquery-ui');
self::validate_file('.','egw_fw','jdots'); self::validate_file('.','egw_fw','jdots');
self::validate_file('.','egw_fw_ui','jdots'); self::validate_file('.','egw_fw_ui','jdots');
self::validate_file('.','egw_fw_classes','jdots'); self::validate_file('.','egw_fw_classes','jdots');
@ -215,6 +284,9 @@ class jdots_framework extends egw_framework
// hook after_navbar (eg. notifications) // hook after_navbar (eg. notifications)
$this->tpl->set_var('hook_after_navbar',$this->_get_after_navbar()); $this->tpl->set_var('hook_after_navbar',$this->_get_after_navbar());
//Global sidebar width
$this->tpl->set_var('sidebox_width', self::get_global_sidebar_width());
// add framework div's // add framework div's
$this->tpl->set_var($this->_get_footer()); $this->tpl->set_var($this->_get_footer());
$content .= $this->tpl->fp('out','framework'); $content .= $this->tpl->fp('out','framework');
@ -519,6 +591,46 @@ class jdots_framework extends egw_framework
$response->data($this->get_sidebox($appname)); $response->data($this->get_sidebox($appname));
} }
/**
* Stores the width of the sidebox menu depending on the sidebox menu settings
* @param $appname the name of the application
* @param $width the width set
*/
public function ajax_sideboxwidth($appname, $width)
{
error_log(__METHOD__."($appname, $width)");
//Check whether the supplied parameters are valid
if (is_int($width) && $GLOBALS['egw_info']['user']['apps'][$appname])
{
self::set_sidebar_width($appname, $width);
}
}
/**
* Stores the user defined sorting of the applications inside the preferences
*/
public function ajax_appsort($apps)
{
$order = array();
$i = 0;
//Parse the "$apps" array for valid content (security)
foreach($apps as $app)
{
//Check whether the app really exists and add it to the $app_arr var
if ($GLOBALS['egw_info']['user']['apps'][$app])
{
$order[$app] = $i;
$i++;
}
}
//Store the order array inside the common user preferences
$GLOBALS['egw']->preferences->read_repository();
$GLOBALS['egw']->preferences->change('common', 'user_apporder', serialize($order));
$GLOBALS['egw']->preferences->save_repository(true);
}
/** /**
* Prepare an array with apps used to render the navbar * Prepare an array with apps used to render the navbar
* *
@ -536,6 +648,12 @@ class jdots_framework extends egw_framework
{ {
$apps = parent::_get_navbar_apps(); $apps = parent::_get_navbar_apps();
//Add its sidebox width to each app
foreach ($apps as $key => $value)
{
$apps[$key]['sideboxwidth'] = self::get_sidebar_width($key);
}
unset($apps['logout']); // never display it unset($apps['logout']); // never display it
if (isset($apps['about'])) $apps['about']['noNavbar'] = true; if (isset($apps['about'])) $apps['about']['noNavbar'] = true;
if (isset($apps['preferences'])) $apps['preferences']['noNavbar'] = true; if (isset($apps['preferences'])) $apps['preferences']['noNavbar'] = true;

View File

@ -21,12 +21,15 @@
* @param string _tabsId specifies the name of the div container which should cotain the tab area * @param string _tabsId specifies the name of the div container which should cotain the tab area
* @param string _webserverUrl specifies the egroupware root url * @param string _webserverUrl specifies the egroupware root url
*/ */
function egw_fw(_sidemenuId, _tabsId, _webserverUrl) function egw_fw(_sidemenuId, _tabsId, _splitterId, _webserverUrl, _sideboxSizeCallback,
_sideboxStartSize)
{ {
/* Get the base div */ /* Get the base div */
this.sidemenuDiv = document.getElementById(_sidemenuId); this.sidemenuDiv = document.getElementById(_sidemenuId);
this.tabsDiv = document.getElementById(_tabsId); this.tabsDiv = document.getElementById(_tabsId);
this.splitterDiv = document.getElementById(_splitterId);
this.webserverUrl = _webserverUrl; this.webserverUrl = _webserverUrl;
this.sideboxSizeCallback = _sideboxSizeCallback;
window.egw_webserverUrl = _webserverUrl; window.egw_webserverUrl = _webserverUrl;
this.sidemenuUi = null; this.sidemenuUi = null;
@ -37,15 +40,31 @@ function egw_fw(_sidemenuId, _tabsId, _webserverUrl)
this.applications = new Object(); this.applications = new Object();
this.activeApp = null; this.activeApp = null;
if (this.sidemenuDiv && this.tabsDiv) if (this.sidemenuDiv && this.tabsDiv && this.splitterDiv)
{ {
//Create the sidemenu and the tabs area //Wrap a scroll area handler around the applications
this.sidemenuUi = new egw_fw_ui_sidemenu(this.sidemenuDiv); 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);
this.tabsUi = new egw_fw_ui_tabs(this.tabsDiv); this.tabsUi = new egw_fw_ui_tabs(this.tabsDiv);
this.splitterUi = new egw_fw_ui_splitter(this.splitterDiv,
EGW_SPLITTER_VERTICAL, this.splitterResize,
[
{
"size": _sideboxStartSize,
"minsize": 225,
"maxsize": 0
},
], this);
this.loadApplications("home.jdots_framework.ajax_navbar_apps"); this.loadApplications("home.jdots_framework.ajax_navbar_apps");
} }
_sideboxSizeCallback(_sideboxStartSize);
//Register the resize handler //Register the resize handler
$(window).resize(function(){window.framework.resizeHandler()}); $(window).resize(function(){window.framework.resizeHandler()});
@ -97,6 +116,97 @@ egw_fw.prototype.keyPressHandler = function(event)
} }
} }
/**
* 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);
}
/** /**
* tabCloseClickCallback is used internally by egw_fw in order to handle clicks * tabCloseClickCallback is used internally by egw_fw in order to handle clicks
* on the close button of every tab. * on the close button of every tab.
@ -116,8 +226,8 @@ egw_fw.prototype.tabCloseClickCallback = function(_sender)
app.tab = null; app.tab = null;
app.iframe = null; app.iframe = null;
//Activate the new application in the sidebar menu //Set the active application to the application of the currently active tab
app.parentFw.sidemenuUi.open(tabsUi.activeTab.tag.sidemenuEntry); app.parentFw.setActiveApp(tabsUi.activeTab.tag);
} }
tabsUi.setCloseable(tabsUi.tabs.length > 1); tabsUi.setCloseable(tabsUi.tabs.length > 1);
@ -134,6 +244,8 @@ egw_fw.prototype.resizeHandler = function()
{ {
this.applications[app].iframe.style.height = this.getIFrameHeight() + 'px'; this.applications[app].iframe.style.height = this.getIFrameHeight() + 'px';
} }
this.scrollAreaUi.update();
} }
} }
@ -152,12 +264,8 @@ egw_fw.prototype.getIFrameHeight = function()
*/ */
egw_fw.prototype.tabClickCallback = function(_sender) egw_fw.prototype.tabClickCallback = function(_sender)
{ {
this.parent.showTab(this); //Set the active application in the framework
this.tag.parentFw.sidemenuUi.open(this.tag.sidemenuEntry); this.tag.parentFw.setActiveApp(this.tag);
document.title = this.tag.website_title ? this.tag.website_title : this.tag.appName;
//Set this application as the active application
this.tag.parentFw.activeApp = this.tag;
} }
/** /**
@ -202,24 +310,7 @@ egw_fw.prototype.applicationTabNavigate = function(_app, _url)
//Set the iframe location //Set the iframe location
_app.iframe.src = typeof(_url) == "undefined" ? _app.execName : _url; _app.iframe.src = typeof(_url) == "undefined" ? _app.execName : _url;
//Set this application as the active application _app.parentFw.setActiveApp(_app);
_app.parentFw.activeApp = _app;
//Show the tab
this.tabsUi.showTab(_app.tab);
if (_app.sidemenuEntry != null)
{
//Open the sidemenu entry content
if (_app.hasSideboxMenuContent)
{
_app.sidemenuEntry.parent.open(_app.sidemenuEntry);
}
}
else
{
_app.parentFw.sidemenuUi.open(null);
}
} }
/** /**
@ -248,7 +339,7 @@ egw_fw.prototype.loadApplicationsCallback = function(apps)
var app = apps[i]; var app = apps[i];
appData = new egw_fw_class_application(this, appData = new egw_fw_class_application(this,
app.name, app.title, app.icon, app.url); app.name, app.title, app.icon, app.url, app.sideboxwidth);
//Create a sidebox menu entry for each application //Create a sidebox menu entry for each application
if (!app.noNavbar) if (!app.noNavbar)
@ -282,6 +373,8 @@ egw_fw.prototype.loadApplicationsCallback = function(apps)
{ {
this.applicationTabNavigate(defaultApp); this.applicationTabNavigate(defaultApp);
} }
this.scrollAreaUi.update();
} }
/** /**
@ -359,6 +452,12 @@ egw_fw.prototype.categoryOpenCloseCallback = function(_opened)
/* Store the state of the category lokaly */ /* Store the state of the category lokaly */
this.tag.parentFw.categoryOpenCache[this.tag.appName + '#' + this.catName] = _opened; this.tag.parentFw.categoryOpenCache[this.tag.appName + '#' + this.catName] = _opened;
// this.tag.parentFw.scrollAreaUi.update();
}
egw_fw.prototype.categoryAnimationCallback = function()
{
this.tag.parentFw.scrollAreaUi.update();
} }
/** /**
@ -415,7 +514,8 @@ egw_fw.prototype.setSidebox = function(_app, _data, _md5)
if (catContent != '') if (catContent != '')
{ {
var categoryUi = new egw_fw_ui_category(contDiv,_data[i].menu_name, var categoryUi = new egw_fw_ui_category(contDiv,_data[i].menu_name,
_data[i].title, catContent, this.categoryOpenCloseCallback, _app); _data[i].title, catContent, this.categoryOpenCloseCallback,
this.categoryAnimationCallback, _app);
//Lookup whether this entry was opened before. If no data is //Lookup whether this entry was opened before. If no data is
//stored about this, use the information we got from the server //stored about this, use the information we got from the server
@ -442,6 +542,9 @@ egw_fw.prototype.setSidebox = function(_app, _data, _md5)
_app.hasSideboxMenuContent = true; _app.hasSideboxMenuContent = true;
_app.sidemenuEntry.parent.open(_app.sidemenuEntry); _app.sidemenuEntry.parent.open(_app.sidemenuEntry);
_app.parentFw.scrollAreaUi.update();
_app.parentFw.scrollAreaUi.setScrollPos(0);
} }
} }

View File

@ -10,7 +10,8 @@
Class egw_fw_class_application Class egw_fw_class_application
----------------------------*/ ----------------------------*/
function egw_fw_class_application(_parentFw, _appName, _displayName, _icon, _execName) function egw_fw_class_application(_parentFw, _appName, _displayName, _icon,
_execName, _sideboxWidth)
{ {
//Copy the application properties //Copy the application properties
this.appName = _appName; this.appName = _appName;
@ -19,6 +20,8 @@ function egw_fw_class_application(_parentFw, _appName, _displayName, _icon, _exe
this.execName = _execName; this.execName = _execName;
this.sidebox_md5 = ''; this.sidebox_md5 = '';
this.sideboxWidth = _sideboxWidth;
//Setup a link to the parent framework class //Setup a link to the parent framework class
this.parentFw = _parentFw; this.parentFw = _parentFw;

View File

@ -26,14 +26,17 @@
* @param function(_sender) _callback specifies the function which should be called when the entry is clicked. The _sender parameter passed is a reference to this egw_fw_ui_sidemenu_entry element. * @param function(_sender) _callback specifies the function which should be called when the entry is clicked. The _sender parameter passed is a reference to this egw_fw_ui_sidemenu_entry element.
* @param object _tag can be used to attach any user data to the object. Inside egw_fw _tag is used to attach an egw_fw_class_application to each sidemenu entry. * @param object _tag can be used to attach any user data to the object. Inside egw_fw _tag is used to attach an egw_fw_class_application to each sidemenu entry.
*/ */
function egw_fw_ui_sidemenu_entry(_parent, _baseDiv, _name, _icon, _callback, _tag) function egw_fw_ui_sidemenu_entry(_parent, _baseDiv, _elemDiv, _name, _icon, _callback,
_tag)
{ {
this.baseDiv = _baseDiv; this.baseDiv = _baseDiv;
this.elemDiv = _elemDiv;
this.entryName = _name; this.entryName = _name;
this.icon = _icon; this.icon = _icon;
this.tag = _tag; this.tag = _tag;
this.parent = _parent; this.parent = _parent;
this.atTop = false; this.atTop = false;
this.isDraged = false;
//Add a new div for the new entry to the base div //Add a new div for the new entry to the base div
this.headerDiv = document.createElement("div"); this.headerDiv = document.createElement("div");
@ -58,9 +61,13 @@ function egw_fw_ui_sidemenu_entry(_parent, _baseDiv, _name, _icon, _callback, _t
$(this.headerDiv).append(iconDiv); $(this.headerDiv).append(iconDiv);
$(this.headerDiv).append(entryH1); $(this.headerDiv).append(entryH1);
$(this.headerDiv).append(this.ajaxloader); $(this.headerDiv).append(this.ajaxloader);
this.headerDiv._parent = this;
this.headerDiv._callbackObject = new egw_fw_class_callback(this, _callback); this.headerDiv._callbackObject = new egw_fw_class_callback(this, _callback);
$(this.headerDiv).click(function(){ $(this.headerDiv).click(function(){
this._callbackObject.call(this); if (!this._parent.isDraged)
this._callbackObject.call(this);
this._parent.isDraged = false;
return true;
}); });
//Create the content div //Create the content div
@ -72,12 +79,48 @@ function egw_fw_ui_sidemenu_entry(_parent, _baseDiv, _name, _icon, _callback, _t
//Add in invisible marker to store the original position of this element in the DOM tree //Add in invisible marker to store the original position of this element in the DOM tree
this.marker = document.createElement("div"); this.marker = document.createElement("div");
this.marker._parent = this;
this.marker.className = 'egw_fw_ui_sidemenu_marker';
var entryH1 = document.createElement("h1");
$(entryH1).append(this.entryName);
$(this.marker).append(entryH1);
$(this.marker).hide(); $(this.marker).hide();
//Create a container which contains all generated elements and is then added
//to the baseDiv
this.containerDiv = document.createElement("div");
this.containerDiv._parent = this;
$(this.containerDiv).append(this.marker);
$(this.containerDiv).append(this.headerDiv);
$(this.containerDiv).append(this.contentDiv);
//Append header and content div to the base div //Append header and content div to the base div
$(this.baseDiv).append(this.marker); $(this.elemDiv).append(this.containerDiv);
$(this.baseDiv).append(this.headerDiv);
$(this.baseDiv).append(this.contentDiv); //Make the base Div sortable. Set all elements with the style "egw_fw_ui_sidemenu_entry_header"
//as handle
$(this.elemDiv).sortable("destroy");
$(this.elemDiv).sortable({
handle: ".egw_fw_ui_sidemenu_entry_header",
distance: 15,
start: function(event, ui)
{
var parent = ui.item.context._parent;
parent.isDraged = true;
parent.parent.startDrag.call(parent.parent);
},
stop: function(event, ui)
{
var parent = ui.item.context._parent;
parent.parent.stopDrag.call(parent.parent);
parent.parent.refreshSort.call(parent.parent);
},
opacity: 0.7,
// appendTo: 'body',
// helper: 'clone',
axis: 'y'
});
} }
/** /**
@ -143,7 +186,7 @@ egw_fw_ui_sidemenu_entry.prototype.close = function()
$(this.contentDiv).hide(); $(this.contentDiv).hide();
} }
/** /**egw_fw_ui_sidemenu_entry_header_active
* showAjaxLoader shows the AjaxLoader animation which should be displayed when * showAjaxLoader shows the AjaxLoader animation which should be displayed when
* the content of the sidemenu entry is just being loaded. * the content of the sidemenu entry is just being loaded.
*/ */
@ -181,10 +224,65 @@ egw_fw_ui_sidemenu_entry.prototype.remove = function()
* *
* @param object _baseDiv specifies the "div" in which all entries added by the addEntry function should be displayed. * @param object _baseDiv specifies the "div" in which all entries added by the addEntry function should be displayed.
*/ */
function egw_fw_ui_sidemenu(_baseDiv) function egw_fw_ui_sidemenu(_baseDiv, _sortCallback)
{ {
this.baseDiv = _baseDiv; this.baseDiv = _baseDiv;
this.elemDiv = document.createElement('div');
this.sortCallback = _sortCallback;
$(this.baseDiv).append(this.elemDiv);
this.entries = new Array(); this.entries = new Array();
this.activeEntry = null;
}
/**
* Funtion used internally to recursively step through a dom tree and add all appliction
* markers in their order of appereance
*/
egw_fw_ui_sidemenu.prototype._searchMarkers = function(_resultArray, _children)
{
for (var i = 0; i < _children.length; i++)
{
var child = _children[i];
if (child.className == 'egw_fw_ui_sidemenu_marker' && typeof child._parent != 'undefined')
{
_resultArray.push(child._parent);
}
this._searchMarkers(_resultArray, child.childNodes);
}
}
egw_fw_ui_sidemenu.prototype.startDrag = function()
{
if (this.activeEntry)
{
$(this.activeEntry.marker).show();
$(this.elemDiv).sortable("refresh");
}
}
egw_fw_ui_sidemenu.prototype.stopDrag = function()
{
if (this.activeEntry)
{
$(this.activeEntry.marker).hide();
$(this.elemDiv).sortable("refresh");
}
}
/**
* Called by the sidemenu elements whenever they were sorted. An array containing
* the sidemenu_entries ui-objects is generated and passed to the sort callback
*/
egw_fw_ui_sidemenu.prototype.refreshSort = function()
{
//Step through all children of elemDiv and add all markers to the result array
var resultArray = new Array();
this._searchMarkers(resultArray, this.elemDiv.childNodes);
//Call the sort callback with the array containing the sidemenu_entries
this.sortCallback(resultArray);
} }
/** /**
@ -197,9 +295,10 @@ function egw_fw_ui_sidemenu(_baseDiv)
egw_fw_ui_sidemenu.prototype.addEntry = function(_name, _icon, _callback, _tag) egw_fw_ui_sidemenu.prototype.addEntry = function(_name, _icon, _callback, _tag)
{ {
//Create a new sidemenu entry and add it to the list //Create a new sidemenu entry and add it to the list
var entry = new egw_fw_ui_sidemenu_entry(this, this.baseDiv, _name, _icon, _callback, _tag); var entry = new egw_fw_ui_sidemenu_entry(this, this.baseDiv, this.elemDiv, _name, _icon,
_callback, _tag);
this.entries[this.entries.length] = entry; this.entries[this.entries.length] = entry;
return entry; return entry;
} }
@ -223,6 +322,8 @@ egw_fw_ui_sidemenu.prototype.open = function(_entry)
{ {
_entry.open(); _entry.open();
} }
this.activeEntry = _entry;
} }
@ -286,9 +387,10 @@ function egw_fw_ui_tab(_parent, _contHeaderDiv, _contDiv, _icon, _callback,
if (!$(this).hasClass("egw_fw_ui_tab_header_active")) if (!$(this).hasClass("egw_fw_ui_tab_header_active"))
$(this).addClass("egw_fw_ui_tab_header_hover"); $(this).addClass("egw_fw_ui_tab_header_hover");
}, },
function() {http://localhost/egroupware/index.php?menuaction=addressbook.addressbook_ui.index function() {var parent = ui.item.context._parent;
$(this).removeClass("egw_fw_ui_tab_header_hover") $(this).removeClass("egw_fw_ui_tab_header_hover")
}); }
);
//Create the icon and append it to the header div //Create the icon and append it to the header div
var icon = document.createElement("img"); var icon = document.createElement("img");
@ -574,12 +676,13 @@ egw_fw_ui_tabs.prototype.clean = function()
*/ */
function egw_fw_ui_category(_contDiv, _name, _title, _content, _callback, _tag) function egw_fw_ui_category(_contDiv, _name, _title, _content, _callback, _animationCallback, _tag)
{ {
//Copy the parameters //Copy the parameters
this.contDiv = _contDiv; this.contDiv = _contDiv;
this.catName = _name; this.catName = _name;
this.callback = _callback; this.callback = _callback;
this.animationCallback = _animationCallback;
this.tag = _tag; this.tag = _tag;
//Create the ui divs //Create the ui divs
@ -593,6 +696,7 @@ function egw_fw_ui_category(_contDiv, _name, _title, _content, _callback, _tag)
//Add the content //Add the content
this.contentDiv = document.createElement('div'); this.contentDiv = document.createElement('div');
this.contentDiv._parent = this;
$(this.contentDiv).addClass('egw_fw_ui_category_content'); $(this.contentDiv).addClass('egw_fw_ui_category_content');
$(this.contentDiv).append(_content); $(this.contentDiv).append(_content);
$(this.contentDiv).hide(); $(this.contentDiv).hide();
@ -622,10 +726,13 @@ egw_fw_ui_category.prototype.open = function(_instantly)
if (_instantly) if (_instantly)
{ {
$(this.contentDiv).show(); $(this.contentDiv).show();
this.animationCallback();
} }
else else
{ {
$(this.contentDiv).slideDown(); $(this.contentDiv).slideDown(200, function() {
this._parent.animationCallback.call(this._parent);
});
} }
} }
@ -637,10 +744,13 @@ egw_fw_ui_category.prototype.close = function(_instantly)
if (_instantly) if (_instantly)
{ {
$(this.contentDiv).hide(); $(this.contentDiv).hide();
this.animationCallback();
} }
else else
{ {
$(this.contentDiv).slideUp(); $(this.contentDiv).slideUp(200, function() {
this._parent.animationCallback.call(this._parent);
});
} }
} }
@ -651,3 +761,383 @@ egw_fw_ui_category.prototype.remove = function()
$(this.headerDiv).remove(); $(this.headerDiv).remove();
} }
/**
* egw_fw_ui_scrollarea class
*/
function egw_fw_ui_scrollarea(_contDiv)
{
this.startScrollSpeed = 50.0; //in px/sec
this.endScrollSpeed = 250.0; //in px/sec
this.scrollSpeedAccel = 75.0; //in px/sec^2
this.timerInterval = 0.04; //in seconds //20ms is the timer base timer resolution on windows systems
this.contDiv = _contDiv;
this.contHeight = 0;
this.boxHeight = 0;
this.scrollPos = 0;
this.buttonScrollOffs = 0;
this.maxScrollPos = 0;
this.buttonsVisible = true;
this.mouseOver = false;
this.scrollTime = 0.0;
this.btnUpEnabled = true;
this.btnDownEnabled = true;
//Wrap a new "scroll" div around the content of the content div
this.scrollDiv = document.createElement("div");
this.scrollDiv.style.position = "relative";
$(this.scrollDiv).addClass("egw_fw_ui_scrollarea");
//Create a container which contains the up/down buttons and the scrollDiv
this.outerDiv = document.createElement("div");
$(this.outerDiv).addClass("egw_fw_ui_scrollarea_outerdiv");
$(this.outerDiv).append(this.scrollDiv);
$(this.contDiv).children().appendTo(this.scrollDiv);
$(this.contDiv).append(this.outerDiv);
this.contentDiv = this.scrollDiv;
//Create the "up" and the "down" button
this.btnUp = document.createElement("span");
$(this.btnUp).addClass("egw_fw_ui_scrollarea_button");
$(this.btnUp).addClass("egw_fw_ui_scrollarea_button_up");
$(this.btnUp).hide();
this.btnUp._parent = this;
$(this.btnUp).mouseenter(function(){
this._parent.mouseOverToggle(true, -1);
$(this).addClass("egw_fw_ui_scrollarea_button_hover");
});
$(this.btnUp).click(function(){
this._parent.setScrollPos(0);
});
$(this.btnUp).mouseleave(function(){
this._parent.mouseOverToggle(false, -1);
$(this).removeClass("egw_fw_ui_scrollarea_button_hover");
});
$(this.outerDiv).prepend(this.btnUp);
this.btnDown = document.createElement("span");
$(this.btnDown).addClass("egw_fw_ui_scrollarea_button");
$(this.btnDown).addClass("egw_fw_ui_scrollarea_button_down");
$(this.btnDown).hide();
this.btnDown._parent = this;
$(this.btnDown).mouseenter(function(){
this._parent.mouseOverToggle(true, 1);
$(this).addClass("egw_fw_ui_scrollarea_button_hover");
});
$(this.btnDown).click(function() {
this._parent.setScrollPos(this._parent.maxScrollPos);
});
$(this.btnDown).mouseleave(function(){
this._parent.mouseOverToggle(false, 1);
$(this).removeClass("egw_fw_ui_scrollarea_button_hover");
});
$(this.outerDiv).prepend(this.btnDown);
//Update - read height of the children elements etc.
this.update();
}
egw_fw_ui_scrollarea.prototype.setScrollPos = function(_pos)
{
if (this.buttonsVisible)
{
if (_pos <= 0)
{
if (this.btnUpEnabled)
$(this.btnUp).addClass("egw_fw_ui_scrollarea_button_disabled");
if (!this.btnDownEnabled)
$(this.btnDown).removeClass("egw_fw_ui_scrollarea_button_disabled");
this.btnDownEnabled = true;
this.btnUpEnabled = false;
_pos = 0;
}
else if (_pos >= this.maxScrollPos)
{
if (this.btnDownEnabled)
$(this.btnDown).addClass("egw_fw_ui_scrollarea_button_disabled");
if (!this.btnUpEnabled)
$(this.btnUp).removeClass("egw_fw_ui_scrollarea_button_disabled");
this.btnDownEnabled = false;
this.btnUpEnabled = true;
_pos = this.maxScrollPos;
}
else
{
if (!this.btnUpEnabled)
$(this.btnUp).removeClass("egw_fw_ui_scrollarea_button_disabled");
if (!this.btnDownEnabled)
$(this.btnDown).removeClass("egw_fw_ui_scrollarea_button_disabled");
this.btnUpEnabled = true;
this.btnDownEnabled = true;
}
this.scrollPos = _pos;
//Apply the calculated scroll position to the scrollDiv
this.scrollDiv.style.top = Math.round(-_pos) + 'px';
}
}
egw_fw_ui_scrollarea.prototype.scrollDelta = function(_delta)
{
this.setScrollPos(this.scrollPos + _delta);
}
egw_fw_ui_scrollarea.prototype.toggleButtons = function(_visible)
{
if (_visible)
{
$(this.btnDown).show();
$(this.btnUp).show();
this.buttonHeight = $(this.btnDown).outerHeight();
this.maxScrollPos = this.contHeight - this.boxHeight;
this.setScrollPos(this.scrollPos);
}
else
{
this.scrollDiv.style.top = '0';
$(this.btnDown).hide();
$(this.btnUp).hide();
}
this.buttonsVisible = _visible;
}
egw_fw_ui_scrollarea.prototype.update = function()
{
//Get the height of the content and the outer box
this.contHeight = $(this.scrollDiv).outerHeight();
this.boxHeight = $(this.outerDiv).height();
this.toggleButtons(this.contHeight > this.boxHeight);
this.setScrollPos(this.scrollPos);
}
egw_fw_ui_scrollarea.prototype.getScrollDelta = function(_timeGap)
{
//Calculate the current scroll speed
var curScrollSpeed = this.startScrollSpeed + this.scrollSpeedAccel * this.scrollTime;
if (curScrollSpeed > this.endScrollSpeed)
{
curScrollSpeed = this.endScrollSpeed;
}
//Increment the scroll time counter
this.scrollTime = this.scrollTime + _timeGap;
//Return the actual delta value
return curScrollSpeed * _timeGap;
}
egw_fw_ui_scrollarea.prototype.mouseOverCallback = function(_context)
{
//Do the scrolling
_context.scrollDelta(_context.getScrollDelta(_context.timerInterval) *
_context.dir);
if (_context.mouseOver)
{
//Set the next timeout
window.setTimeout(_context.mouseOverCallback, Math.round(_context.timerInterval * 1000),
_context);
}
}
egw_fw_ui_scrollarea.prototype.mouseOverToggle = function(_over, _dir)
{
this.mouseOver = _over;
this.dir = _dir;
if (_over)
{
window.setTimeout(this.mouseOverCallback, Math.round(this.timerInterval * 1000),
this);
}
else
{
this.scrollTime = 0.0;
}
}
/**
* egw_fw_ui_splitter class
*/
var EGW_SPLITTER_HORIZONTAL = 0;
var EGW_SPLITTER_VERTICAL = 1;
function egw_fw_ui_splitter(_contDiv, _orientation, _resizeCallback, _constraints, _tag)
{
//Copy the parameters
this.tag = _tag;
this.contDiv = _contDiv;
this.orientation = _orientation;
this.resizeCallback = _resizeCallback;
this.startPos = 0;
this.constraints =
[
{
"size": 0,
"minsize": 0,
"maxsize": 0
},
{
"size": 0,
"minsize": 0,
"maxsize": 0
}
];
//Copy the given constraints parameter, keeping the default values set above
if (_constraints.constructor == Array)
{
for (var i = 0; i < 2; i++)
{
if (typeof _constraints[i] != 'undefined')
{
if (typeof _constraints[i].size != 'undefined')
this.constraints[i].size = _constraints[i].size;
if (typeof _constraints[i].minsize != 'undefined')
this.constraints[i].minsize = _constraints[i].minsize;
if (typeof _constraints[i].maxsize != 'undefined')
this.constraints[i].maxsize = _constraints[i].maxsize;
}
}
}
//Create the actual splitter div
this.splitterDiv = document.createElement('div');
this.splitterDiv._parent = this;
$(this.splitterDiv).addClass("egw_fw_ui_splitter");
//Setup the options for the dragable object
var dragoptions = {
opacity: 0.7,
helper: 'clone',
start: function(event, ui) {
return this._parent.dragStartHandler.call(this._parent, event, ui);
},
drag: function(event, ui) {
return this._parent.dragHandler.call(this._parent, event, ui);
},
stop: function(event, ui) {
return this._parent.dragStopHandler.call(this._parent, event, ui);
},
containment: 'document',
appendTo: 'body',
axis: 'y',
iframeFix: true,
zIndex: 10000
};
switch (this.orientation)
{
case EGW_SPLITTER_HORIZONTAL:
dragoptions.axis = 'y';
$(this.splitterDiv).addClass("egw_fw_ui_splitter_horizontal");
break;
case EGW_SPLITTER_VERTICAL:
dragoptions.axis = 'x';
$(this.splitterDiv).addClass("egw_fw_ui_splitter_vertical");
break;
}
$(this.splitterDiv).draggable(dragoptions);
//Handle mouse hovering of the splitter div
$(this.splitterDiv).mouseenter(function() {
$(this).addClass("egw_fw_ui_splitter_hover");
});
$(this.splitterDiv).mouseleave(function() {
$(this).removeClass("egw_fw_ui_splitter_hover");
});
$(this.contDiv).append(this.splitterDiv);
}
egw_fw_ui_splitter.prototype.clipDelta = function(_delta)
{
var result = _delta;
for (var i = 0; i < 2; i++)
{
var mul = (i == 0) ? 1 : -1;
if (this.constraints[i].maxsize > 0)
{
var size = this.constraints[i].size + mul * result;
if (size > this.constraints[i].maxsize)
result += mul * (this.constraints[i].maxsize - size);
}
if (this.constraints[i].minsize > 0)
{
var size = this.constraints[i].size + mul * result;
if (size < this.constraints[i].minsize)
result += mul * (this.constraints[i].minsize - size);
}
}
return result;
}
egw_fw_ui_splitter.prototype.dragStartHandler = function(event, ui)
{
switch (this.orientation)
{
case EGW_SPLITTER_HORIZONTAL:
this.startPos = ui.offset.top;
break;
case EGW_SPLITTER_VERTICAL:
this.startPos = ui.offset.left;
break;
}
}
egw_fw_ui_splitter.prototype.dragHandler = function(event, ui)
{
/* var delta = 0;
switch (this.orientation)
{
case EGW_SPLITTER_HORIZONTAL:
var old = ui.offset.top - this.startPos;
clipped = this.clipDelta(old);
$(this.splitterDiv).data('draggable').offset.click.top += (old - clipped);
break;
case EGW_SPLITTER_VERTICAL:
var old = ui.offset.left - this.startPos;
clipped = this.clipDelta(old);
$(this.splitterDiv).data('draggable').offset.click.left += (old - clipped);
break;
}*/
}
egw_fw_ui_splitter.prototype.dragStopHandler = function(event, ui)
{
var delta = 0;
switch (this.orientation)
{
case EGW_SPLITTER_HORIZONTAL:
delta = ui.offset.top - this.startPos;
break;
case EGW_SPLITTER_VERTICAL:
delta = ui.offset.left - this.startPos;
break;
}
//Clip the delta value
delta = this.clipDelta(delta);
this.constraints[0].size += delta;
this.constraints[1].size -= delta;
this.resizeCallback(this.constraints[0].size, this.constraints[1].size);
}

View File

@ -25,12 +25,13 @@
{include_wz_tooltip} {include_wz_tooltip}
<!-- END head --> <!-- END head -->
<!-- BEGIN framework --> <!-- BEGIN framework -->
{hook_after_navbar}
<div id="egw_fw_basecontainer"> <div id="egw_fw_basecontainer">
<div id="egw_fw_sidebar"> <div id="egw_fw_sidebar">
<div id="egw_divLogo"><a href="{logo_url}" target="_blank"><img src="{logo_file}" title="{logo_title}" alt="EGroupware"/></a></div> <div id="egw_divLogo"><a href="{logo_url}" target="_blank"><img src="{logo_file}" title="{logo_title}" alt="EGroupware"/></a></div>
<div id="egw_fw_sidemenu"></div> <div id="egw_fw_sidemenu"></div>
<div id="egw_fw_splitter"></div>
</div> </div>
{hook_after_navbar}
<div id="egw_fw_main"> <div id="egw_fw_main">
<div id="egw_fw_topmenu"> <div id="egw_fw_topmenu">
<div id="egw_fw_topmenu_items">{topmenu_items}</div> <div id="egw_fw_topmenu_items">{topmenu_items}</div>
@ -45,8 +46,15 @@
var var
framework = null; framework = null;
function egw_setSideboxSize(_size)
{
document.getElementById('egw_fw_main').style.marginLeft = _size + 'px';
document.getElementById('egw_fw_sidebar').style.width = _size + 'px';
}
$(document).ready(function() { $(document).ready(function() {
framework = new egw_fw("egw_fw_sidemenu", "egw_fw_tabs", "{webserver_url}"); framework = new egw_fw("egw_fw_sidemenu", "egw_fw_tabs", "egw_fw_splitter",
"{webserver_url}", egw_setSideboxSize, {sidebox_width});
} }
); );
</script> </script>